eitcom / pyEIT

Python based toolkit for Electrical Impedance Tomography
Other
177 stars 100 forks source link

Add features to work with external meshes and compute GREIT figures of merit #54

Closed acreegan closed 2 years ago

acreegan commented 2 years ago

Introduction

This PR consists of work done at the Auckland Bioengineering Institute over the course of 2020-2021. Our goal was to use pyEIT to perform subject-specific EIT of the human lung. A study making use of this work will be published later this year in a Springer book titled Computational Biomechanics for Medicine: Towards Translation and Better Patient Outcomes.

We add two main features to pyEIT:

External Meshes

Code for working with external meshes is located in pyeit.mesh.external.

load_mesh is used to load a mesh from a file using trimesh, and create a PyEITMesh object. The perm attribute of the PyEITMesh object can be read from the file if the .ply file format. perm is read as a 32 bit float from the 4 bytes of the ply color attribute.

place_electrodes_equal_spacing is used to identify a list of nodes in the PyEITMesh object representing equal-spaced placing of electrodes around the mesh's perimeter.

GREIT Figures of Merit

Code for the GREIT figures of merit is located in pyeit.quality.merit. The GREIT figures of merit are a commonly used set of measures for EIT image quality. We have implemented them as proposed by Adler et al. (as they are implemented in EIDORS) along with an adaption for non-circular targets as proposed by Biguri et al.

Since the GRIET figures of merit use an image analysis approach, the solved pyEIT mesh must first be rendered into a rectangular array of pixels before the figures of merit can be calculated. We provide code to do this in pyeit.eit.render

model_inverse_uv is used to render an unstructured triangular mesh into a rectangular array of pixels with the value of each pixel being the index of the triangle it lies within.

map_image is used to map a list of values onto the image generated by model_inverse_uv

calc_greit_figures_of_merit is used to calculate the five GREIT figures of merit, given a target image and reconstruction image.

Plotting

To support examples to demonstrate working with external meshes and computing figures of merit, we have introduced three types of plots, located in pyeit.visual.plot

create_mesh_plot_2 is used to create a plot to display a 2d mesh, and optionally plot electrode positions and coordinate labels. This is an alternative to the existing pyeit.visual.plot.mesh_plot

create_plot uses matplotlib's tripcolor to create a plot of a reconstructed EIT image, and optionally plot electrode positions and coordinate labels.

create_layered_image_plot is used to create a plot using imshow from discrete layers, which are labeled in the legend.

Examples

The examples folder contains eit_external_mesh.py and merit.py, to demonstrate working with external meshes and computing figures of merit respectively.

Bugfix

We added from __future__ import annotations to files that import from typing so that tests will bass on python 3.8

Testing

We added tox.ini to enable use of tox for testing multiple versions of python. Tests for this PR are passing in python versions 3.8, 3.9, and 3.10. The base pyEIT version is failing for python versions 3.6 and 3.7 (are these still intended to be supported?)

With pytest --cov, test coverage for new code is as follows: render.py: 84% external.py: 96% merit.py: 21%

Thanks for considering this PR :)

liubenyuan commented 2 years ago

Thank you~

  1. Is the plot create_mesh_plot_2 with _2 means 2D in your codes? if so, I would suggest using create_mesh_plot or create_mesh_plot2d instead. The files in examples and visual should be modified all-together.
  2. A .gitignore file should be added to the test/test_data directory (maybe test/test_data should be renamed to test/data for simplicity?). The .STL files and other important binary files related to the test and coverage scripts should be kept and the intermediate binary data (like .npy, .bmp) can be ignored and deleted from the tracking files. This could reduce the overall package size.
acreegan commented 2 years ago

Thank you~

  1. Is the plot create_mesh_plot_2 with _2 means 2D in your codes? if so, I would suggest using create_mesh_plot or create_mesh_plot2d instead. The files in examples and visual should be modified all-together.
  2. A .gitignore file should be added to the test/test_data directory (maybe test/test_data should be renamed to test/data for simplicity?). The .STL files and other important binary files related to the test and coverage scripts should be kept and the intermediate binary data (like .npy, .bmp) can be ignored and deleted from the tracking files. This could reduce the overall package size.
liubenyuan commented 2 years ago

mesh_plot is used for debugging and generating mesh plots in the eitmesh project, which hosts various of binary meshes of lung, and head phantoms.

Sure, you can merge existing mesh_plot into your create_mesh_plot_2 and keep only the necessary functions (particularly this function should show the electrodes' node-locations), and rename it into create_mesh_plot. Please let me know if this is ok and let's merge this PR!

acreegan commented 2 years ago

mesh_plot is used for debugging and generating mesh plots in the eitmesh project, which hosts various of binary meshes of lung, and head phantoms.

Sure, you can merge existing mesh_plot into your create_mesh_plot_2 and keep only the necessary functions (particularly this function should show the electrodes' node-locations), and rename it into create_mesh_plot. Please let me know if this is ok and let's merge this PR!

I have removed mesh_plot and renamed create_mesh_plot_2 to create_mesh_plot. This function is able to show and number the electrode locations. Note that this means the ability to load a background image has been removed. I didn't see this feature being actually used in the eitmesh project, but we can add it back if you like.