1313NUM_DEMO_DIMS = 2 # Currently can be 2D or 3D
1414AFFINE_NUM_DECIMALS = 4
1515
16- # TODO may not be needed, depends on how we handle the two coord spaces
1716MARKERS_SHADER = """
1817#uicontrol vec3 fixedPointColor color(default="#00FF00")
1918#uicontrol vec3 movingPointColor color(default="#0000FF")
@@ -102,7 +101,7 @@ def rigid_or_similarity_fit(
102101 # Homogeneous (D+1)x(D+1)
103102 T = np .zeros ((D , D + 1 ))
104103 T [:D , :D ] = s * R
105- T [:, - 1 ] = np .diagonal (t )
104+ T [:, - 1 ] = - 1 * np .diagonal (t )
106105
107106 affine = np .round (T , decimals = AFFINE_NUM_DECIMALS )
108107 return affine
@@ -246,6 +245,8 @@ def __init__(self, args):
246245 self .stored_points = [[], []]
247246 self .stored_moving_dims = {}
248247 self .moving_layer_names = []
248+ self .input_dim_names = []
249+ self .output_dim_names = []
249250 self .stored_group_number = - 1
250251 self .affine = None
251252 self .co_ords_ready = False
@@ -314,9 +315,9 @@ def setup_two_panel_layout(self, s: neuroglancer.ViewerState):
314315 # In theory we could make keep unlinked and then on state change check
315316 # but that could be not worth compared to trying to improve rendering
316317 s .layout .children [1 ].crossSectionOrientation .link = "unlinked"
317- s .layout .children [1 ].crossSectionScale .link = "unlinked"
318+ # s.layout.children[1].crossSectionScale.link = "unlinked"
318319 s .layout .children [1 ].projectionOrientation .link = "unlinked"
319- s .layout .children [1 ].projectionScale .link = "unlinked"
320+ # s.layout.children[1].projectionScale.link = "unlinked"
320321
321322 def setup_second_coord_space (self ):
322323 if not self .moving_layer_names :
@@ -327,33 +328,69 @@ def setup_second_coord_space(self):
327328 info_future = self .viewer .volume_info (layer_name )
328329 info_future .add_done_callback (lambda f : self .save_coord_space_info (f ))
329330
331+ def combine_affine_across_dims (self , s : neuroglancer .ViewerState , affine ):
332+ all_dims = s .dimensions .names
333+ moving_dims = self .output_dim_names
334+ # The affine matrix only applies to the moving dims
335+ # so we need to create a larger matrix that applies to all dims
336+ # by adding identity transforms for the real dims
337+ full_matrix = np .zeros ((len (all_dims ), len (all_dims ) + 1 ))
338+ for i , dim in enumerate (all_dims ):
339+ for j , dim2 in enumerate (all_dims ):
340+ if dim in moving_dims and dim2 in moving_dims :
341+ moving_i = moving_dims .index (dim )
342+ moving_j = moving_dims .index (dim2 )
343+ full_matrix [i , j ] = affine [moving_i , moving_j ]
344+ elif dim == dim2 :
345+ full_matrix [i , j ] = 1
346+ if dim in moving_dims :
347+ moving_i = moving_dims .index (dim )
348+ full_matrix [i , - 1 ] = affine [moving_i , - 1 ]
349+ return full_matrix
350+
330351 def setup_registration_layers (self , s : neuroglancer .ViewerState ):
331352 dimensions = s .dimensions
332353 # It is possible that the dimensions are not ready yet, return if so
333354 if len (dimensions .names ) != self .num_dims :
334355 return
356+
335357 # Make the annotation layer if needed
336- # TODO probably don't need the properties, to be confirmed if
337- # one co-ord space is fine or need two
338358 if s .layers .index (self .annotations_name ) == - 1 :
339- s .layers [self .annotations_name ] = neuroglancer .LocalAnnotationLayer (
340- dimensions = create_dimensions (s .dimensions ),
341- # annotation_properties=[
342- # neuroglancer.AnnotationPropertySpec(
343- # id="label",
344- # type="uint32",
345- # default=0,
346- # ),
347- # neuroglancer.AnnotationPropertySpec(
348- # id="group",
349- # type="uint8",
350- # default=0,
351- # enum_labels=["fixed", "moving"],
352- # enum_values=[0, 1],
353- # ),
354- # ],
355- # shader=MARKERS_SHADER,
356- )
359+ if self .two_coord_spaces :
360+ s .layers [self .annotations_name ] = neuroglancer .LocalAnnotationLayer (
361+ dimensions = create_dimensions (s .dimensions )
362+ )
363+ else :
364+ s .layers [self .annotations_name ] = neuroglancer .LocalAnnotationLayer (
365+ dimensions = create_dimensions (s .dimensions ),
366+ annotation_properties = [
367+ neuroglancer .AnnotationPropertySpec (
368+ id = "label" ,
369+ type = "uint32" ,
370+ default = 0 ,
371+ ),
372+ neuroglancer .AnnotationPropertySpec (
373+ id = "group" ,
374+ type = "uint8" ,
375+ default = 0 ,
376+ enum_labels = ["fixed" , "moving" ],
377+ enum_values = [0 , 1 ],
378+ ),
379+ ],
380+ shader = MARKERS_SHADER ,
381+ )
382+
383+ # Make a copy of all the moving layers but in original coord space
384+ # and as part of the left hand panel
385+ for layer_name in self .moving_layer_names :
386+ copy = deepcopy (s .layers [layer_name ])
387+ copy .name = layer_name + "_registered"
388+ copy .visible = False
389+ for source in copy .source :
390+ # TODO might need mapping
391+ source .transform = None
392+ s .layers [copy .name ] = copy
393+ s .layout .children [0 ].layers .append (copy .name )
357394 s .layers [self .annotations_name ].tool = "annotatePoint"
358395 s .selected_layer .layer = self .annotations_name
359396 s .selected_layer .visible = True
@@ -394,9 +431,14 @@ def save_coord_space_info(self, info_future):
394431 source .transform = new_coord_space
395432
396433 def toggle_registered_visibility (self , _ ):
397- self .setup_viewer ()
398- # is_registered_visible = s.layers["registered"].visible
399- # s.layers["registered"].visible = not is_registered_visible
434+ if not self .ready :
435+ self .setup_viewer ()
436+ return
437+ with self .viewer .txn () as s :
438+ for layer_name in self .moving_layer_names :
439+ registered_name = layer_name + "_registered"
440+ is_registered_visible = s .layers [registered_name ].visible
441+ s .layers [registered_name ].visible = not is_registered_visible
400442
401443 def setup_viewer_actions (self ):
402444 viewer = self .viewer
@@ -489,6 +531,20 @@ def update_registered_layers(self, s: neuroglancer.ViewerState):
489531 output_dimensions = change_coord_names (v , "2" ),
490532 matrix = transform ,
491533 )
534+ for source in s .layers [k + "_registered" ].source :
535+ source .transform = neuroglancer .CoordinateSpaceTransform (
536+ input_dimensions = v ,
537+ output_dimensions = v ,
538+ matrix = transform ,
539+ )
540+ print (self .combine_affine_across_dims (s , self .affine ).tolist ())
541+ s .layers [self .annotations_name ].source [
542+ 0
543+ ].transform = neuroglancer .CoordinateSpaceTransform (
544+ input_dimensions = create_dimensions (s .dimensions ),
545+ output_dimensions = create_dimensions (s .dimensions ),
546+ matrix = self .combine_affine_across_dims (s , self .affine ).tolist (),
547+ )
492548
493549 # print(s.layers["registered"].source[0].transform.matrix)
494550 # TODO this is where that mapping needs to happen of affine dims
0 commit comments