@@ -441,6 +441,7 @@ def test_write_graph_runs(tmpdir):
441
441
442
442
assert os .path .exists ('graph.dot' ) or os .path .exists (
443
443
'graph_detailed.dot' )
444
+
444
445
try :
445
446
os .remove ('graph.dot' )
446
447
except OSError :
@@ -484,6 +485,164 @@ def test_deep_nested_write_graph_runs(tmpdir):
484
485
pass
485
486
486
487
488
+ # examples of dot files used in the following test
489
+ dotfile_orig = ['strict digraph {\n ' ,
490
+ '"mod1 (engine)";\n ' ,
491
+ '"mod2 (engine)";\n ' ,
492
+ '"mod1 (engine)" -> "mod2 (engine)";\n ' ,
493
+ '}\n ' ]
494
+
495
+ dotfile_detailed_orig = ['digraph structs {\n ' ,
496
+ 'node [shape=record];\n ' ,
497
+ 'pipemod1 [label="{IN}|{ mod1 | engine | }|{OUT|<outoutput1> output1}"];\n ' ,
498
+ 'pipemod2 [label="{IN|<ininput1> input1}|{ mod2 | engine | }|{OUT}"];\n ' ,
499
+ 'pipemod1:outoutput1:e -> pipemod2:ininput1:w;\n ' ,
500
+ '}' ]
501
+
502
+
503
+ dotfile_hierarchical = ['digraph pipe{\n ' ,
504
+ ' label="pipe";\n ' ,
505
+ ' pipe_mod1[label="mod1 (engine)"];\n ' ,
506
+ ' pipe_mod2[label="mod2 (engine)"];\n ' ,
507
+ ' pipe_mod1 -> pipe_mod2;\n ' ,
508
+ '}' ]
509
+
510
+ dotfile_colored = ['digraph pipe{\n ' ,
511
+ ' label="pipe";\n ' ,
512
+ ' pipe_mod1[label="mod1 (engine)", style=filled, fillcolor="#FFFFC8"];\n ' ,
513
+ ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n ' ,
514
+ ' pipe_mod1 -> pipe_mod2;\n ' ,
515
+ '}' ]
516
+
517
+ dotfiles = {
518
+ "orig" : dotfile_orig ,
519
+ "flat" : dotfile_orig ,
520
+ "exec" : dotfile_orig ,
521
+ "hierarchical" : dotfile_hierarchical ,
522
+ "colored" : dotfile_colored
523
+ }
524
+
525
+ @pytest .mark .parametrize ("simple" , [True , False ])
526
+ @pytest .mark .parametrize ("graph_type" , ['orig' , 'flat' , 'exec' , 'hierarchical' , 'colored' ])
527
+ def test_write_graph_dotfile (tmpdir , graph_type , simple ):
528
+ """ checking dot files for a workflow without iterables"""
529
+ tmpdir .chdir ()
530
+
531
+ pipe = pe .Workflow (name = 'pipe' )
532
+ mod1 = pe .Node (interface = EngineTestInterface (), name = 'mod1' )
533
+ mod2 = pe .Node (interface = EngineTestInterface (), name = 'mod2' )
534
+ pipe .connect ([(mod1 , mod2 , [('output1' , 'input1' )])])
535
+ pipe .write_graph (
536
+ graph2use = graph_type , simple_form = simple , format = 'dot' )
537
+
538
+ with open ("graph.dot" ) as f :
539
+ graph_str = f .read ()
540
+
541
+ if simple :
542
+ for line in dotfiles [graph_type ]:
543
+ assert line in graph_str
544
+ else :
545
+ # if simple=False graph.dot uses longer names
546
+ for line in dotfiles [graph_type ]:
547
+ if graph_type in ["hierarchical" , "colored" ]:
548
+ assert line .replace ("mod1 (engine)" , "mod1.EngineTestInterface.engine" ).replace (
549
+ "mod2 (engine)" , "mod2.EngineTestInterface.engine" ) in graph_str
550
+ else :
551
+ assert line .replace (
552
+ "mod1 (engine)" , "pipe.mod1.EngineTestInterface.engine" ).replace (
553
+ "mod2 (engine)" , "pipe.mod2.EngineTestInterface.engine" ) in graph_str
554
+
555
+ # graph_detailed is the same for orig, flat, exec (if no iterables)
556
+ # graph_detailed is not created for hierachical or colored
557
+ if graph_type not in ["hierarchical" , "colored" ]:
558
+ with open ("graph_detailed.dot" ) as f :
559
+ graph_str = f .read ()
560
+ for line in dotfile_detailed_orig :
561
+ assert line in graph_str
562
+
563
+
564
+ # examples of dot files used in the following test
565
+ dotfile_detailed_iter_exec = [
566
+ 'digraph structs {\n ' ,
567
+ 'node [shape=record];\n ' ,
568
+ 'pipemod1aIa1 [label="{IN}|{ a1 | engine | mod1.aI }|{OUT|<outoutput1> output1}"];\n ' ,
569
+ 'pipemod2a1 [label="{IN|<ininput1> input1}|{ a1 | engine | mod2 }|{OUT}"];\n ' ,
570
+ 'pipemod1aIa0 [label="{IN}|{ a0 | engine | mod1.aI }|{OUT|<outoutput1> output1}"];\n ' ,
571
+ 'pipemod2a0 [label="{IN|<ininput1> input1}|{ a0 | engine | mod2 }|{OUT}"];\n ' ,
572
+ 'pipemod1aIa0:outoutput1:e -> pipemod2a0:ininput1:w;\n ' ,
573
+ 'pipemod1aIa1:outoutput1:e -> pipemod2a1:ininput1:w;\n ' ,
574
+ '}' ]
575
+
576
+ dotfile_iter_hierarchical = [
577
+ 'digraph pipe{\n ' ,
578
+ ' label="pipe";\n ' ,
579
+ ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n ' ,
580
+ ' pipe_mod2[label="mod2 (engine)"];\n ' ,
581
+ ' pipe_mod1 -> pipe_mod2;\n ' ,
582
+ '}' ]
583
+
584
+ dotfile_iter_colored = [
585
+ 'digraph pipe{\n ' ,
586
+ ' label="pipe";\n ' ,
587
+ ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n ' ,
588
+ ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n ' ,
589
+ ' pipe_mod1 -> pipe_mod2;\n ' ,
590
+ '}' ]
591
+
592
+ dotfiles_iter = {
593
+ "orig" : dotfile_orig ,
594
+ "flat" : dotfile_orig ,
595
+ "exec" : dotfile_orig ,
596
+ "hierarchical" : dotfile_iter_hierarchical ,
597
+ "colored" : dotfile_iter_colored
598
+ }
599
+
600
+ dotfiles_detailed_iter = {
601
+ "orig" : dotfile_detailed_orig ,
602
+ "flat" : dotfile_detailed_orig ,
603
+ "exec" : dotfile_detailed_iter_exec
604
+ }
605
+
606
+ @pytest .mark .parametrize ("simple" , [True , False ])
607
+ @pytest .mark .parametrize ("graph_type" , ['orig' , 'flat' , 'exec' , 'hierarchical' , 'colored' ])
608
+ def test_write_graph_dotfile_iterables (tmpdir , graph_type , simple ):
609
+ """ checking dot files for a workflow with iterables"""
610
+ tmpdir .chdir ()
611
+
612
+ pipe = pe .Workflow (name = 'pipe' )
613
+ mod1 = pe .Node (interface = EngineTestInterface (), name = 'mod1' )
614
+ mod1 .iterables = ('input1' , [1 , 2 ])
615
+ mod2 = pe .Node (interface = EngineTestInterface (), name = 'mod2' )
616
+ pipe .connect ([(mod1 , mod2 , [('output1' , 'input1' )])])
617
+ pipe .write_graph (
618
+ graph2use = graph_type , simple_form = simple , format = 'dot' )
619
+
620
+ with open ("graph.dot" ) as f :
621
+ graph_str = f .read ()
622
+
623
+ if simple :
624
+ for line in dotfiles_iter [graph_type ]:
625
+ assert line in graph_str
626
+ else :
627
+ # if simple=False graph.dot uses longer names
628
+ for line in dotfiles_iter [graph_type ]:
629
+ if graph_type in ["hierarchical" , "colored" ]:
630
+ assert line .replace ("mod1 (engine)" , "mod1.EngineTestInterface.engine" ).replace (
631
+ "mod2 (engine)" , "mod2.EngineTestInterface.engine" ) in graph_str
632
+ else :
633
+ assert line .replace (
634
+ "mod1 (engine)" , "pipe.mod1.EngineTestInterface.engine" ).replace (
635
+ "mod2 (engine)" , "pipe.mod2.EngineTestInterface.engine" ) in graph_str
636
+
637
+ # graph_detailed is not created for hierachical or colored
638
+ if graph_type not in ["hierarchical" , "colored" ]:
639
+ with open ("graph_detailed.dot" ) as f :
640
+ graph_str = f .read ()
641
+ for line in dotfiles_detailed_iter [graph_type ]:
642
+ assert line in graph_str
643
+
644
+
645
+
487
646
def test_io_subclass ():
488
647
"""Ensure any io subclass allows dynamic traits"""
489
648
from nipype .interfaces .io import IOBase
0 commit comments