1+ # ' Helper function for processing coordination dictionaries
2+ # '
3+ # ' @keywords internal
4+ # ' @param scopes The coordination scopes to process.
5+ # ' @param coordination_scopes The coordination scopes object to update.
6+ # ' @param coordination_scopes_by The coordination scopes by object to update.
7+ # ' @return A list containing updated coordination_scopes and coordination_scopes_by.
8+ use_coordination_by_dict_helper <- function (scopes , coordination_scopes , coordination_scopes_by ) {
9+ # Recursive inner function
10+ process_level <- function (parent_type , parent_scope , level_type , level_val ) {
11+ if (is.list(level_val ) && ! inherits(level_val , " VitessceConfigCoordinationScope" )) {
12+ # Check if this is a list of coordination objects
13+ all_have_scope <- all(sapply(level_val , function (x ) is.list(x ) && " scope" %in% names(x )))
14+ if (all_have_scope ) {
15+ # This is a list of coordination objects
16+ if (is.null(coordination_scopes_by [[parent_type ]])) coordination_scopes_by [[parent_type ]] <- list ()
17+ if (is.null(coordination_scopes_by [[parent_type ]][[level_type ]])) coordination_scopes_by [[parent_type ]][[level_type ]] <- list ()
18+ coordination_scopes_by [[parent_type ]][[level_type ]][[parent_scope $ c_scope ]] <- sapply(level_val , function (child_val ) child_val [[" scope" ]]$ c_scope )
19+
20+ for (child_val in level_val ) {
21+ if (" children" %in% names(child_val )) {
22+ # Continue recursion
23+ for (next_level_type in names(child_val [[" children" ]])) {
24+ next_level_val <- child_val [[" children" ]][[next_level_type ]]
25+ process_level(level_type , child_val [[" scope" ]], next_level_type , next_level_val )
26+ }
27+ }
28+ }
29+ }
30+ } else {
31+ # Single coordination object
32+ if (is.null(coordination_scopes_by [[parent_type ]])) coordination_scopes_by [[parent_type ]] <- list ()
33+ if (is.null(coordination_scopes_by [[parent_type ]][[level_type ]])) coordination_scopes_by [[parent_type ]][[level_type ]] <- list ()
34+ coordination_scopes_by [[parent_type ]][[level_type ]][[parent_scope $ c_scope ]] <- level_val [[" scope" ]]$ c_scope
35+
36+ if (" children" %in% names(level_val )) {
37+ # Continue recursion
38+ for (next_level_type in names(level_val [[" children" ]])) {
39+ next_level_val <- level_val [[" children" ]][[next_level_type ]]
40+ process_level(level_type , level_val [[" scope" ]], next_level_type , next_level_val )
41+ }
42+ }
43+ }
44+ }
45+
46+ # Process top-level coordination types
47+ for (top_level_type in names(scopes )) {
48+ top_level_val <- scopes [[top_level_type ]]
49+
50+ if (is.list(top_level_val ) && ! inherits(top_level_val , " VitessceConfigCoordinationScope" )) {
51+ # Check if this is a list of coordination objects
52+ all_have_scope <- all(sapply(top_level_val , function (x ) is.list(x ) && " scope" %in% names(x )))
53+ if (all_have_scope ) {
54+ coordination_scopes [[top_level_type ]] <- sapply(top_level_val , function (level_val ) level_val [[" scope" ]]$ c_scope )
55+
56+ for (level_val in top_level_val ) {
57+ if (" children" %in% names(level_val )) {
58+ # Begin recursion
59+ for (next_level_type in names(level_val [[" children" ]])) {
60+ next_level_val <- level_val [[" children" ]][[next_level_type ]]
61+ process_level(top_level_type , level_val [[" scope" ]], next_level_type , next_level_val )
62+ }
63+ }
64+ }
65+ } else {
66+ # Single coordination object - handle the case where it's a simple list with scope
67+ if (" scope" %in% names(top_level_val )) {
68+ coordination_scopes [[top_level_type ]] <- top_level_val [[" scope" ]]$ c_scope
69+ if (" children" %in% names(top_level_val )) {
70+ # Begin recursion
71+ for (next_level_type in names(top_level_val [[" children" ]])) {
72+ next_level_val <- top_level_val [[" children" ]][[next_level_type ]]
73+ process_level(top_level_type , top_level_val [[" scope" ]], next_level_type , next_level_val )
74+ }
75+ }
76+ }
77+ }
78+ }
79+ }
80+
81+ return (list (coordination_scopes = coordination_scopes , coordination_scopes_by = coordination_scopes_by ))
82+ }
83+
184# ' Get next scope name
285# '
386# ' @keywords internal
@@ -280,7 +363,7 @@ VitessceConfigMetaCoordinationScope <- R6::R6Class("VitessceConfigMetaCoordinati
280363 self $ meta_by_scope = VitessceConfigCoordinationScope $ new(CoordinationType $ META_COORDINATION_SCOPES_BY , meta_by_scope )
281364 },
282365 use_coordination = function (c_scopes ) {
283- if (is.na(self $ meta_scope4c_value )) {
366+ if (is.na(self $ meta_scope $ c_value )) {
284367 self $ meta_scope $ set_value(obj_list())
285368 }
286369
@@ -292,7 +375,23 @@ VitessceConfigMetaCoordinationScope <- R6::R6Class("VitessceConfigMetaCoordinati
292375 invisible (self )
293376 },
294377 use_coordination_by_dict = function (scopes ) {
295- # TODO
378+ if (is.na(self $ meta_scope $ c_value )) {
379+ self $ meta_scope $ set_value_raw(obj_list())
380+ }
381+
382+ if (is.na(self $ meta_by_scope $ c_value )) {
383+ self $ meta_by_scope $ set_value_raw(obj_list())
384+ }
385+
386+ result <- use_coordination_by_dict_helper(
387+ scopes ,
388+ self $ meta_scope $ c_value ,
389+ self $ meta_by_scope $ c_value
390+ )
391+
392+ self $ meta_scope $ set_value_raw(result $ coordination_scopes )
393+ self $ meta_by_scope $ set_value_raw(result $ coordination_scopes_by )
394+
296395 invisible (self )
297396 }
298397 )
@@ -384,11 +483,48 @@ VitessceConfigView <- R6::R6Class("VitessceConfigView",
384483 invisible (self )
385484 },
386485 use_coordination_by_dict = function (scopes ) {
387- # TODO
486+ if (is.null(private $ view $ coordinationScopes )) {
487+ private $ view $ coordinationScopes <- list ()
488+ }
489+
490+ if (is.null(private $ view $ coordinationScopesBy )) {
491+ private $ view $ coordinationScopesBy <- list ()
492+ }
493+
494+ result <- use_coordination_by_dict_helper(
495+ scopes ,
496+ private $ view $ coordinationScopes ,
497+ private $ view $ coordinationScopesBy
498+ )
499+
500+ private $ view $ coordinationScopes <- result $ coordination_scopes
501+ private $ view $ coordinationScopesBy <- result $ coordination_scopes_by
502+
388503 invisible (self )
389504 },
390505 use_meta_coordination = function (meta_scope ) {
391- # TODO
506+ if (is.null(private $ view $ coordinationScopes )) {
507+ private $ view $ coordinationScopes <- list ()
508+ }
509+
510+ # Initialize as empty lists if they don't exist
511+ if (is.null(private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES ]])) {
512+ private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES ]] <- list ()
513+ }
514+ if (is.null(private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES_BY ]])) {
515+ private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES_BY ]] <- list ()
516+ }
517+
518+ # Append the new meta scope values
519+ private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES ]] <- c(
520+ private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES ]],
521+ meta_scope $ meta_scope $ c_scope
522+ )
523+ private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES_BY ]] <- c(
524+ private $ view $ coordinationScopes [[CoordinationType $ META_COORDINATION_SCOPES_BY ]],
525+ meta_scope $ meta_by_scope $ c_scope
526+ )
527+
392528 invisible (self )
393529 },
394530 # ' @description
@@ -557,13 +693,100 @@ VitessceConfig <- R6::R6Class("VitessceConfig",
557693 result
558694 },
559695 add_meta_coordination = function () {
560- # TODO
696+ prev_meta_scopes <- names(self $ config $ coordinationSpace [[CoordinationType $ META_COORDINATION_SCOPES ]])
697+ prev_meta_by_scopes <- names(self $ config $ coordinationSpace [[CoordinationType $ META_COORDINATION_SCOPES_BY ]])
698+
699+ if (is.null(prev_meta_scopes )) prev_meta_scopes <- character ()
700+ if (is.null(prev_meta_by_scopes )) prev_meta_by_scopes <- character ()
701+
702+ meta_container <- VitessceConfigMetaCoordinationScope $ new(
703+ get_next_scope(prev_meta_scopes ),
704+ get_next_scope(prev_meta_by_scopes )
705+ )
706+
707+ if (! is.element(CoordinationType $ META_COORDINATION_SCOPES , names(self $ config $ coordinationSpace ))) {
708+ self $ config $ coordinationSpace [[CoordinationType $ META_COORDINATION_SCOPES ]] <- list ()
709+ }
710+ if (! is.element(CoordinationType $ META_COORDINATION_SCOPES_BY , names(self $ config $ coordinationSpace ))) {
711+ self $ config $ coordinationSpace [[CoordinationType $ META_COORDINATION_SCOPES_BY ]] <- list ()
712+ }
713+
714+ self $ config $ coordinationSpace [[CoordinationType $ META_COORDINATION_SCOPES ]][[meta_container $ meta_scope $ c_scope ]] <- meta_container $ meta_scope
715+ self $ config $ coordinationSpace [[CoordinationType $ META_COORDINATION_SCOPES_BY ]][[meta_container $ meta_by_scope $ c_scope ]] <- meta_container $ meta_by_scope
716+
717+ meta_container
561718 },
562719 add_coordination_by_dict = function (input_val ) {
563- # TODO
720+ # Recursive function to process each level
721+ process_level <- function (level ) {
722+ result <- list ()
723+ if (is.null(level )) {
724+ return (result )
725+ }
726+
727+ for (c_type in names(level )) {
728+ next_level_or_initial_value <- level [[c_type ]]
729+
730+ # Check if value is a CoordinationLevel instance
731+ if (inherits(next_level_or_initial_value , " CoordinationLevel" )) {
732+ next_level <- next_level_or_initial_value $ value
733+ if (is.list(next_level )) {
734+ if (next_level_or_initial_value $ is_cached()) {
735+ result [[c_type ]] <- next_level_or_initial_value $ get_cached()
736+ } else {
737+ processed_level <- lapply(next_level , function (next_el ) {
738+ dummy_scopes <- self $ add_coordination(c_type )
739+ dummy_scope <- dummy_scopes [[1 ]]
740+ dummy_scope $ set_value(" __dummy__" )
741+ list (
742+ scope = dummy_scope ,
743+ children = process_level(next_el )
744+ )
745+ })
746+ next_level_or_initial_value $ set_cached(processed_level )
747+ result [[c_type ]] <- processed_level
748+ }
749+ } else {
750+ stop(" Expected CoordinationLevel$value to be a list." )
751+ }
752+ } else {
753+ # Base case
754+ initial_value <- next_level_or_initial_value
755+ if (inherits(initial_value , " VitessceConfigCoordinationScope" )) {
756+ result [[c_type ]] <- list (scope = initial_value )
757+ } else {
758+ scopes <- self $ add_coordination(c_type )
759+ scope <- scopes [[1 ]]
760+ scope $ set_value(initial_value )
761+ result [[c_type ]] <- list (scope = scope )
762+ }
763+ }
764+ }
765+ return (result )
766+ }
767+
768+ # Begin recursion
769+ output_val <- process_level(input_val )
770+ return (output_val )
564771 },
565- link_views_by_dict = function (views , input_val , meta = TRUE ) {
566- # TODO
772+ link_views_by_dict = function (views , input_val , meta = TRUE , scope_prefix = NA ) {
773+ # TODO: implement scope_prefix functionality similar to Python version
774+ scopes <- self $ add_coordination_by_dict(input_val )
775+
776+ if (meta ) {
777+ meta_scope <- self $ add_meta_coordination()
778+ meta_scope $ use_coordination_by_dict(scopes )
779+
780+ for (view in views ) {
781+ view $ use_meta_coordination(meta_scope )
782+ }
783+ } else {
784+ for (view in views ) {
785+ view $ use_coordination_by_dict(scopes )
786+ }
787+ }
788+
789+ invisible (self )
567790 },
568791 # ' @description
569792 # ' Define the layout of views.
0 commit comments