Browse Source

added Surface.add_rectangle()

Fabian Peter Hammerle 5 years ago
parent
commit
952cf8c3d6
5 changed files with 68 additions and 20 deletions
  1. 30 1
      Pipfile.lock
  2. 5 18
      examples/precentral_gyrus_border.ipynb
  3. 12 0
      freesurfer_surface/__init__.py
  4. 3 1
      setup.py
  5. 18 0
      tests/test_surface.py

+ 30 - 1
Pipfile.lock

@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "8352fc62d16e328f3af33b4fb405bf12384ddb936c3ebbc33197245d69c80c72"
+            "sha256": "9f4b353098ebb834c6bff1eff489f9d5fe7a33476e10720b45e6cba07dea4cff"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -19,6 +19,35 @@
         "freesurfer-surface": {
             "editable": true,
             "path": "."
+        },
+        "numpy": {
+            "hashes": [
+                "sha256:0e2eed77804b2a6a88741f8fcac02c5499bba3953ec9c71e8b217fad4912c56c",
+                "sha256:1c666f04553ef70fda54adf097dbae7080645435fc273e2397f26bbf1d127bbb",
+                "sha256:1f46532afa7b2903bfb1b79becca2954c0a04389d19e03dc73f06b039048ac40",
+                "sha256:315fa1b1dfc16ae0f03f8fd1c55f23fd15368710f641d570236f3d78af55e340",
+                "sha256:3d5fcea4f5ed40c3280791d54da3ad2ecf896f4c87c877b113576b8280c59441",
+                "sha256:48241759b99d60aba63b0e590332c600fc4b46ad597c9b0a53f350b871ef0634",
+                "sha256:4b4f2924b36d857cf302aec369caac61e43500c17eeef0d7baacad1084c0ee84",
+                "sha256:54fe3b7ed9e7eb928bbc4318f954d133851865f062fa4bbb02ef8940bc67b5d2",
+                "sha256:5a8f021c70e6206c317974c93eaaf9bc2b56295b6b1cacccf88846e44a1f33fc",
+                "sha256:754a6be26d938e6ca91942804eb209307b73f806a1721176278a6038869a1686",
+                "sha256:771147e654e8b95eea1293174a94f34e2e77d5729ad44aefb62fbf8a79747a15",
+                "sha256:78a6f89da87eeb48014ec652a65c4ffde370c036d780a995edaeb121d3625621",
+                "sha256:7fde5c2a3a682a9e101e61d97696687ebdba47637611378b4127fe7e47fdf2bf",
+                "sha256:80d99399c97f646e873dd8ce87c38cfdbb668956bbc39bc1e6cac4b515bba2a0",
+                "sha256:88a72c1e45a0ae24d1f249a529d9f71fe82e6fa6a3fd61414b829396ec585900",
+                "sha256:a4f4460877a16ac73302a9c077ca545498d9fe64e6a81398d8e1a67e4695e3df",
+                "sha256:a61255a765b3ac73ee4b110b28fccfbf758c985677f526c2b4b39c48cc4b509d",
+                "sha256:ab4896a8c910b9a04c0142871d8800c76c8a2e5ff44763513e1dd9d9631ce897",
+                "sha256:abbd6b1c2ef6199f4b7ca9f818eb6b31f17b73a6110aadc4e4298c3f00fab24e",
+                "sha256:b16d88da290334e33ea992c56492326ea3b06233a00a1855414360b77ca72f26",
+                "sha256:b78a1defedb0e8f6ae1eb55fa6ac74ab42acc4569c3a2eacc2a407ee5d42ebcb",
+                "sha256:cfef82c43b8b29ca436560d51b2251d5117818a8d1fb74a8384a83c096745dad",
+                "sha256:d160e57731fcdec2beda807ebcabf39823c47e9409485b5a3a1db3a8c6ce763e"
+            ],
+            "index": "pypi",
+            "version": "==1.16.3"
         }
     },
     "develop": {

+ 5 - 18
examples/precentral_gyrus_border.ipynb

@@ -74,30 +74,17 @@
    "source": [
     "from freesurfer_surface import Vertex, Triangle\n",
     "\n",
-    "FACTOR = 1.5\n",
+    "FACTOR = 1.3\n",
     "for segment in border_chain.segments():\n",
-    "    new_vertix_indices = [\n",
-    "        surface.add_vertex(Vertex(\n",
-    "            right=surface.vertices[segment.vertex_indices[0]].right * FACTOR,\n",
-    "            anterior=surface.vertices[segment.vertex_indices[0]].anterior * FACTOR,\n",
-    "            superior=surface.vertices[segment.vertex_indices[0]].superior * FACTOR,\n",
-    "        )),\n",
+    "    surface.add_rectangle((\n",
+    "        segment.vertex_indices[0],\n",
+    "        segment.vertex_indices[1],\n",
     "        surface.add_vertex(Vertex(\n",
     "            right=surface.vertices[segment.vertex_indices[1]].right * FACTOR,\n",
     "            anterior=surface.vertices[segment.vertex_indices[1]].anterior * FACTOR,\n",
     "            superior=surface.vertices[segment.vertex_indices[1]].superior * FACTOR,\n",
     "        )),\n",
-    "    ]\n",
-    "    surface.triangles.append(Triangle((\n",
-    "        segment.vertex_indices[0],\n",
-    "        segment.vertex_indices[1],\n",
-    "        new_vertix_indices[0],\n",
-    "    )))\n",
-    "    surface.triangles.append(Triangle((\n",
-    "        segment.vertex_indices[1],\n",
-    "        new_vertix_indices[0],\n",
-    "        new_vertix_indices[1],\n",
-    "    )))\n",
+    "    ))\n",
     "len(surface.triangles)"
    ]
   },

+ 12 - 0
freesurfer_surface/__init__.py

@@ -38,6 +38,8 @@ import re
 import struct
 import typing
 
+import numpy
+
 try:
     from freesurfer_surface.version import __version__
 except ImportError:  # pragma: no cover
@@ -347,6 +349,16 @@ class Surface:
         self.vertices.append(vertex)
         return len(self.vertices) - 1
 
+    def add_rectangle(self, vertex_indices: typing.Iterable[int]) -> typing.Iterable[int]:
+        vertex_indices = list(vertex_indices)
+        assert len(vertex_indices) == 3
+        vertex_coords = [numpy.array(self.vertices[vertex_index])
+                         for vertex_index in vertex_indices]
+        vertex_coords.append(vertex_coords[0] + vertex_coords[2] - vertex_coords[1])
+        vertex_indices.append(self.add_vertex(Vertex(*vertex_coords[3])))
+        self.triangles.append(Triangle(vertex_indices[:3]))
+        self.triangles.append(Triangle(vertex_indices[2:] + vertex_indices[:1]))
+
     def _find_label_border_segments(self, label: Label) -> typing.Iterator[_LineSegment]:
         for triangle in self.triangles:
             border_vertex_indices = tuple(filter(

+ 3 - 1
setup.py

@@ -49,7 +49,9 @@ setuptools.setup(
             'freesurfer-annotation-labels = freesurfer_surface.__main__:annotation_labels',
         ],
     },
-    install_requires=[],
+    install_requires=[
+        'numpy<2',
+    ],
     setup_requires=[
         'setuptools_scm',
     ],

+ 18 - 0
tests/test_surface.py

@@ -134,6 +134,24 @@ def test_add_vertex():
     assert surface.vertices[1].right == pytest.approx(-3.0)
 
 
+@pytest.mark.parametrize(('vertices_coords', 'expected_extra_vertex_coords'), [
+    (((0, 0, 0), (2, 4, 0), (2, 4, 3)), (0, 0, 3)),
+    (((1, 1, 0), (3, 5, 0), (3, 5, 3)), (1, 1, 3)),
+    (((1, 1, 7), (3, 5, 7), (3, 5, 3)), (1, 1, 3)),
+    (((1, 1, 1), (3, 5, 7), (3, 5, 9)), (1, 1, 3)),
+    (((3, 5, 7), (1, 1, 1), (1, 1, 3)), (3, 5, 9)),
+])
+def test_add_rectangle(vertices_coords, expected_extra_vertex_coords):
+    surface = Surface()
+    for vertex_coords in vertices_coords:
+        surface.add_vertex(Vertex(*(float(c) for c in vertex_coords)))
+    surface.add_rectangle(range(3))
+    assert tuple(surface.vertices[3]) == pytest.approx(expected_extra_vertex_coords)
+    assert len(surface.triangles) == 2
+    assert surface.triangles[0].vertex_indices == (0, 1, 2)
+    assert surface.triangles[1].vertex_indices == (2, 3, 0)
+
+
 def test__find_label_border_segments():
     surface = Surface.read_triangular(SURFACE_FILE_PATH)
     surface.load_annotation_file(ANNOTATION_FILE_PATH)