Creating a new Leginon node » History » Version 11
Anchi Cheng, 09/15/2014 07:25 PM
1 | 1 | Jim Pulokas | h1. Creating a new Leginon node |
---|---|---|---|
2 | |||
3 | The basic steps that will be described in detail below are: |
||
4 | |||
5 | 6 | Anchi Cheng | * Code the core functionality in a new subclass |
6 | * Define required attribute for all node classes: |
||
7 | ** Node Settings and its defaults |
||
8 | ** GUI Panel |
||
9 | ** Input/Output Events |
||
10 | * Define new data type or event this node produces |
||
11 | * Make the gui |
||
12 | 1 | Jim Pulokas | * register it with the list of available nodes |
13 | |||
14 | 5 | Jim Pulokas | For each task, it is easiest to look at an existing node as an example. Usually we just make a copy of a node the is similar in function and go from there. |
15 | 1 | Jim Pulokas | |
16 | 6 | Anchi Cheng | h2. Example |
17 | 1 | Jim Pulokas | |
18 | 6 | Anchi Cheng | We have a base class in Leginon that creates a node to fix a particular instrument condition. The module is leginon/condition.py. When a FixConditionEvent is sent to it, it will check the database to find whether the condition fixing has been done recently. If it has past the timeout defined in its settings (Defined by ConditionerSettingsData in leginondata.py), then it will execute the action defined in its fixCondition function, and reset the timer. |
19 | 5 | Jim Pulokas | |
20 | 6 | Anchi Cheng | The FixConditionEvent is sent normally from the final exposure Acquisition Node (named "Exposure", "Tomography" etc. depending on the node class and application". While the condition is being fixed, the node will wait for it to return before starting to process the targets it received (meaning moving to the acquisition position, focusing, etc). |
21 | |||
22 | To make a new subclass that triggers the vacuum pump that pumps the buffer area of the scope, we will make a subclass of Conditioner here, called BufferCycler. There is no settings change, but we want its settings saved separately from the parent. |
||
23 | |||
24 | 1 | Jim Pulokas | h2. Code the core functionality |
25 | |||
26 | 6 | Anchi Cheng | * Make a new class in your new module. Let it inherit a class of Leginon nodes. The lowest base class you can use is node.Node |
27 | 1 | Jim Pulokas | |
28 | 6 | Anchi Cheng | In our example, see leginon/buffercycler.py source:trunk/leginon/buffercycler.py |
29 | |||
30 | The new class inherits conditioner.Conditioner. It defines the string for condition type in setCTypes, and how to call buffer cycling. |
||
31 | |||
32 | 8 | Anchi Cheng | h2. Define the required attributes for all nodes |
33 | 6 | Anchi Cheng | |
34 | h3. Settings |
||
35 | |||
36 | * The data class that is usually added when a new node is added is the one defines its settings in Leginon gui. Its name should have the class name as prefix. |
||
37 | * To make the class uses the new settings class, it is defined in the module. |
||
38 | |||
39 | 9 | Anchi Cheng | In our example: |
40 | |||
41 | # Look at the difference in leginon/leginondata.py for r18567, a new subclass of ConditionerSettingsData is defined as BufferCyclerSettingsData without adding anything new. |
||
42 | # We define the settings class used in buffercycler.py |
||
43 | 6 | Anchi Cheng | <pre> |
44 | settingsclass = leginondata.BufferCyclerSettingsData |
||
45 | </pre> |
||
46 | # The defaults of the buffer cycler settings are also inherited from conditioner.Conditioner |
||
47 | 7 | Anchi Cheng | <pre> |
48 | 6 | Anchi Cheng | defaultsettings = conditioner.Conditioner.defaultsettings |
49 | 7 | Anchi Cheng | </pre> |
50 | 6 | Anchi Cheng | |
51 | h3. GUI panel class |
||
52 | |||
53 | 11 | Anchi Cheng | Define panelclass to make the class load the right gui panel that you will write later. |
54 | |||
55 | 6 | Anchi Cheng | <pre> |
56 | panelclass = leginon.gui.wx.BufferCycler.Panel |
||
57 | </pre> |
||
58 | 10 | Anchi Cheng | |
59 | 6 | Anchi Cheng | h3. Input/Output Events |
60 | |||
61 | We inherit the eventinputs of the parent class in the example. |
||
62 | <pre> |
||
63 | eventinputs = conditioner.Conditioner.eventinputs |
||
64 | </pre> |
||
65 | |||
66 | h2. Define new data type or event this node produces |
||
67 | |||
68 | New output data type should be defined in leginondata.py, and new event, if any, defined in event.py |
||
69 | |||
70 | Neither is needed in the example. |
||
71 | |||
72 | 1 | Jim Pulokas | h2. Create the user interface |
73 | 5 | Jim Pulokas | |
74 | 6 | Anchi Cheng | See source:trunk/leginon/gui/wx/BufferCycler.py for an inherited example that does not need any new definition. This is the minimal definition of Leginon gui. |
75 | 1 | Jim Pulokas | |
76 | 6 | Anchi Cheng | # Make a new file under leginon/gui/wx for the gui definition. In the example: gui/wx/BufferCycler.py |
77 | # Define Panel Class |
||
78 | # OnSettingsTool method, SettingsDialog class, and ScrolledSettings are redefined in this module so that the local one is used. |
||
79 | |||
80 | 5 | Jim Pulokas | h2. Register the node |
81 | |||
82 | 6 | Anchi Cheng | Register the node by adding it to leginon/allnodes.py as shown in the modification made in r18567 |
83 | |||
84 | 2 | Jim Pulokas | |
85 | 4 | Jim Pulokas | back to [[Leginon Developer Guide]] |