Commit 87bb8b913bd958cd13016dc921c46d39ce44ca5e
Exists in
master
Merge branch 'master' into multimodal_tracking
# Conflicts: # invesalius/gui/task_navigator.py
Showing
11 changed files
with
70 additions
and
115 deletions
Show diff stats
invesalius/constants.py
... | ... | @@ -828,7 +828,7 @@ TREKKER_CONFIG = {'seed_max': 1, 'step_size': 0.1, 'min_fod': 0.1, 'probe_qualit |
828 | 828 | 'write_interval': 50, 'numb_threads': '', 'max_lenth': 200, |
829 | 829 | 'min_lenth': 20, 'max_sampling_step': 100} |
830 | 830 | |
831 | -MARKER_FILE_MAGICK_STRING = "INVESALIUS3_MARKER_FILE_" | |
831 | +MARKER_FILE_MAGICK_STRING = "##INVESALIUS3_MARKER_FILE_" | |
832 | 832 | CURRENT_MARKER_FILE_VERSION = 0 |
833 | 833 | WILDCARD_MARKER_FILES = _("Marker scanner coord files (*.mkss)|*.mkss") |
834 | 834 | ... | ... |
invesalius/control.py
... | ... | @@ -122,8 +122,6 @@ class Controller(): |
122 | 122 | |
123 | 123 | Publisher.subscribe(self.OnSaveProject, 'Save project') |
124 | 124 | |
125 | - Publisher.subscribe(self.Send_affine, 'Get affine matrix') | |
126 | - | |
127 | 125 | Publisher.subscribe(self.create_project_from_matrix, 'Create project from matrix') |
128 | 126 | |
129 | 127 | Publisher.subscribe(self.show_mask_preview, 'Show mask preview') |
... | ... | @@ -506,8 +504,9 @@ class Controller(): |
506 | 504 | utils.debug("No medical images found on given directory") |
507 | 505 | return |
508 | 506 | |
509 | - matrix, matrix_filename = self.OpenOtherFiles(group) | |
510 | - self.CreateOtherProject(str(name[0]), matrix, matrix_filename) | |
507 | + if group: | |
508 | + matrix, matrix_filename = self.OpenOtherFiles(group) | |
509 | + self.CreateOtherProject(str(name[0]), matrix, matrix_filename) | |
511 | 510 | # OPTION 4: Nothing... |
512 | 511 | |
513 | 512 | self.LoadProject() |
... | ... | @@ -623,6 +622,11 @@ class Controller(): |
623 | 622 | Publisher.sendMessage(('Set scroll position', 'AXIAL'), index=proj.matrix_shape[0]/2) |
624 | 623 | Publisher.sendMessage(('Set scroll position', 'SAGITAL'),index=proj.matrix_shape[1]/2) |
625 | 624 | Publisher.sendMessage(('Set scroll position', 'CORONAL'),index=proj.matrix_shape[2]/2) |
625 | + | |
626 | + if self.Slice.affine is not None: | |
627 | + Publisher.sendMessage('Enable Go-to-Coord', status=True) | |
628 | + else: | |
629 | + Publisher.sendMessage('Enable Go-to-Coord', status=False) | |
626 | 630 | |
627 | 631 | Publisher.sendMessage('End busy cursor') |
628 | 632 | |
... | ... | @@ -715,9 +719,6 @@ class Controller(): |
715 | 719 | proj.matrix_dtype = matrix.dtype.name |
716 | 720 | proj.matrix_filename = matrix_filename |
717 | 721 | |
718 | - if self.affine is not None: | |
719 | - proj.affine = self.affine.tolist() | |
720 | - | |
721 | 722 | # Orientation must be CORONAL in order to as_closes_canonical and |
722 | 723 | # swap axis in img2memmap to work in a standardized way. |
723 | 724 | # TODO: Create standard import image for all acquisition orientations |
... | ... | @@ -730,6 +731,8 @@ class Controller(): |
730 | 731 | proj.level = self.Slice.window_level |
731 | 732 | proj.threshold_range = int(matrix.min()), int(matrix.max()) |
732 | 733 | proj.spacing = self.Slice.spacing |
734 | + if self.Slice.affine is not None: | |
735 | + proj.affine = self.Slice.affine.tolist() | |
733 | 736 | |
734 | 737 | ###### |
735 | 738 | session = ses.Session() |
... | ... | @@ -915,16 +918,7 @@ class Controller(): |
915 | 918 | matrix, matrix_filename = self.OpenOtherFiles(group) |
916 | 919 | self.CreateOtherProject(name, matrix, matrix_filename) |
917 | 920 | self.LoadProject() |
918 | - if group.affine.any(): | |
919 | - # TODO: replace the inverse of the affine by the actual affine in the whole code | |
920 | - # remove scaling factor for non-unitary voxel dimensions | |
921 | - # self.affine = image_utils.world2invspace(affine=group.affine) | |
922 | - scale, shear, angs, trans, persp = tr.decompose_matrix(group.affine) | |
923 | - self.affine = np.linalg.inv(tr.compose_matrix(scale=None, shear=shear, | |
924 | - angles=angs, translate=trans, perspective=persp)) | |
925 | - # print("repos_img: {}".format(repos_img)) | |
926 | - self.Slice.affine = self.affine | |
927 | - Publisher.sendMessage('Update affine matrix', affine=self.affine) | |
921 | + | |
928 | 922 | Publisher.sendMessage("Enable state project", state=True) |
929 | 923 | else: |
930 | 924 | dialog.ImportInvalidFiles(ftype="Others") |
... | ... | @@ -1034,13 +1028,7 @@ class Controller(): |
1034 | 1028 | self.matrix, scalar_range, self.filename = image_utils.img2memmap(group) |
1035 | 1029 | |
1036 | 1030 | hdr = group.header |
1037 | - # if group.affine.any(): | |
1038 | - # self.affine = group.affine | |
1039 | - # Publisher.sendMessage('Update affine matrix', | |
1040 | - # affine=self.affine, status=True) | |
1041 | 1031 | hdr.set_data_dtype('int16') |
1042 | - dims = hdr.get_zooms() | |
1043 | - dimsf = tuple([float(s) for s in dims]) | |
1044 | 1032 | |
1045 | 1033 | wl = float((scalar_range[0] + scalar_range[1]) * 0.5) |
1046 | 1034 | ww = float((scalar_range[1] - scalar_range[0])) |
... | ... | @@ -1048,19 +1036,29 @@ class Controller(): |
1048 | 1036 | self.Slice = sl.Slice() |
1049 | 1037 | self.Slice.matrix = self.matrix |
1050 | 1038 | self.Slice.matrix_filename = self.filename |
1051 | - | |
1052 | - self.Slice.spacing = dimsf | |
1039 | + # even though the axes 0 and 2 are swapped when creating self.matrix | |
1040 | + # the spacing should be kept the original, as it is modified somewhere later | |
1041 | + # otherwise generate wrong results | |
1042 | + # also need to convert to float because original get_zooms return numpy.float32 | |
1043 | + # which is unsupported by the plist for saving the project | |
1044 | + self.Slice.spacing = tuple([float(s) for s in hdr.get_zooms()]) | |
1053 | 1045 | self.Slice.window_level = wl |
1054 | 1046 | self.Slice.window_width = ww |
1055 | 1047 | |
1048 | + if group.affine.any(): | |
1049 | + # remove scaling factor for non-unitary voxel dimensions | |
1050 | + scale, shear, angs, trans, persp = tr.decompose_matrix(group.affine) | |
1051 | + self.Slice.affine = np.linalg.inv(tr.compose_matrix(scale=None, shear=shear, | |
1052 | + angles=angs, translate=trans, perspective=persp)) | |
1053 | + else: | |
1054 | + self.Slice.affine = None | |
1055 | + | |
1056 | 1056 | scalar_range = int(scalar_range[0]), int(scalar_range[1]) |
1057 | + | |
1057 | 1058 | Publisher.sendMessage('Update threshold limits list', |
1058 | 1059 | threshold_range=scalar_range) |
1059 | - return self.matrix, self.filename | |
1060 | 1060 | |
1061 | - def Send_affine(self): | |
1062 | - if self.affine is not None: | |
1063 | - Publisher.sendMessage('Update affine matrix', affine=self.affine) | |
1061 | + return self.matrix, self.filename | |
1064 | 1062 | |
1065 | 1063 | def LoadImagedataInfo(self): |
1066 | 1064 | proj = prj.Project() | ... | ... |
invesalius/data/imagedata_utils.py
... | ... | @@ -549,6 +549,17 @@ def get_LUT_value_255(data, window, level): |
549 | 549 | return data |
550 | 550 | |
551 | 551 | |
552 | +def get_LUT_value(data, window, level): | |
553 | + shape = data.shape | |
554 | + data_ = data.ravel() | |
555 | + data = np.piecewise(data_, | |
556 | + [data_ <= (level - 0.5 - (window-1)/2), | |
557 | + data_ > (level - 0.5 + (window-1)/2)], | |
558 | + [0, window, lambda data_: ((data_ - (level - 0.5))/(window-1) + 0.5)*(window)]) | |
559 | + data.shape = shape | |
560 | + return data | |
561 | + | |
562 | + | |
552 | 563 | def image_normalize(image, min_=0.0, max_=1.0, output_dtype=np.int16): |
553 | 564 | output = np.empty(shape=image.shape, dtype=output_dtype) |
554 | 565 | imin, imax = image.min(), image.max() |
... | ... | @@ -595,7 +606,7 @@ def convert_invesalius_to_voxel(position): |
595 | 606 | :return: a vector of 3 coordinates in the voxel space |
596 | 607 | """ |
597 | 608 | slice = sl.Slice() |
598 | - return np.array((position[0], slice.matrix.shape[1] - position[1] - 1, position[2])) | |
609 | + return np.array((position[0], slice.spacing[1]*(slice.matrix.shape[1] - 1) - position[1], position[2])) | |
599 | 610 | |
600 | 611 | |
601 | 612 | def convert_invesalius_to_world(position, orientation): | ... | ... |
invesalius/data/styles.py
... | ... | @@ -45,6 +45,7 @@ import invesalius.utils as utils |
45 | 45 | from invesalius.data.measures import (CircleDensityMeasure, MeasureData, |
46 | 46 | PolygonDensityMeasure) |
47 | 47 | |
48 | +from invesalius.data.imagedata_utils import get_LUT_value, get_LUT_value_255 | |
48 | 49 | from invesalius_cy import floodfill |
49 | 50 | |
50 | 51 | # For tracts |
... | ... | @@ -69,26 +70,6 @@ WATERSHED_OPERATIONS = {_("Erase"): BRUSH_ERASE, |
69 | 70 | _("Foreground"): BRUSH_FOREGROUND, |
70 | 71 | _("Background"): BRUSH_BACKGROUND,} |
71 | 72 | |
72 | -def get_LUT_value(data, window, level): | |
73 | - shape = data.shape | |
74 | - data_ = data.ravel() | |
75 | - data = np.piecewise(data_, | |
76 | - [data_ <= (level - 0.5 - (window-1)/2), | |
77 | - data_ > (level - 0.5 + (window-1)/2)], | |
78 | - [0, window, lambda data_: ((data_ - (level - 0.5))/(window-1) + 0.5)*(window)]) | |
79 | - data.shape = shape | |
80 | - return data | |
81 | - | |
82 | -def get_LUT_value_255(data, window, level): | |
83 | - shape = data.shape | |
84 | - data_ = data.ravel() | |
85 | - data = np.piecewise(data_, | |
86 | - [data_ <= (level - 0.5 - (window-1)/2), | |
87 | - data_ > (level - 0.5 + (window-1)/2)], | |
88 | - [0, 255, lambda data_: ((data_ - (level - 0.5))/(window-1) + 0.5)*(255)]) | |
89 | - data.shape = shape | |
90 | - return data | |
91 | - | |
92 | 73 | |
93 | 74 | class BaseImageInteractorStyle(vtk.vtkInteractorStyleImage): |
94 | 75 | def __init__(self, viewer): | ... | ... |
invesalius/data/surface.py
... | ... | @@ -51,6 +51,7 @@ else: |
51 | 51 | |
52 | 52 | import invesalius.constants as const |
53 | 53 | import invesalius.data.imagedata_utils as iu |
54 | +import invesalius.data.slice_ as sl | |
54 | 55 | import invesalius.data.polydata_utils as pu |
55 | 56 | import invesalius.project as prj |
56 | 57 | import invesalius.session as ses |
... | ... | @@ -159,7 +160,6 @@ class SurfaceManager(): |
159 | 160 | def __init__(self): |
160 | 161 | self.actors_dict = {} |
161 | 162 | self.last_surface_index = 0 |
162 | - self.affine_vtk = None | |
163 | 163 | self.convert2inv = None |
164 | 164 | self.__bind_events() |
165 | 165 | |
... | ... | @@ -207,7 +207,6 @@ class SurfaceManager(): |
207 | 207 | |
208 | 208 | Publisher.subscribe(self.OnImportSurfaceFile, 'Import surface file') |
209 | 209 | |
210 | - Publisher.subscribe(self.UpdateAffineMatrix, 'Update affine matrix') | |
211 | 210 | Publisher.subscribe(self.UpdateConvert2InvFlag, 'Update convert2inv flag') |
212 | 211 | |
213 | 212 | Publisher.subscribe(self.CreateSurfaceFromPolydata, 'Create surface from polydata') |
... | ... | @@ -338,16 +337,6 @@ class SurfaceManager(): |
338 | 337 | name = os.path.splitext(os.path.split(filename)[-1])[0] |
339 | 338 | self.CreateSurfaceFromPolydata(polydata, name=name, scalar=scalar) |
340 | 339 | |
341 | - def UpdateAffineMatrix(self, affine): | |
342 | - if affine is not None: | |
343 | - prj_data = prj.Project() | |
344 | - matrix_shape = tuple(prj_data.matrix_shape) | |
345 | - affine = affine.copy() | |
346 | - affine[1, -1] -= matrix_shape[1] | |
347 | - self.affine_vtk = vtk_utils.numpy_to_vtkMatrix4x4(affine) | |
348 | - else: | |
349 | - self.affine_vtk = None | |
350 | - | |
351 | 340 | def UpdateConvert2InvFlag(self, convert2inv=False): |
352 | 341 | self.convert2inv = convert2inv |
353 | 342 | |
... | ... | @@ -373,12 +362,17 @@ class SurfaceManager(): |
373 | 362 | actor.SetMapper(mapper) |
374 | 363 | actor.GetProperty().SetBackfaceCulling(1) |
375 | 364 | |
376 | - if self.convert2inv and (self.affine_vtk is not None): | |
377 | - actor.SetUserMatrix(self.affine_vtk) | |
365 | + if self.convert2inv: | |
366 | + # convert between invesalius and world space with shift in the Y coordinate | |
367 | + affine = sl.Slice().affine | |
368 | + if affine is not None: | |
369 | + affine[1, -1] -= sl.Slice().spacing[1] * (sl.Slice().matrix.shape[1] - 1) | |
370 | + affine_vtk = vtk_utils.numpy_to_vtkMatrix4x4(affine) | |
371 | + actor.SetUserMatrix(affine_vtk) | |
378 | 372 | |
379 | 373 | if overwrite: |
380 | 374 | if index is None: |
381 | - index = self.last_surface_index | |
375 | + index = self.last_surface_index | |
382 | 376 | surface = Surface(index=index) |
383 | 377 | else: |
384 | 378 | surface = Surface() | ... | ... |
invesalius/data/viewer_volume.py
... | ... | @@ -1455,7 +1455,8 @@ class Viewer(wx.Panel): |
1455 | 1455 | self.ren.RemoveActor(self.object_orientation_torus_actor) |
1456 | 1456 | self.ren.RemoveActor(self.obj_projection_arrow_actor) |
1457 | 1457 | self.actor_peel = None |
1458 | - self.ball_actor.SetVisibility(1) | |
1458 | + if self.ball_actor: | |
1459 | + self.ball_actor.SetVisibility(1) | |
1459 | 1460 | |
1460 | 1461 | if flag and actor: |
1461 | 1462 | self.ren.AddActor(actor) | ... | ... |
invesalius/gui/dialogs.py
... | ... | @@ -4208,37 +4208,23 @@ class GoToDialogScannerCoord(wx.Dialog): |
4208 | 4208 | self.__bind_events() |
4209 | 4209 | |
4210 | 4210 | btn_ok.Bind(wx.EVT_BUTTON, self.OnOk) |
4211 | - Publisher.sendMessage('Get affine matrix') | |
4212 | 4211 | |
4213 | 4212 | def __bind_events(self): |
4214 | 4213 | Publisher.subscribe(self.SetNewFocalPoint, 'Cross focal point') |
4215 | - Publisher.subscribe(self.UpdateAffineMatrix, 'Update affine matrix') | |
4216 | - | |
4217 | - def UpdateAffineMatrix(self, affine): | |
4218 | - self.affine = affine | |
4219 | 4214 | |
4220 | 4215 | def SetNewFocalPoint(self, coord, spacing): |
4221 | 4216 | Publisher.sendMessage('Update cross pos', coord=self.result*spacing) |
4222 | 4217 | |
4223 | 4218 | def OnOk(self, evt): |
4224 | - from numpy.linalg import inv | |
4225 | 4219 | import invesalius.data.slice_ as slc |
4226 | 4220 | try: |
4227 | - #get affine from image import | |
4228 | - if self.affine is not None: | |
4229 | - affine = self.affine | |
4230 | - #get affine from project | |
4231 | - else: | |
4232 | - from invesalius.project import Project | |
4233 | - affine = Project().affine | |
4234 | - | |
4235 | 4221 | point = [float(self.goto_sagital.GetValue()), |
4236 | 4222 | float(self.goto_coronal.GetValue()), |
4237 | 4223 | float(self.goto_axial.GetValue())] |
4238 | 4224 | |
4239 | 4225 | # transformation from scanner coordinates to inv coord system |
4240 | - affine = inv(affine) | |
4241 | - self.result = np.dot(affine[:3, :3], np.transpose(point[0:3])) + affine[:3, 3] | |
4226 | + affine_inverse = np.linalg.inv(slc.Slice().affine) | |
4227 | + self.result = np.dot(affine_inverse[:3, :3], np.transpose(point[0:3])) + affine_inverse[:3, 3] | |
4242 | 4228 | self.result[1] = slc.Slice().GetMaxSliceNumber(const.CORONAL_STR) - self.result[1] |
4243 | 4229 | |
4244 | 4230 | Publisher.sendMessage('Update status text in GUI', label=_("Calculating the transformation ...")) | ... | ... |
invesalius/gui/frame.py
... | ... | @@ -892,7 +892,7 @@ class MenuBar(wx.MenuBar): |
892 | 892 | sub(self.OnEnableState, "Enable state project") |
893 | 893 | sub(self.OnEnableUndo, "Enable undo") |
894 | 894 | sub(self.OnEnableRedo, "Enable redo") |
895 | - sub(self.OnEnableGotoCoord, "Update affine matrix") | |
895 | + sub(self.OnEnableGotoCoord, "Enable Go-to-Coord") | |
896 | 896 | sub(self.OnEnableNavigation, "Navigation status") |
897 | 897 | |
898 | 898 | sub(self.OnAddMask, "Add mask") |
... | ... | @@ -1242,15 +1242,13 @@ class MenuBar(wx.MenuBar): |
1242 | 1242 | else: |
1243 | 1243 | self.FindItemById(wx.ID_REDO).Enable(False) |
1244 | 1244 | |
1245 | - def OnEnableGotoCoord(self, affine): | |
1245 | + def OnEnableGotoCoord(self, status=True): | |
1246 | 1246 | """ |
1247 | - Disable goto coord either if there is no affine matrix or affine is wrongly imported. | |
1248 | - :param status: Affine matrix status | |
1247 | + Enable or disable goto coord depending on the imported affine matrix. | |
1248 | + :param status: True for enabling and False for disabling the Go-To-Coord | |
1249 | 1249 | """ |
1250 | - if affine is not None: | |
1251 | - self.FindItemById(const.ID_GOTO_COORD).Enable(True) | |
1252 | - else: | |
1253 | - self.FindItemById(const.ID_GOTO_COORD).Enable(False) | |
1250 | + | |
1251 | + self.FindItemById(const.ID_GOTO_COORD).Enable(status) | |
1254 | 1252 | |
1255 | 1253 | def OnEnableNavigation(self, nav_status, vis_status): |
1256 | 1254 | """ | ... | ... |
invesalius/gui/task_navigator.py
... | ... | @@ -691,8 +691,8 @@ class NeuronavigationPanel(wx.Panel): |
691 | 691 | size = 2 |
692 | 692 | seed = 3 * [0.] |
693 | 693 | |
694 | - Publisher.sendMessage('Create marker', coord=coord, colour=colour, size=size, label=label, seed=seed) | |
695 | - | |
694 | + Publisher.sendMessage('Create marker', coord=coord, colour=colour, size=size, | |
695 | + label=label, seed=seed) | |
696 | 696 | else: |
697 | 697 | for m in [0, 1, 2]: |
698 | 698 | self.numctrls_fiducial[n][m].SetValue(float(self.current_coord[m])) |
... | ... | @@ -1189,11 +1189,11 @@ class MarkersPanel(wx.Panel): |
1189 | 1189 | res += '\t'.join(map(lambda x: 'N/A' if x is None else str(x), (*position_world, *orientation_world))) |
1190 | 1190 | return res |
1191 | 1191 | |
1192 | - def from_string(self, str): | |
1193 | - """Deserialize from a tab-separated string. If the string is not | |
1192 | + def from_string(self, inp_str): | |
1193 | + """Deserialize from a tab-separated string. If the string is not | |
1194 | 1194 | properly formatted, might throw an exception and leave the object |
1195 | 1195 | in an inconsistent state.""" |
1196 | - for field, str_val in zip(dataclasses.fields(self.__class__), str.split('\t')): | |
1196 | + for field, str_val in zip(dataclasses.fields(self.__class__), inp_str.split('\t')): | |
1197 | 1197 | if field.type is float: |
1198 | 1198 | setattr(self, field.name, float(str_val)) |
1199 | 1199 | if field.type is int: |
... | ... | @@ -1294,7 +1294,7 @@ class MarkersPanel(wx.Panel): |
1294 | 1294 | self.lc.InsertColumn(1, 'X') |
1295 | 1295 | self.lc.InsertColumn(2, 'Y') |
1296 | 1296 | self.lc.InsertColumn(3, 'Z') |
1297 | - self.lc.InsertColumn(4, 'ID') | |
1297 | + self.lc.InsertColumn(4, 'Label') | |
1298 | 1298 | self.lc.InsertColumn(5, 'Target') |
1299 | 1299 | self.lc.InsertColumn(6, 'Session') |
1300 | 1300 | |
... | ... | @@ -2125,7 +2125,7 @@ class SessionPanel(wx.Panel): |
2125 | 2125 | except AttributeError: |
2126 | 2126 | default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) |
2127 | 2127 | self.SetBackgroundColour(default_colour) |
2128 | - | |
2128 | + | |
2129 | 2129 | # session count spinner |
2130 | 2130 | self.__spin_session = wx.SpinCtrl(self, -1, "", size=wx.Size(40, 23)) |
2131 | 2131 | self.__spin_session.SetRange(1, 99) |
... | ... | @@ -2133,13 +2133,13 @@ class SessionPanel(wx.Panel): |
2133 | 2133 | |
2134 | 2134 | self.__spin_session.Bind(wx.EVT_TEXT, self.OnSessionChanged) |
2135 | 2135 | self.__spin_session.Bind(wx.EVT_SPINCTRL, self.OnSessionChanged) |
2136 | - | |
2136 | + | |
2137 | 2137 | sizer_create = wx.FlexGridSizer(rows=1, cols=1, hgap=5, vgap=5) |
2138 | 2138 | sizer_create.AddMany([(self.__spin_session, 1)]) |
2139 | 2139 | |
2140 | 2140 | def OnSessionChanged(self, evt): |
2141 | 2141 | Publisher.sendMessage('Current session changed', new_session_id=self.__spin_session.GetValue()) |
2142 | - | |
2142 | + | |
2143 | 2143 | |
2144 | 2144 | class InputAttributes(object): |
2145 | 2145 | # taken from https://stackoverflow.com/questions/2466191/set-attributes-from-dictionary-in-python | ... | ... |
invesalius/project.py
... | ... | @@ -329,8 +329,6 @@ class Project(metaclass=Singleton): |
329 | 329 | |
330 | 330 | if project.get("affine", ""): |
331 | 331 | self.affine = project["affine"] |
332 | - Publisher.sendMessage('Update affine matrix', | |
333 | - affine=np.asarray(self.affine).reshape(4, 4)) | |
334 | 332 | |
335 | 333 | # Opening the masks |
336 | 334 | self.mask_dict = TwoWaysDictionary() | ... | ... |
invesalius/segmentation/brain/segment.py
... | ... | @@ -22,17 +22,6 @@ SIZE = 48 |
22 | 22 | OVERLAP = SIZE // 2 + 1 |
23 | 23 | |
24 | 24 | |
25 | -def get_LUT_value(data, window, level): | |
26 | - shape = data.shape | |
27 | - data_ = data.ravel() | |
28 | - data = np.piecewise(data_, | |
29 | - [data_ <= (level - 0.5 - (window-1)/2), | |
30 | - data_ > (level - 0.5 + (window-1)/2)], | |
31 | - [0, window, lambda data_: ((data_ - (level - 0.5))/(window-1) + 0.5)*(window)]) | |
32 | - data.shape = shape | |
33 | - return data | |
34 | - | |
35 | - | |
36 | 25 | def gen_patches(image, patch_size, overlap): |
37 | 26 | sz, sy, sx = image.shape |
38 | 27 | i_cuts = list( |
... | ... | @@ -188,8 +177,7 @@ class SegmentProcess(ctx.Process): |
188 | 177 | ) |
189 | 178 | |
190 | 179 | if self.apply_wwwl: |
191 | - print("Applying window level") | |
192 | - image = get_LUT_value(image, self.window_width, self.window_level) | |
180 | + image = imagedata_utils.get_LUT_value(image, self.window_width, self.window_level) | |
193 | 181 | |
194 | 182 | probability_array = np.memmap( |
195 | 183 | self._prob_array_filename, | ... | ... |