@@ -65,8 +65,8 @@ setMethod(f = "dag_execute",
6565 # Check that all nodes are valid
6666 for (node_name in names(nodes )) {
6767 node = nodes [[node_name ]]
68- if (! is(node , ' model_node' ) && ! is(node , ' data_node' ) && ! is(node , ' prediction_node' )) {
69- stop(' Node "' , node_name , ' " must be a model_node, data_node, or prediction_node object' )
68+ if (! is(node , ' model_node' ) && ! is(node , ' data_node' ) && ! is(node , ' prediction_node' ) && ! is( node , ' chart_node ' ) ) {
69+ stop(' Node "' , node_name , ' " must be a model_node, data_node, prediction_node, or chart_node object' )
7070 }
7171 }
7272
@@ -333,6 +333,93 @@ setMethod(f = "dag_execute",
333333 cat(' Model output: ' , class(result )[1 ], ' \n ' )
334334 }
335335 }
336+ } else if (is(current_node , ' chart_node' )) {
337+ # Chart nodes: execute chart_plot
338+
339+ # Find all input objects for this node
340+ input_objects = list ()
341+
342+ # Look for edges pointing to this node
343+ for (edge in dag $ edges ) {
344+ if (edge $ to == current ) {
345+ from_node = edge $ from
346+ from_param = edge $ from_param
347+ to_param = edge $ to_param
348+
349+ if (from_node %in% names(results )) {
350+ from_output = results [[from_node ]]
351+ from_node_obj = nodes [[from_node ]]
352+
353+ # Handle different from_param values
354+ if (from_param == " asis" || is.null(from_param )) {
355+ # Pass the object as-is (for data nodes)
356+ input_value = from_output
357+ } else if (from_param == " predicted" ) {
358+ # Use predicted() output (for model nodes to other model nodes)
359+ if (is(from_output , ' struct_class' ) && is(from_output , ' model' )) {
360+ tryCatch({
361+ input_value = predicted(from_output )
362+ }, error = function (e ) {
363+ stop(' Failed to get predicted output from ' , from_node , ' : ' , e $ message )
364+ })
365+ } else {
366+ stop(' Cannot get predicted output from non-model node: ' , from_node )
367+ }
368+ } else {
369+ # Use named slot/parameter
370+ if (is(from_output , ' struct_class' )) {
371+ tryCatch({
372+ input_value = from_output [[from_param ]]
373+ }, error = function (e ) {
374+ stop(' Failed to get parameter "' , from_param , ' " from ' , from_node , ' : ' , e $ message )
375+ })
376+ } else {
377+ stop(' Cannot get parameter from non-struct object: ' , from_node )
378+ }
379+ }
380+
381+ # Handle different to_param values for chart nodes
382+ if (to_param == " input_object" || is.null(to_param )) {
383+ # Add to input_objects list in order
384+ input_objects = c(input_objects , list (input_value ))
385+ } else {
386+ # Set named parameter for the chart
387+ chart_obj = chart(current_node )
388+ chart_obj [[to_param ]] = input_value
389+ current_node @ chart = chart_obj
390+ }
391+ }
392+ }
393+ }
394+
395+ # Set the input_objects for the current node
396+ current_node @ input_objects = input_objects
397+
398+ if (verbose ) {
399+ cat(' Executing chart: ' , class(chart(current_node ))[1 ], ' with chart_plot\n ' )
400+ }
401+
402+ # Execute the chart using chart_plot
403+ chart_obj = chart(current_node )
404+
405+ # Call chart_plot with the chart object and input objects
406+ if (length(input_objects ) == 0 ) {
407+ # No input objects, just call chart_plot with the chart
408+ result = chart_plot(chart_obj )
409+ } else if (length(input_objects ) == 1 ) {
410+ # Single input object
411+ result = chart_plot(chart_obj , input_objects [[1 ]])
412+ } else {
413+ # Multiple input objects - use do.call to pass them as arguments
414+ result = do.call(chart_plot , c(list (chart_obj ), input_objects ))
415+ }
416+
417+ # Store the result (chart_plot returns a plot object)
418+ results [[current ]] = result
419+
420+ if (verbose ) {
421+ cat(' Chart output: plot object of class ' , class(result )[1 ], ' \n ' )
422+ }
336423 }
337424
338425 # Update in-degrees and add new sources to queue
0 commit comments