diff --git a/docs/basics.rst b/docs/basics.rst index 7ecc4476907c16b8c2c0aacdd6b6e751d51bb5cd..aab879e0354d40d45e3856bc125698e769b17bc0 100644 --- a/docs/basics.rst +++ b/docs/basics.rst @@ -103,11 +103,11 @@ If a workflow has been added without check it can be check later with:: lpad check_wflow -i <firework ID> -Note: The correctness check is recommended for all exercises in the tutorial. +**NOTE:** The correctness check is recommended for all exercises in this tutorial. -View workflows --------------- +Visualize workflows +------------------- Already added workflows can be converted into DOT format and viewed graphically as PDF:: @@ -134,10 +134,14 @@ To run all fireworks in *READY* state in a sequence:: rlaunch rapidfire -Note: Every firework changes its state to *READY* after all its dependency fireworks -are completed (state *COMPLETED*) and the states of linked child fireworks are updated -as soon as a firework if completed. This means that any workflow will be run until -there are no more fireworks in *READY* state. +**NOTE:** Every firework changes its state to *READY* after all its parent +fireworks are completed (state *COMPLETED*) and the states of linked child +fireworks are updated as soon as a firework if completed. This means that any +workflow will be run until there are no more fireworks in *READY* state. + +**NOTE:** In singleshot mode ``rlaunch`` runs the firework in the directory where it is +started. In rapidfire mode ``rlaunch`` creates a runtime sibdirectory one per firework +and executes each firework in a separate directory. To suppress verbose information on the screen the *-s* flag can be added:: @@ -155,13 +159,13 @@ To query individual fireworks use the command:: lpad get_fws [-i <firework ID> [-d <more|all>]] -Note: The query from the command line is recommended for thi tutorial. +Note: The query from the command line is recommended in this tutorial. Alternatively the web GUI can be used:: lpad webgui -Note: Make sure that a web browser is configured in your terminal session and an +**NOTE:** Make sure that a web browser is configured in your terminal session and an X server is running on your machine and it is configured and tunneled properly in your terminal session. diff --git a/docs/exercise5.rst b/docs/exercise5.rst index 762cd3ca904464b3ee636e27a26789a4e4d060d0..affaf23e2900a1351698233ea521076a99711f2b 100644 --- a/docs/exercise5.rst +++ b/docs/exercise5.rst @@ -1,12 +1,111 @@ -.. _exercise5: - Exercise 5: Writing a Firetask ============================== +This exercise bases on an extended version of the example from **Exercise 2**. +It is implemented as a python script +**exercises/problems/5_author_firetask/recruiting-script.py**. It has two new aspects: + + 1. All parameters are loaded at the beginning from a JSON document + **parameters.json**. + 2. The steps candidates_apply() and screen_candidates() are repeated as long + as the size of the canditate list is smaller than ``number_to_invite``. + + +Anatomy of Firetasks +-------------------- + +All firetasks are classes derived from the ``FiretaskBase`` class. Many built-in +Firetasks are available in the upstream FireWorks, such as the ``ScriptTask``, +``PyTask``, FileTransferTask. Additional firetasks can be written for both +generic and specific purposes. + +The skeleton of a Firetask looks like this:: + + from fireworks.core.firework import FiretaskBase, FWAction + from fireworks.utilities.fw_utilities import explicit_serialize + + @explicit_serialize + class MyFiretask(FiretaskBase): + """ My new Firetask """ + + _fw_name = 'MyFiretask' + required_params = ['par1', 'par2'] + optional_params = ['optional par'] + + def run_task(self, fw_spec): + """ + This is the method called upon Firetask execution. It has access + to the spec through the fw_spec parameter. The required and the + optional parameters are accessed through self, i.e. they are class + attributes. Optionally this function returns a FWAction object to pass + data to next Firetasks and Fireworks and/or to dynamically modify the + workflow. + """ + + print(self[par1], self[par2]) # print the values of required params + print(self.fw_spec['name']) # print the name of the Firework + + if self.get('optional par'): + actions = [ + 'update_spec': { + 'par1': self[par1], + 'optional par': self['optional par'] + } + ] + else: + actions = [] + + return FWAction(*actions) + +Here a firework using this firetask:: + + - fw_id: 1 + name: Sample firework + spec: + _tasks: + - _fw_name: {{custom_tasks.MyFiretask}} + par1: data.json + par2: data.yaml + optional par: {} + + +**NOTE**: the python module ``custom_tasks`` must be in $PYTHONPATH in order to +be correctly registered. For this reason keep the file **custom_tasks.py** either +in **lib** or in **exercises/work/5_author_firetask** where you start the ``lpad`` +and ``rlaunch`` commands. In the latter case you should add that directory to +$PYTHONPATH with:: + + export PYTHONPATH=`pwd`:$PYTHONPATH + + +Problem 5.1: Data Loader Task +----------------------------- + +Write a DataLoaderTask to load the necessary parameters from the JSON document. +If necessary the input data structure can be split into more than one file. +The resulting workflow, which is given in **dataloader.json**, must be successfully +running with no further modifications. + +**Hint**: You can use the ``load()`` method from the ``json`` package to load +JSON documents as list or dictionaries and then return a ``FWAction`` object +with ``update_spec`` and the structure (see above example). + -A. Data Loader Task +Problem 5.2: Conditional Repeater Task +-------------------------------------- -A firetask has to be written to realize the given workflow. +Write a RepeatIfLengthLesser firetask that can implement the while loop in the +script. The firetask should integrate into the workflow available in +**dataloader+repeater.json** without further adaptations. +Hint: You can use the ``load_object`` function from +``fireworks.utilities.fw_serializers`` to construct a firework object and +the ``detours`` keyword argument of ``FWAction`` `to insert the firework +dynamically:: -B. While-task \ No newline at end of file + firework = Firework( + tasks=[load_object(task) for task in fw_spec['_tasks']], + spec=fw_spec, + name='repeat '+self['measure'] + ) + return FWAction(detours=firework) \ No newline at end of file