|
9 | 9 | from builtins import open
|
10 | 10 | from copy import deepcopy
|
11 | 11 | from glob import glob
|
12 |
| -import os |
| 12 | +import os, pdb |
13 | 13 |
|
14 | 14 |
|
15 | 15 | import pytest
|
@@ -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,147 @@ 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 | +dotfile_flat = dotfile_orig |
| 503 | +dotfile_detailed_flat = dotfile_detailed_orig |
| 504 | + |
| 505 | +dotfile_exec = dotfile_orig |
| 506 | +dotfile_detailed_exec = dotfile_detailed_orig |
| 507 | + |
| 508 | + |
| 509 | +dotfile_hierarchical = ('digraph pipe{\n' |
| 510 | + ' label="pipe";\n' |
| 511 | + ' pipe_mod1[label="mod1 (engine)"];\n' |
| 512 | + ' pipe_mod2[label="mod2 (engine)"];\n' |
| 513 | + ' pipe_mod1 -> pipe_mod2;\n' |
| 514 | + '}') |
| 515 | + |
| 516 | +dotfile_colored = ('digraph pipe{\n' |
| 517 | + ' label="pipe";\n' |
| 518 | + ' pipe_mod1[label="mod1 (engine)", style=filled, fillcolor="#FFFFC8"];\n' |
| 519 | + ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n' |
| 520 | + ' pipe_mod1 -> pipe_mod2;\n' |
| 521 | + '}') |
| 522 | + |
| 523 | +@pytest.mark.parametrize("simple", [True, False]) |
| 524 | +@pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) |
| 525 | +def test_write_graph_dotfile(tmpdir, graph_type, simple): |
| 526 | + """ checking dot files for a workflow without iterables""" |
| 527 | + tmpdir.chdir() |
| 528 | + |
| 529 | + pipe = pe.Workflow(name='pipe') |
| 530 | + mod1 = pe.Node(interface=EngineTestInterface(), name='mod1') |
| 531 | + mod2 = pe.Node(interface=EngineTestInterface(), name='mod2') |
| 532 | + pipe.connect([(mod1, mod2, [('output1', 'input1')])]) |
| 533 | + pipe.write_graph( |
| 534 | + graph2use=graph_type, simple_form=simple, format='dot') |
| 535 | + |
| 536 | + with open("graph.dot") as f: |
| 537 | + graph_str = f.read() |
| 538 | + if simple: |
| 539 | + assert graph_str == eval("dotfile_{}".format(graph_type)) |
| 540 | + else: |
| 541 | + # if simple=False graph.dot uses longer names |
| 542 | + if graph_type in ["hierarchical", "colored"]: |
| 543 | + assert graph_str == eval("dotfile_{}".format(graph_type)).replace( |
| 544 | + "mod1 (engine)", "mod1.EngineTestInterface.engine").replace( |
| 545 | + "mod2 (engine)", "mod2.EngineTestInterface.engine") |
| 546 | + else: |
| 547 | + assert graph_str == eval("dotfile_{}".format(graph_type)).replace( |
| 548 | + "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( |
| 549 | + "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") |
| 550 | + |
| 551 | + # graph_detailed is not created for hierachical or colored |
| 552 | + if graph_type not in ["hierarchical", "colored"]: |
| 553 | + with open("graph_detailed.dot") as f: |
| 554 | + graph_str =f.read() |
| 555 | + assert graph_str == eval("dotfile_detailed_{}".format(graph_type)) |
| 556 | + |
| 557 | + |
| 558 | +# examples of dot files used in the following test |
| 559 | +dotfile_iter_orig = dotfile_orig |
| 560 | +dotfile_detailed_iter_orig = dotfile_detailed_orig |
| 561 | + |
| 562 | +dotfile_iter_flat = dotfile_orig |
| 563 | +dotfile_detailed_iter_flat = dotfile_detailed_orig |
| 564 | + |
| 565 | +dotfile_iter_exec = dotfile_orig |
| 566 | +dotfile_detailed_iter_exec = ( |
| 567 | + 'digraph structs {\n' |
| 568 | + 'node [shape=record];\n' |
| 569 | + 'pipemod1aIa1 [label="{IN}|{ a1 | engine | mod1.aI }|{OUT|<outoutput1> output1}"];\n' |
| 570 | + 'pipemod2a1 [label="{IN|<ininput1> input1}|{ a1 | engine | mod2 }|{OUT}"];\n' |
| 571 | + 'pipemod1aIa0 [label="{IN}|{ a0 | engine | mod1.aI }|{OUT|<outoutput1> output1}"];\n' |
| 572 | + 'pipemod2a0 [label="{IN|<ininput1> input1}|{ a0 | engine | mod2 }|{OUT}"];\n' |
| 573 | + 'pipemod1aIa0:outoutput1:e -> pipemod2a0:ininput1:w;\n' |
| 574 | + 'pipemod1aIa1:outoutput1:e -> pipemod2a1:ininput1:w;\n' |
| 575 | + '}') |
| 576 | + |
| 577 | +dotfile_iter_hierarchical = ( |
| 578 | + 'digraph pipe{\n' |
| 579 | + ' label="pipe";\n' |
| 580 | + ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n' |
| 581 | + ' pipe_mod2[label="mod2 (engine)"];\n' |
| 582 | + ' pipe_mod1 -> pipe_mod2;\n' |
| 583 | + '}') |
| 584 | + |
| 585 | +dotfile_iter_colored = ( |
| 586 | + 'digraph pipe{\n' |
| 587 | + ' label="pipe";\n' |
| 588 | + ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n' |
| 589 | + ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n' |
| 590 | + ' pipe_mod1 -> pipe_mod2;\n' |
| 591 | + '}') |
| 592 | + |
| 593 | +@pytest.mark.parametrize("simple", [True, False]) |
| 594 | +@pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) |
| 595 | +def test_write_graph_dotfile_iterables(tmpdir, graph_type, simple): |
| 596 | + """ checking dot files for a workflow with iterables""" |
| 597 | + tmpdir.chdir() |
| 598 | + |
| 599 | + pipe = pe.Workflow(name='pipe') |
| 600 | + mod1 = pe.Node(interface=EngineTestInterface(), name='mod1') |
| 601 | + mod1.iterables = ('input1', [1, 2]) |
| 602 | + mod2 = pe.Node(interface=EngineTestInterface(), name='mod2') |
| 603 | + pipe.connect([(mod1, mod2, [('output1', 'input1')])]) |
| 604 | + pipe.write_graph( |
| 605 | + graph2use=graph_type, simple_form=simple, format='dot') |
| 606 | + |
| 607 | + with open("graph.dot") as f: |
| 608 | + graph_str = f.read() |
| 609 | + if simple: |
| 610 | + assert graph_str == eval("dotfile_iter_{}".format(graph_type)) |
| 611 | + else: |
| 612 | + # if simple=False graph.dot uses longer names |
| 613 | + if graph_type in ["hierarchical", "colored"]: |
| 614 | + assert graph_str == eval("dotfile_iter_{}".format(graph_type)).replace( |
| 615 | + "mod1 (engine)", "mod1.EngineTestInterface.engine").replace( |
| 616 | + "mod2 (engine)", "mod2.EngineTestInterface.engine") |
| 617 | + else: |
| 618 | + assert graph_str == eval("dotfile_iter_{}".format(graph_type)).replace( |
| 619 | + "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( |
| 620 | + "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") |
| 621 | + |
| 622 | + # graph_detailed is not created for hierachical or colored |
| 623 | + if graph_type not in ["hierarchical", "colored"]: |
| 624 | + with open("graph_detailed.dot") as f: |
| 625 | + graph_str =f.read() |
| 626 | + assert graph_str == eval("dotfile_detailed_iter_{}".format(graph_type)) |
| 627 | + |
| 628 | + |
487 | 629 | def test_io_subclass():
|
488 | 630 | """Ensure any io subclass allows dynamic traits"""
|
489 | 631 | from nipype.interfaces.io import IOBase
|
|
0 commit comments