/doc/tutorials/manual/follows.rst

https://code.google.com/p/ruffus/ · ReStructuredText · 193 lines · 123 code · 70 blank · 0 comment · 0 complexity · 7d9ac29be38e4e6cfae820c102cf4fc4 MD5 · raw file

  1. .. include:: ../../global.inc
  2. .. include:: chapter_numbers.inc
  3. .. _manual.follows:
  4. #################################################################################################
  5. |manual.follows.chapter_num| : `Arranging tasks into a pipeline with` **@follows**
  6. #################################################################################################
  7. * :ref:`Manual overview <manual>`
  8. * :ref:`@follows syntax in detail <decorators.follows>`
  9. .. index::
  10. pair: @follows; Manual
  11. ***************************************
  12. **@follows**
  13. ***************************************
  14. The order in which stages or :term:`task`\ s of a pipeline are arranged are set
  15. explicitly by the :ref:`@follows(...) <decorators.follows>` python decorator:
  16. ::
  17. from ruffus import *
  18. import sys
  19. def first_task():
  20. print "First task"
  21. @follows(first_task)
  22. def second_task():
  23. print "Second task"
  24. @follows(second_task)
  25. def final_task():
  26. print "Final task"
  27. the ``@follows`` decorator indicate that the ``first_task`` function precedes ``second_task`` in
  28. the pipeline.
  29. .. note::
  30. We shall see in :ref:`Chapter 2 <manual.tasks_as_input>` that the order of pipeline :term:`task`\ s can also be inferred implicitly
  31. for the following decorators
  32. * :ref:`@split(...) <manual.split>`
  33. * :ref:`@transform(...) <manual.transform>`
  34. * :ref:`@merge(...) <manual.merge>`
  35. * :ref:`@collate(...) <manual.collate>`
  36. .. index::
  37. pair: pipeline_run; Manual
  38. =====================
  39. Running
  40. =====================
  41. Now we can run the pipeline by:
  42. ::
  43. pipeline_run([final_task])
  44. Because ``final_task`` depends on ``second_task`` which depends on ``first_task`` , all
  45. three functions will be executed in order.
  46. .. index::
  47. pair: pipeline_printout_graph; Manual
  48. pair: pipeline_printout; Manual
  49. =====================
  50. Displaying
  51. =====================
  52. We can see a flowchart of our fledgling pipeline by executing:
  53. ::
  54. pipeline_printout_graph ( "manual_follows1.png",
  55. "png",
  56. [final_task],
  57. no_key_legend=True)
  58. producing the following flowchart
  59. .. image:: ../../images/manual_follows1.png
  60. or in text format with:
  61. ::
  62. pipeline_printout(sys.stdout, [final_task])
  63. which produces the following:
  64. ::
  65. Task = first_task
  66. Task = second_task
  67. Task = final_task
  68. .. index::
  69. pair: @follows; referring to functions before they are defined
  70. pair: @follows; out of order
  71. .. _manual.follows.out_of_order:
  72. ***************************************
  73. Defining pipeline tasks out of order
  74. ***************************************
  75. All this assumes that all your pipelined tasks are defined in order.
  76. (``first_task`` before ``second_task`` before ``final_task``)
  77. | This is usually the most sensible way to arrange your code.
  78. If you wish to refer to tasks which are not yet defined, you can do so by quoting the function name as a string:
  79. ::
  80. @follows("second_task")
  81. def final_task():
  82. print "Final task"
  83. You can refer to tasks (functions) in other modules, in which case the full
  84. qualified name must be used:
  85. ::
  86. @follows("other_module.second_task")
  87. def final_task():
  88. print "Final task"
  89. .. index::
  90. pair: @follows; multiple dependencies
  91. .. _manual.follows.multiple_dependencies:
  92. ***************************************
  93. Multiple dependencies
  94. ***************************************
  95. Each task can depend on more than one antecedent task.
  96. This can be indicated either by stacking ``@follows``:
  97. ::
  98. @follows(first_task)
  99. @follows("second_task")
  100. def final_task():
  101. ""
  102. or in a more concise way:
  103. ::
  104. @follows(first_task, "second_task")
  105. def final_task():
  106. ""
  107. .. _manual.follows.mkdir:
  108. .. index::
  109. single: @follows; mkdir (Manual)
  110. single: mkdir; @follows (Manual)
  111. ******************************************************************************
  112. Making directories automatically with :ref:`mkdir <decorators.mkdir>`
  113. ******************************************************************************
  114. A common prerequisite for any computational task, is making sure that the destination
  115. directories exist.
  116. **Ruffus** provides special syntax to support this, using the special
  117. :ref:`mkdir <decorators.mkdir>` dependency. For example:
  118. ::
  119. @follows(first_task, mkdir("output/results/here"))
  120. def second_task():
  121. print "Second task"
  122. will make sure that ``output/results/here`` exists before `second_task` is run.
  123. In other words, it will make the ``output/results/here`` directory if it does not exist.