{"id":25237183,"url":"https://github.com/guiwitz/microfilm","last_synced_at":"2026-02-21T00:01:48.390Z","repository":{"id":38110244,"uuid":"356305900","full_name":"guiwitz/microfilm","owner":"guiwitz","description":"Creating figures and animations for multi-channel images with a focus on microscopy.","archived":false,"fork":false,"pushed_at":"2024-12-16T14:23:00.000Z","size":152301,"stargazers_count":78,"open_issues_count":4,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-10-24T08:43:43.761Z","etag":null,"topics":["matplotlib","microscopy-images","plotting"],"latest_commit_sha":null,"homepage":"https://guiwitz.github.io/microfilm","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/guiwitz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-09T14:52:09.000Z","updated_at":"2025-07-26T16:13:44.000Z","dependencies_parsed_at":"2025-02-11T15:46:53.049Z","dependency_job_id":null,"html_url":"https://github.com/guiwitz/microfilm","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/guiwitz/microfilm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guiwitz%2Fmicrofilm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guiwitz%2Fmicrofilm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guiwitz%2Fmicrofilm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guiwitz%2Fmicrofilm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guiwitz","download_url":"https://codeload.github.com/guiwitz/microfilm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guiwitz%2Fmicrofilm/sbom","scorecard":{"id":448983,"data":{"date":"2025-08-11","repo":{"name":"github.com/guiwitz/microfilm","commit":"58c1de32bc9dc7576e2545b9bfec95fdd4032d41"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/24 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/test_build.yml:65","Warn: no topLevel permission defined: .github/workflows/book.yml:1","Warn: no topLevel permission defined: .github/workflows/manual_matrix_tests.yml:1","Warn: no topLevel permission defined: .github/workflows/publish-to-test-pypi.yml:1","Warn: no topLevel permission defined: .github/workflows/test_build.yml:1","Warn: no topLevel permission defined: .github/workflows/tests.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.3.0rc not signed: https://api.github.com/repos/guiwitz/microfilm/releases/190918543","Warn: release artifact v0.3.0 not signed: https://api.github.com/repos/guiwitz/microfilm/releases/190963877","Warn: release artifact v0.3.0rc does not have provenance: https://api.github.com/repos/guiwitz/microfilm/releases/190918543","Warn: release artifact v0.3.0 does not have provenance: https://api.github.com/repos/guiwitz/microfilm/releases/190963877"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/test_build.yml:53"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/book.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/book.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/book.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/book.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/book.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/book.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/manual_matrix_tests.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/manual_matrix_tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/manual_matrix_tests.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/manual_matrix_tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-to-test-pypi.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/publish-to-test-pypi.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-to-test-pypi.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/publish-to-test-pypi.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish-to-test-pypi.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/publish-to-test-pypi.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_build.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/test_build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_build.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/test_build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_build.yml:69: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/test_build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_build.yml:72: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/test_build.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test_build.yml:87: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/test_build.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test_build.yml:91: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/test_build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/guiwitz/microfilm/tests.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/manual_matrix_tests.yml:25","Warn: pipCommand not pinned by hash: .github/workflows/manual_matrix_tests.yml:26","Warn: pipCommand not pinned by hash: .github/workflows/publish-to-test-pypi.yml:20","Warn: pipCommand not pinned by hash: .github/workflows/test_build.yml:44","Warn: pipCommand not pinned by hash: .github/workflows/test_build.yml:45","Warn: pipCommand not pinned by hash: .github/workflows/test_build.yml:79","Warn: pipCommand not pinned by hash: .github/workflows/test_build.yml:80","Info:   0 out of  12 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned","Info:   0 out of   7 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}}]},"last_synced_at":"2025-08-19T07:39:56.457Z","repository_id":38110244,"created_at":"2025-08-19T07:39:56.457Z","updated_at":"2025-08-19T07:39:56.457Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29668624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T23:24:07.480Z","status":"ssl_error","status_checked_at":"2026-02-20T23:24:06.202Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["matplotlib","microscopy-images","plotting"],"created_at":"2025-02-11T15:33:32.466Z","updated_at":"2026-02-21T00:01:46.338Z","avatar_url":"https://github.com/guiwitz.png","language":"Jupyter Notebook","funding_links":[],"categories":["🌻 Visualization"],"sub_categories":["Software tools"],"readme":"[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/guiwitz/microfilm/master?urlpath=lab)\n[![build](https://github.com/guiwitz/microfilm/actions/workflows/test_build.yml/badge.svg)](https://github.com/guiwitz/microfilm/actions/workflows/test_build.yml)\n![PyPI - License](https://img.shields.io/pypi/l/microfilm)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/microfilm)\n![PyPI](https://img.shields.io/pypi/v/microfilm)\n![PyPI - Status](https://img.shields.io/pypi/status/microfilm)\n# microfilm\n\nThis package is a collection of tools to display and analyze 2D and 2D time-lapse microscopy images. In particular it makes it straightforward to create figures containing multi-channel images represented in a *composite* color mode as done in the popular image processing software [Fiji](https://imagej.net/software/fiji/). It also allows to easily complete such figures with standard annotations like **labels** and **scale bars**. In case of time-lapse data, the figures are turned into **animations** which can be interactively browsed from a Jupyter notebook, saved in standard movie formats (mp4, gif etc.) and completed with **time counters**. Finally, figures and animations can easily be combined into larger **panels**. These main functionalities are provided by the ```microfilm.microplot``` and ```microfilm.microanim``` modules.\n\nFollowing the model of [seaborn](https://seaborn.pydata.org/index.html), ```microfilm``` is entirely based on [Matplotlib](https://matplotlib.org/) and tries to provide good defaults to produce good microcopy figures *out-of-the-box*. It however also offers complete access to the Matplotlib structures like axis and figures underlying the ```microfilm``` objects, allowing thus for the creation of arbitrarily complex plots.\n\n## Installation\n\nYou can install this package directly with pip using: \n\n```\npip install microfilm\n```\n\nTo get the latest stage of the package with yet unreleased features use:\n\n```\npip install git+https://github.com/guiwitz/microfilm.git\n```\n\nTo test the package via the Jupyter interface and the notebooks available [here](notebooks) you can create a conda environment using the [environment.yml](binder/environment.yml) file:\n\n```\nconda env create -f environment.yml\n```\n\n### Optional installs\n\nIf you want to use the ```dataset``` submodule (see below in Additional functionalities) and need to handle multipage tiff files or nd2 files, use:\n\n```\npip install \"microfilm[multipage]\"\n```\n\nor \n\n```\npip install \"microfilm[nd2]\"\n```\n\nIf you plan to not just use simple plotting but want to create animations, you need to install:\n\n```\npip install \"microfilm[animation]\"\n```\n\nTo install all options use:\n\n```\npip install \"microfilm[all]\"\n```\n\n## Simple plot\n\nIt is straightforward to create a ready-to-use plot of a multi-channel image dataset. In the following code snippet, we load a Numpy array of a multi-channel time-lapse dataset with shape ```CTXY``` (three channels). The figure below showing the time-point ```t=10``` is generated in a single command with a few options and saved as a png:\n\n```python\nimport numpy as np\nimport skimage.io\nfrom microfilm.microplot import microshow\n\nimage = skimage.io.imread('../demodata/coli_nucl_ori_ter.tif')\ntime = 10\n\nmicroim = microshow(\n    images=image[:, time, :, :], fig_scaling=5,\n    cmaps=['pure_blue','pure_red', 'pure_green'],\n    unit='um', scalebar_size_in_units=3, scalebar_unit_per_pix=0.065, scalebar_font_size=20,\n    label_text='A', label_font_size=0.04)\n\nmicroim.savefig('../illustrations/composite.png', bbox_inches = 'tight', pad_inches = 0, dpi=600)\n```\n\n\u003cimg src=\"https://github.com/guiwitz/microfilm/raw/master/illustrations/composite.png\" alt=\"image\" width=\"300\"\u003e\n\n## Animation\n\nIt is then easy to extend a simple figure into an animation as both objects take the same options. Additionally, a time-stamp can be added to the animation. This code generates the movie visible below:\n\n```python\nimport numpy as np\nimport skimage.io\nfrom microfilm.microanim import Microanim\n\nimage = skimage.io.imread('../demodata/coli_nucl_ori_ter.tif')\n\nmicroanim = Microanim(data=image, cmaps=['pure_blue','pure_red', 'pure_green'], fig_scaling=5,\n                      unit='um', scalebar_size_in_units=3, scalebar_unit_per_pix=0.065,\n                      scalebar_thickness=0.02, scalebar_font_size=20)\n\nmicroanim.add_label('A', label_font_size=30)\nmicroanim.add_time_stamp('T', 10, location='lower left', timestamp_size=20)\n\nmicroanim.save_movie('../illustrations/composite_movie.gif', fps=15)\n```\n\n\u003cimg src=\"https://github.com/guiwitz/microfilm/raw/master/illustrations/composite_movie.gif\" alt=\"image\" width=\"300\"\u003e\n\n## Panels\n\nBoth simple figures and animations can be combined into larger panels via the ```microplot.Micropanel``` and ```microanim.Microanimpanel``` objects. For example we can first create two figures ```microim1``` and ```microim2``` and then combine them into ```micropanel```:\n\n```python\nfrom microfilm import microplot\nimport skimage.io\n\nimage = skimage.io.imread('../demodata/coli_nucl_ori_ter.tif')\n\nmicroim1 = microplot.microshow(images=[image[0, 10, :, :], image[1, 10, :, :]],\n                               cmaps=['Greys', 'pure_magenta'], flip_map=[False, False],\n                               label_text='A', label_color='black')\nmicroim2 = microplot.microshow(images=[image[0, 10, :, :], image[2, 10, :, :]],\n                               cmaps=['Greys', 'pure_cyan'], flip_map=[False, False],\n                               label_text='B', label_color='black')\n\nmicropanel = microplot.Micropanel(rows=1, cols=2, figsize=[4,3])\n\nmicropanel.add_element(pos=[0,0], microim=microim1)\nmicropanel.add_element(pos=[0,1], microim=microim2)\n\nmicropanel.savefig('../illustrations/panel.png', bbox_inches = 'tight', pad_inches = 0, dpi=600)\n```\n\n\u003cimg src=\"https://github.com/guiwitz/microfilm/raw/master/illustrations/panel.png\" alt=\"image\" width=\"300\"\u003e\n\nAnd similarly for animations:\n\n```python\nfrom microfilm import microanim\nimport skimage.io\n\nimage = skimage.io.imread('../demodata/coli_nucl_ori_ter.tif')\n\nmicroanim1 = microanim.Microanim(data=image[[0,1],::], cmaps=['Greys', 'pure_magenta'],\n                                 flip_map=[False, False], label_text='A', label_color='black')\nmicroanim2 = microanim.Microanim(data=image[[0,2],::], cmaps=['Greys', 'pure_cyan'],\n                                 flip_map=[False, False], label_text='B', label_color='black')\n\nmicroanim1.add_time_stamp(unit='T', unit_per_frame='3', location='lower-right', timestamp_color='black')\n\nanimpanel = microanim.Microanimpanel(rows=1, cols=2, figsize=[4,3])\nanimpanel.add_element(pos=[0,0], microanim=microanim1)\nanimpanel.add_element(pos=[0,1], microanim=microanim2)\n\nanimpanel.save_movie('../illustrations/panel.gif')\n```\n\n\u003cimg src=\"https://github.com/guiwitz/microfilm/raw/master/illustrations/panel.gif\" alt=\"image\" width=\"300\"\u003e\n\n## Additional functionalities\n\nIn addition to these main plotting capabilities, the packages also offers:\n- ```microfilm.colorify```: a series of utility functions used by the main functions to create the composite color images. It contains functions to create colormaps, to turn 2D arrays into 3D-RGB arrays with appropriate colormaps etc.\n- ```microfilm.dataset```: a module offering a simple common data structure to handle multi-channel time-lapse data from multipage tiffs, series of tiff files, Nikon ND2 files, H5 and Numpy arrays. Requirement to use this module are at the moment very constrained (e.g. dimension order of Numpy arrays, name of H5 content etc.) but might evolve in the future.\n\n## Authors\n\nThis package has been created by Guillaume Witz, Microscopy Imaging Center and Science IT Support, University of Bern.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguiwitz%2Fmicrofilm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguiwitz%2Fmicrofilm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguiwitz%2Fmicrofilm/lists"}