<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to Home</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>Recent changes to Home</description><atom:link href="https://sourceforge.net/p/elderpt/wiki/Home/feed" rel="self"/><language>en</language><lastBuildDate>Mon, 22 Jun 2020 06:46:10 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/elderpt/wiki/Home/feed" rel="self" type="application/rss+xml"/><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v48
+++ v49
@@ -4,11 +4,11 @@
 Download the latest elder-pt release (e.g. elderpt-0.1.tar.gz). 
 [[download_button]]
 Unpack the file `tar -zxvf elderpt-0.1.tar.gz`.  Change into the unpacked directory `cd elderpt-0.1`.  
-### configuration
+### configure
 If you want to install into the system path you need root priviliges. If this is the case type `./configure`. If this is not the case you can intall into your home directory (e.g. $HOME/.local). In this case type `./configure --prefix=$HOME/.local`.  
-### compilation
+### compile
 Then type `make -j 8`.  If your c++ compiler is too old (you'll get compilation errors in that case) you may have to type `make CXXFLAGS=-std=c++11 -j 8`. 
-### installation
+### install
 In case you want a system wide installation, type `sudo make install`. In case you're installing into your home directory type `make install`.  The installation of elder-pt is now complete.  
 Note that in case you've installed elder-pt into your home directory your may need to set the LD_LIBRARY_PATH environment variable before you start any program that uses elder-pt, e.g. in order to start go4 (see below) type `LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/bin" go4`. 
 Alternatively, you can define an alias in your .profile 
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Mon, 22 Jun 2020 06:46:10 -0000</pubDate><guid>https://sourceforge.net63f09005ed8df14a5d8548ce0a1cbb945c689c74</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v47
+++ v48
@@ -1,7 +1,9 @@
 [TOC]
 # elder-pt documentation
 ## installation
-Download the latest elder-pt release (e.g. elderpt-0.1.tar.gz). Unpack the file `tar -zxvf elderpt-0.1.tar.gz`.  Change into the unpacked directory `cd elderpt-0.1`.  
+Download the latest elder-pt release (e.g. elderpt-0.1.tar.gz). 
+[[download_button]]
+Unpack the file `tar -zxvf elderpt-0.1.tar.gz`.  Change into the unpacked directory `cd elderpt-0.1`.  
 ### configuration
 If you want to install into the system path you need root priviliges. If this is the case type `./configure`. If this is not the case you can intall into your home directory (e.g. $HOME/.local). In this case type `./configure --prefix=$HOME/.local`.  
 ### compilation
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 13:03:12 -0000</pubDate><guid>https://sourceforge.netc1ec9d0e69fe5dcd0354d1e6384fdf5169c1dbd8</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v46
+++ v47
@@ -63,7 +63,7 @@
 ## adding plugin libraries
 Consider the following situation: In a beam line there are two position and time sensitive detectors in a certain distance.  The detector arrangement is used to track charged particles that penetrates the two detectors.
 [[img src=tracking_detector.png alt=detector_setup]]
-I'll show how to write an elder-pt plugin that contains a tracking processor and how to use this processor in an analysis.
+I'll show how to write an elder-pt plugin with a tracking processor to calculate the particle velocity and direction based on the information from two such planar detectors, and how to use this processor in an elder-pt analysis.
 ### the structure of the plugin
 Create a directory with name `tracking` and the following strucure:
 ```
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 10:32:43 -0000</pubDate><guid>https://sourceforge.net0b7f209750c54c4e497e9442459013881fdc7604</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v45
+++ v46
@@ -10,9 +10,9 @@
 In case you want a system wide installation, type `sudo make install`. In case you're installing into your home directory type `make install`.  The installation of elder-pt is now complete.  
 Note that in case you've installed elder-pt into your home directory your may need to set the LD_LIBRARY_PATH environment variable before you start any program that uses elder-pt, e.g. in order to start go4 (see below) type `LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/bin" go4`. 
 Alternatively, you can define an alias in your .profile 
-`alias go4="LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/lib" go4"` 
+`alias go4='LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/lib" go4'` 
 and 
-`alias go4analysis="LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/lib" go4analysis"`.
+`alias go4analysis='LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/lib" go4analysis'`.
 If you want to compile any program that uses elder-pt, in particular elder-pt plugins, and elder-pt was installed into your home directory, you need to set the PKG_CONFIG_PATH environment variable. It is a good idea to set it in your .profile
 `export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$HOME/.local/lib/pkgconfig"`.
 ## introduction to elder-pt
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 10:28:35 -0000</pubDate><guid>https://sourceforge.netc6737e326177ac7b23d778faff236a5d29cb09e3</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v44
+++ v45
@@ -318,6 +318,7 @@
 using std
 using tracking

+# create four processors using two nested for loops
 for $PLANE in 1 2 
    for $COORD in x y
        processor plane$PLANE_$COORD std.rand_gaussian
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 09:57:44 -0000</pubDate><guid>https://sourceforge.net6e89294a73a054ba086bf4933af40c7e9dc717d9</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v43
+++ v44
@@ -312,5 +312,41 @@
 end
 ```

+## For loops in config files
+There is a log of redundancy in the `analysis.config` file above. In order to reduce the size we can use a for loop. The following file does the exact same thing but is shorter and easyier to read:
+```
+using std
+using tracking
+
+for $PLANE in 1 2 
+   for $COORD in x y
+       processor plane$PLANE_$COORD std.rand_gaussian
+           parameter mean  = 0
+           parameter sigma = 10
+       end
+   end 
+end 
+processor plane1_t std.rand_gaussian
+   parameter mean  = 0
+   parameter sigma = 1
+end
+processor plane2_t std.rand_gaussian
+   parameter mean  = 10
+   parameter sigma = 1
+end
+
+processor tracker tracking.TwoPlaneTracker
+   plane1_x &amp;lt;- plane1_x.value
+   plane1_y &amp;lt;- plane1_y.value
+   plane1_t &amp;lt;- plane1_t.value
+   plane2_x &amp;lt;- plane2_x.value
+   plane2_y &amp;lt;- plane2_y.value
+   plane2_t &amp;lt;- plane2_t.value
+   histogram v_abs 10000
+   histogram plane1_x:plane2_x
+   histogram plane1_t:v_abs
+end
+```
+
 [[members limit=20]]
 [[download_button]]
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 09:56:27 -0000</pubDate><guid>https://sourceforge.net2851e9c71eda9e3c672713b0f26370d3cca4fe62</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v42
+++ v43
@@ -10,9 +10,9 @@
 In case you want a system wide installation, type `sudo make install`. In case you're installing into your home directory type `make install`.  The installation of elder-pt is now complete.  
 Note that in case you've installed elder-pt into your home directory your may need to set the LD_LIBRARY_PATH environment variable before you start any program that uses elder-pt, e.g. in order to start go4 (see below) type `LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/bin" go4`. 
 Alternatively, you can define an alias in your .profile 
-`alias go4="LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/bin" go4"` 
+`alias go4="LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/lib" go4"` 
 and 
-`alias go4analysis="LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/bin" go4analysis"`.
+`alias go4analysis="LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/.local/lib" go4analysis"`.
 If you want to compile any program that uses elder-pt, in particular elder-pt plugins, and elder-pt was installed into your home directory, you need to set the PKG_CONFIG_PATH environment variable. It is a good idea to set it in your .profile
 `export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$HOME/.local/lib/pkgconfig"`.
 ## introduction to elder-pt
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 09:53:37 -0000</pubDate><guid>https://sourceforge.netda6f654a0fdcb0d42af3f8b9aa695e4aa72910a0</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v41
+++ v42
@@ -189,7 +189,7 @@
 } // namespace elderpt_plugin
 #endif
 ```
-####  TwoPlaneTracker.cpp
+####  process/TwoPlaneTracker.cpp
 This file contians the implementation of the `initialize()` and `process()` member function.
 Inside `initialize()`,  the macro `NAME_PARAMETER()` has to be called for each of the elements in the `Parameter` enum defined in `TwoPlaneTracker.hpp`.
 After that, default values for parameters can be defined optionally. 
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 09:43:39 -0000</pubDate><guid>https://sourceforge.netc20a8cd09116aa92415970a3015d958bc69008aa</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v40
+++ v41
@@ -74,6 +74,10 @@
 |   |-- TwoPlaneTracker.cpp
 |   |-- TwoPlaneTracker.hpp
 ```
+The `makefile` is the same for all elder-pt plugins and no modificationa are needed. 
+The `module.cpp` is a list of all components (processors, unpackers, sources) of the elder-pt plugin. Unitl now we have only seen processors (like std.rand_gaussian or std.pair), and we will ignore unpackers and sources for now.
+The `process` subdirectory contains header and implementation of each processor.  In this case we'll write a processor with name TwoPlaneTracker which takes as input two sets of (x,y,t) coordinates, i.e. the x and y position and the time in each detection plane.
+Later, additional processors can be added by creating a new pair of .hpp and .cpp files and adding the new processor into module.cpp.

 #### makefile
 ```
@@ -114,6 +118,9 @@
 ```

 #### module.cpp 
+This file lists all processors between the `ELDER_MODULE_PROCESSOR_BEGIN;` and `ELDER_MODULE_PROCESSOR_END;` macros.
+The processor list consist of calls of the `ELDER_MODULE_PROCESSOR_ADD();` macro.
+We ignore the unpackers and sources for now.
 ```
 #include &amp;lt;elderpt.hpp&amp;gt;

@@ -130,6 +137,8 @@
 ELDER_MODULE_SOURCE_END;
 ```
 ####  process/TwoPlaneTracker.hpp
+This is the header file for the TwoPlaneTracker. It contains one class declaration that publicly derives from `elderpt::process::Processor`.  It is good practice to place the class in an appropriately named namespace.
+The class defines its inputs, outputs and parameters as enums. It has to provide at least two member functions `void initialize()` and `void process()`. It is good practice to document all inputs, outputs and parameters here.
 ```
 #ifndef TWO_PLANE_TRACKER_HPP_
 #define TWO_PLANE_TRACKER_HPP_
@@ -149,8 +158,6 @@
 class TwoPlaneTracker : public elderpt::process::Processor
 {
 public:
-   TwoPlaneTracker();
-   ~TwoPlaneTracker();
    void initialize();
    void process();

@@ -183,6 +190,19 @@
 #endif
 ```
 ####  TwoPlaneTracker.cpp
+This file contians the implementation of the `initialize()` and `process()` member function.
+Inside `initialize()`,  the macro `NAME_PARAMETER()` has to be called for each of the elements in the `Parameter` enum defined in `TwoPlaneTracker.hpp`.
+After that, default values for parameters can be defined optionally. 
+After that the function `read_paramets()` has to be called.
+Then the macro `NAME_INPUT_CHANNEL()` has to be called for each of the elements in the `Input` enum defined in `TwoPlaneTracker.hpp`.
+Then the macro `NAME_OUPUT_CHANNEL()` has to be called for each of the elements in the `Output` enum defined in `TwoPlaneTracker.hpp`.
+
+The member function `process()` contains the calculation of the outputs based on the inputs.
+For any computation that depends on a given input (e.g. `plane1_x`), one has to check if that input is valid. A value can be invalid if there is no data source attached to the input of that processor, or if the attached processor gave an invalid output.
+The validity of any input (e.g. `plane1_x` can be checked by calling `input_valid(plane1_x)`. Remember that `plane1_x` refers tho the `Input` enum element `plane1_x`  defined in `TwoPlaneTracker.hpp`.
+If all inputs that are neede for the computation are validated, the actual value can be obtained by calling `input_value(plane1_x)`. The result is a double and can be directly used or assigned to a double variable for computation.
+Finally, the ouputs (e.g. `v_abs`) of the Processor are filled by calling the function `set_output(v_abs, sqrt(vx*vx + vy*vy + vz*vz)/c)` where the first parameter refers to an element of the `Output` enum defined in `TwoPlaneTracker.hpp`. 
+The `process()` member function will be called by the elder-pt framework for each event that has to be processed. Where the input comes from and where the output goes to is defined inside the `analysis.config` file that we have seen before.
 ```
 #include "TwoPlaneTracker.hpp"
 #include &amp;lt;iostream&amp;gt;
@@ -194,8 +214,6 @@
 {
 namespace tracking
 {
-TwoPlaneTracker::TwoPlaneTracker() {}
-TwoPlaneTracker::~TwoPlaneTracker() {}
 void TwoPlaneTracker::initialize()
 {
    // define the parameter 
@@ -243,28 +261,56 @@
 } // namespace tracker
 } // namespace elderpt_plugin
 ```
-
-### processors
-```
-class MyProcessor : public elderpt::process::Processor
-{
-    public:
-        void initialize();
-        void process();
-        enum InputValue {
-            in1
-        }
-};
-```
-### unpackers
-```
-class MyUnpacker : public elderpt::unpack::Unpacker
-{
-        void initialize(const std::vector&amp;lt;std::string&amp;gt; ¶meters);
-        void process();
-};
-```
-## using the API
+### compiling the plugin
+The plugin can be compiled by typing `make`, and installed by typing `make install` or, if the elder-pt installation is system wide `sudo make install`.
+### using the plugin
+In order to test the plugin, we can write a file `analysis.config` with the following content.
+```
+using std    # use the standard processors
+using tracking # use the processors insid the new tracking plugin
+
+# first detection plane: Gaussian beam profile with 10 mm sigma arriving at t=0ns with dt=1ns
+processor plane1_x std.rand_gaussian
+   parameter mean  = 0
+   parameter sigma = 10
+end
+processor plane1_y std.rand_gaussian
+   parameter mean  = 0
+   parameter sigma = 10
+end
+processor plane1_t std.rand_gaussian
+   parameter mean  = 0
+   parameter sigma = 1
+end
+
+# second detection plane: Gaussian beam profile with 10 mm sigma arriving at t=10ns with dt=1ns
+processor plane2_x std.rand_gaussian
+   parameter mean  = 0
+   parameter sigma = 10
+end
+processor plane2_y std.rand_gaussian
+   parameter mean  = 0
+   parameter sigma = 10
+end
+processor plane2_t std.rand_gaussian
+   parameter mean  = 10
+   parameter sigma = 1
+end
+
+# create a TwoPlaneTracker and fill it with the random values from above
+processor tracker tracking.TwoPlaneTracker
+   plane1_x &amp;lt;- plane1_x.value
+   plane1_y &amp;lt;- plane1_y.value
+   plane1_t &amp;lt;- plane1_t.value
+   plane2_x &amp;lt;- plane2_x.value
+   plane2_y &amp;lt;- plane2_y.value
+   plane2_t &amp;lt;- plane2_t.value
+    # create some histograms 
+   histogram v_abs 10000
+   histogram plane1_x:plane2_x
+   histogram plane1_t:v_abs
+end
+```

 [[members limit=20]]
 [[download_button]]
&amp;lt;/std::string&amp;gt;&amp;lt;/iostream&amp;gt;&amp;lt;/elderpt.hpp&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 09:42:44 -0000</pubDate><guid>https://sourceforge.net8e286d8542d6184efadce65aff195a0cc7f61051</guid></item><item><title>Home modified by Michael Reese</title><link>https://sourceforge.net/p/elderpt/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v39
+++ v40
@@ -60,9 +60,190 @@
 [[img src=simple_graph.png alt=schematic_graph_representation]]
 Graph nodes (processors) and the connecting edges that specify the data flow are draw in red. The internals of each node are drawn in black. The name can be chosen when placing a processor in a graph. The type specifies the internals (inputs / outputs) of the node. The processor types used in this example are all from the stdandard library of elder-pt. It is easy to write your own library with custom processor types.

-## adding libraries
-Consider the following situation: In a beam line there are two position and time sensitive detectors in a certain distance. 
+## adding plugin libraries
+Consider the following situation: In a beam line there are two position and time sensitive detectors in a certain distance.  The detector arrangement is used to track charged particles that penetrates the two detectors.
 [[img src=tracking_detector.png alt=detector_setup]]
+I'll show how to write an elder-pt plugin that contains a tracking processor and how to use this processor in an analysis.
+### the structure of the plugin
+Create a directory with name `tracking` and the following strucure:
+```
+tracking/
+|-- makefile
+|-- module.cpp
+|-- process
+|   |-- TwoPlaneTracker.cpp
+|   |-- TwoPlaneTracker.hpp
+```
+
+#### makefile
+```
+##########################################################
+# No need to modify this file after adding processors 
+# or unpackers to the module.cpp
+##########################################################
+LIBRARY = $(shell echo libelderpt`pwd | rev | cut -d'/' -f1 | rev`.so)
+OBJECTS = $(shell find -iname "*.cpp" | sed 's/.\/module.cpp//g' | sed 's/module.cpp//g'| sed 's/.cpp/.o/g')
+HEADERS = $(shell find -iname "*.hpp")
+
+ELDERPT_CFLAGS = `pkg-config elderpt-0.1 --cflags` 
+ELDERPT_LIBS   = `pkg-config elderpt-0.1 --libs`  -lasound 
+
+all: $(LIBRARY) 
+
+%.o : %.cpp %.hpp
+   g++ -O3 $(ELDERPT_CFLAGS) -c -g -fPIC -shared $&amp;lt; -o $@
+%.o : %.cpp 
+   g++ -O3 $(ELDERPT_CFLAGS) -c -g -fPIC -shared $&amp;lt; -o $@
+
+$(LIBRARY): $(OBJECTS) $(HEADERS) module.cpp
+   g++ -O3 $(ELDERPT_CFLAGS) $(ELDERPT_LIBS) -fPIC -shared -g -o $(LIBRARY) $(OBJECTS) module.cpp
+
+.PHONY: install uninstall clean
+
+install: all
+   pkg-config elderpt-0.1 --libs | sed 's/ /\n/g' | head -n 1 | sed 's/-L//g' &amp;gt; .install.dir
+   cp $(LIBRARY) `cat .install.dir`
+   @echo installed $(LIBRARY) into `cat .install.dir`
+
+uninstall:
+   @rm `cat .install.dir`/$(LIBRARY)
+   @echo removed $(LIBRARY) from `cat .install.dir`
+
+clean:
+   rm -f $(OBJECTS) $(LIBRARY)
+```
+
+#### module.cpp 
+```
+#include &amp;lt;elderpt.hpp&amp;gt;
+
+#include "process/TwoPlaneTracker.hpp"
+
+ELDER_MODULE_PROCESSOR_BEGIN;
+ELDER_MODULE_PROCESSOR_ADD(elderpt_plugin::tracking::TwoPlaneTracker);
+ELDER_MODULE_PROCESSOR_END;
+
+ELDER_MODULE_UNPACKER_BEGIN;
+ELDER_MODULE_UNPACKER_END;
+
+ELDER_MODULE_SOURCE_BEGIN;
+ELDER_MODULE_SOURCE_END;
+```
+####  process/TwoPlaneTracker.hpp
+```
+#ifndef TWO_PLANE_TRACKER_HPP_
+#define TWO_PLANE_TRACKER_HPP_
+
+#include &amp;lt;elderpt process="" processor.hpp=""&amp;gt;
+
+#include &amp;lt;iostream&amp;gt;
+#include &amp;lt;deque&amp;gt;
+
+namespace elderpt_plugin // this namespace must be there for all elderpt plugins
+{
+
+namespace tracking  // this is the name of the elder plugin
+{
+
+
+class TwoPlaneTracker : public elderpt::process::Processor
+{
+public:
+   TwoPlaneTracker();
+   ~TwoPlaneTracker();
+   void initialize();
+   void process();
+   
+   enum Parameter
+   {
+       plane_distance_z, // distance of the two detection planes [in units of mm]
+   };                    // z-direction points downstream along the beam line
+
+   enum Input
+   {
+       plane1_x, // x position on the first detection plane [in units of mm]
+       plane1_y, // y position on the first detection plane [in units of mm]
+       plane1_t, // time at the first detection plane       [in units of ns]
+       plane2_x, // x position on the second detection plane [in units of mm]
+       plane2_y, // y position on the second detection plane [in units of mm]
+       plane2_t, // time at the second detection plane       [in units of ns]
+   };
+
+   enum Output
+   {
+       v_x, // velocity vector x-coordinate [in units of speed of light]
+       v_y, // velocity vector y-coordinate [in units of speed of light]
+       v_z, // velocity vector z-coordinate [in units of speed of light]
+       v_abs, // absolute value of velocity [in units of speed of light]
+   };
+private:
+};
+} // namespace tracker
+} // namespace elderpt_plugin
+#endif
+```
+####  TwoPlaneTracker.cpp
+```
+#include "TwoPlaneTracker.hpp"
+#include &amp;lt;iostream&amp;gt;
+#include &amp;lt;vector&amp;gt;
+#include &amp;lt;cstdint&amp;gt;
+#include &amp;lt;cmath&amp;gt;
+
+namespace elderpt_plugin 
+{
+namespace tracking
+{
+TwoPlaneTracker::TwoPlaneTracker() {}
+TwoPlaneTracker::~TwoPlaneTracker() {}
+void TwoPlaneTracker::initialize()
+{
+   // define the parameter 
+   NAME_PARAMETER(plane_distance_z);
+   // give a default value for the parameter
+   parameter(plane_distance_z) = 1000; // default distance of 1000 mm = 1 meter
+   // read parameter from file (overriding the default value)
+   read_parameters();
+   // crate the input ports
+   NAME_INPUT_CHANNEL(plane1_x);
+   NAME_INPUT_CHANNEL(plane1_y);
+   NAME_INPUT_CHANNEL(plane1_t);
+   NAME_INPUT_CHANNEL(plane2_x);
+   NAME_INPUT_CHANNEL(plane2_y);
+   NAME_INPUT_CHANNEL(plane2_t);
+   // crate the output ports
+   NAME_OUTPUT_CHANNEL(v_x);
+   NAME_OUTPUT_CHANNEL(v_y);
+   NAME_OUTPUT_CHANNEL(v_z);
+   NAME_OUTPUT_CHANNEL(v_abs);
+}
+
+void TwoPlaneTracker::process()
+{
+   static const double c = 299.79; // speed of light in mm/ns
+   // check if all inputs are valid (the "input_valid" function is provided by the Processor base class)
+   if (input_valid(plane1_x) &amp;amp;&amp;amp; input_valid(plane1_y) &amp;amp;&amp;amp; input_valid(plane1_t) &amp;amp;&amp;amp; 
+       input_valid(plane2_x) &amp;amp;&amp;amp; input_valid(plane2_y) &amp;amp;&amp;amp; input_valid(plane2_t)) {
+       // set the output values
+       double dt = input_value(plane2_t) - input_value(plane1_t);
+       double dx = input_value(plane2_x) - input_value(plane1_x);
+       double dy = input_value(plane2_y) - input_value(plane1_y);
+       double dz = parameter(plane_distance_z);
+       // calculate velocity in units of mm/ns
+       double vx = dx/dt; 
+       double vy = dy/dt;
+       double vz = dz/dt;
+       // output velocity in units of c;
+       set_output(v_x, vx/c);
+       set_output(v_y, vy/c);
+       set_output(v_z, vz/c);
+       set_output(v_abs, sqrt(vx*vx + vy*vy + vz*vz)/c);
+   }
+}
+} // namespace tracker
+} // namespace elderpt_plugin
+```
+
 ### processors
 ```
 class MyProcessor : public elderpt::process::Processor
&amp;lt;/cmath&amp;gt;&amp;lt;/cstdint&amp;gt;&amp;lt;/vector&amp;gt;&amp;lt;/iostream&amp;gt;&amp;lt;/deque&amp;gt;&amp;lt;/iostream&amp;gt;&amp;lt;/elderpt&amp;gt;&amp;lt;/elderpt.hpp&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Michael Reese</dc:creator><pubDate>Sun, 21 Jun 2020 09:08:54 -0000</pubDate><guid>https://sourceforge.net43f4707664fd47e6c4e1097342ec4dcee9c1170d</guid></item></channel></rss>