{"id":34852904,"url":"https://github.com/instamatic-dev/pyserialem","last_synced_at":"2025-12-25T19:29:49.727Z","repository":{"id":48284338,"uuid":"255877497","full_name":"instamatic-dev/pyserialem","owner":"instamatic-dev","description":"Python module to read/write SerialEM navigator files.","archived":false,"fork":false,"pushed_at":"2023-01-17T16:34:51.000Z","size":165,"stargazers_count":9,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2023-10-20T20:24:18.720Z","etag":null,"topics":["electron-microscopy","navigator","python","serialem"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/instamatic-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-15T10:06:16.000Z","updated_at":"2023-07-01T03:18:27.000Z","dependencies_parsed_at":"2023-02-10T10:45:14.539Z","dependency_job_id":null,"html_url":"https://github.com/instamatic-dev/pyserialem","commit_stats":null,"previous_names":[],"tags_count":8,"template":null,"template_full_name":null,"purl":"pkg:github/instamatic-dev/pyserialem","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instamatic-dev%2Fpyserialem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instamatic-dev%2Fpyserialem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instamatic-dev%2Fpyserialem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instamatic-dev%2Fpyserialem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/instamatic-dev","download_url":"https://codeload.github.com/instamatic-dev/pyserialem/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/instamatic-dev%2Fpyserialem/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28035564,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-25T02:00:05.988Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["electron-microscopy","navigator","python","serialem"],"created_at":"2025-12-25T19:29:46.312Z","updated_at":"2025-12-25T19:29:49.718Z","avatar_url":"https://github.com/instamatic-dev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![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/instamatic-dev/pyserialem\n[serialem]: https://bio3d.colorado.edu/SerialEM/\n[serialem_nav]: https://bio3d.colorado.edu/SerialEM/hlp/html/about_formats.htm\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finstamatic-dev%2Fpyserialem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finstamatic-dev%2Fpyserialem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finstamatic-dev%2Fpyserialem/lists"}