Loading [MathJax]/extensions/tex2jax.js
Iguana 0.9.0
Implementation Guardian of Analysis Algorithms
iguana_ex_fortran_01_action_functions.f
Go to the documentation of this file.
1 !> @begin_doc_example{fortran}
2 !> @file iguana_ex_fortran_01_action_functions.f
3 !> @brief Fortran example demonstrating how to read a HIPO file and use
4 !> its data with Iguana algorithms' action functions.
5 !> Run with no arguments to see the usage guide.
6 !> @see @ref fortran_usage_guide for more guidance
7 !> @end_doc_example
8 !>
9 !> Fortran example program
11
12 use iso_c_binding
13 implicit none
14
15c ------------------------------------------------------------------
16c data declarations
17c ------------------------------------------------------------------
18c NOTE: using `iso_c_binding` types for input and output of C-bound
19c functions and subroutines, i.e., for HIPO and Iguana usage;
20c using standard F77 types may still work, but might be
21c compiler dependent in some cases
22
23c program parameters
24 integer*4 argc
25 character*1024 in_file ! HIPO file
26 integer num_events ! number of events to read
27 character*1024 config_file ! YAML configuration file
28 character*16 num_events_arg
29 logical config_file_set
30 character(kind=c_char, len=1024)
31 & in_file_cstr, config_file_cstr, etc_dir
32
33c HIPO and bank variables
34 integer counter ! event counter
35 integer(c_int) reader_status ! hipo event loop vars
36 integer(c_int) nr ! unused
37 integer n_max ! max number of rows we can read
38 parameter(n_max=50)
39
40c REC::Particle columns
41 integer(c_int) nrows_p ! number of rows
42 integer(c_int) pindex(n_max)
43 integer(c_int) pid(n_max)
44 real(c_float) px(n_max), py(n_max), pz(n_max)
45 real(c_float) vz(n_max)
46 integer(c_int) stat(n_max)
47
48c RUN::config columns
49 integer(c_int) nrows_c ! number of rows
50 real(c_float) torus(n_max)
51 integer(c_int) runnum(n_max)
52 integer(c_int) evnum(n_max)
53
54c REC::Track, REC::Calorimeter, REC::Scintillator columns
55 integer(c_int) nrows_trk, nrows_cal, nrows_sci
56 integer(c_int) sector_trk(n_max) ! sectors from REC::Track
57 integer(c_int) pindex_trk(n_max) ! pindices from REC::Track
58 integer(c_int) sector_cal(n_max) ! from REC::Calorimeter
59 integer(c_int) pindex_cal(n_max)
60 integer(c_int) sector_sci(n_max) ! from REC::Scintillator
61 integer(c_int) pindex_sci(n_max)
62
63c iguana algorithm outputs
64 logical(c_bool) accept(n_max) ! filter
65 real(c_double) qx, qy, qz, qe ! q vector
66 real(c_double) q2, x, y, w, nu ! inclusive kinematics
67 real(c_double) beampz, targetm ! beam and target
68 integer(c_int) key_vz_filter ! key for Z-vertex filter
69 integer(c_int) key_inc_kin ! key for inclusive kinematics
70 integer(c_int) sector(n_max) ! sectors
71 integer(c_int) nrows_sec ! size of `sector`
72
73c iguana algorithm indices
74 integer(c_int) algo_eb_filter, algo_vz_filter,
75 & algo_inc_kin, algo_sec_finder, algo_mom_cor
76
77c misc.
78 integer i, j
79 real p, p_ele
80 integer i_ele
81 logical found_ele
82
83c ------------------------------------------------------------------
84c open the input file
85c ------------------------------------------------------------------
86
87c parse arguments
88 num_events = 10
89 config_file_set = .false.
90 argc = iargc()
91 if(argc.lt.1) then
92 etc_dir = ''
93 call iguana_getconfiginstallationprefix(etc_dir)
94 print *, 'ERROR: please at least specify a HIPO_FILE'
95 print *, ''
96 print *, 'ARGS: ', 'HIPO_FILE', ' ', 'NUM_EVENTS'
97 print *, ''
98 print *, ' HIPO_FILE: ', 'the input HIPO file'
99 print *, ''
100 print *, ' NUM_EVENTS (optional): ',
101 & 'the number of events (0 for all)'
102 print *, ' default: ', num_events
103 print *, ''
104 print *, ' CONFIG_FILE (optional): ',
105 & 'algorithm configuration file'
106 print *, ' default: ', 'use the internal defaults'
107 print *, ' example config file: ',
108 & trim(etc_dir)//'/examples/my_z_vertex_cuts.yaml'
109 stop
110 else
111 call getarg(1, in_file)
112 in_file_cstr = trim(in_file)//c_null_char
113 end if
114 if(argc.ge.2) then
115 call getarg(2, num_events_arg)
116 read(num_events_arg,*) num_events
117 end if
118 if(argc.ge.3) then
119 call getarg(3, config_file)
120 config_file_cstr = trim(config_file)//c_null_char
121 config_file_set = .true.
122 endif
123
124c open the input HIPO file
125 call hipo_file_open(in_file_cstr)
126 reader_status = 0
127 counter = 0
128
129c ------------------------------------------------------------------
130c create iguana algorithms
131c ------------------------------------------------------------------
132
133c before anything for Iguana, call `iguana_create()`
134 call iguana_create()
135! call iguana_bindings_set_verbose() ! enable additional log print
136
137c then create the algorithm instances
138c - the 1st argument is an integer, the algorithm index, which
139c references the created instance of the algorithm; it will be
140c set after calling this subroutine and you will need it to call
141c other iguana subroutines (namely, "action functions")
142c - the 2nd argument is the algorithm name
143c IMPORTANT: any time you pass a string to iguana, be sure that
144c it has the correct termination by appending:
145c `//c_null_char`
146 call iguana_algo_create(
147 & algo_eb_filter,
148 & 'clas12::EventBuilderFilter'//c_null_char)
149 call iguana_algo_create(
150 & algo_vz_filter,
151 & 'clas12::ZVertexFilter'//c_null_char)
152 call iguana_algo_create(
153 & algo_inc_kin,
154 & 'physics::InclusiveKinematics'//c_null_char)
155 call iguana_algo_create(
156 & algo_sec_finder,
157 & 'clas12::SectorFinder'//c_null_char)
158 call iguana_algo_create(
159 & algo_mom_cor,
160 & 'clas12::MomentumCorrection'//c_null_char)
161
162c ------------------------------------------------------------------
163c configure and start iguana algorithms
164c ------------------------------------------------------------------
165
166c set log levels (don't forget `//c_null_char`)
167 call iguana_algo_set_log_level(
168 & algo_eb_filter, 'debug'//c_null_char)
169 call iguana_algo_set_log_level(
170 & algo_vz_filter, 'debug'//c_null_char)
171 call iguana_algo_set_log_level(
172 & algo_inc_kin, 'debug'//c_null_char)
173 call iguana_algo_set_log_level(
174 & algo_sec_finder, 'debug'//c_null_char)
175 call iguana_algo_set_log_level(
176 & algo_mom_cor, 'debug'//c_null_char)
177
178c configure algorithms with a configuration file
179 if(config_file_set) then
180 call iguana_set_config_file(config_file_cstr)
181 endif
182
183c start all algorithms, which "locks" their configuration
184 call iguana_start()
185
186c ------------------------------------------------------------------
187c event loop
188c ------------------------------------------------------------------
189
190 10 if(reader_status.eq.0 .and.
191 & (num_events.eq.0 .or. counter.lt.num_events)) then
192
193 print *, ''
194 print *, '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> event ', counter
195
196c read banks
197 call hipo_file_next(reader_status)
198c read each bank and get their numbers of rows
199 call hipo_read_bank('REC::Particle', nrows_p)
200 call hipo_read_bank('RUN::config', nrows_c)
201 call hipo_read_bank('REC::Track', nrows_trk)
202 call hipo_read_bank('REC::Calorimeter', nrows_cal)
203 call hipo_read_bank('REC::Scintillator', nrows_sci)
204c get bank elements
205 call hipo_read_int('REC::Particle', 'pid', nr, pid, n_max)
206 call hipo_read_float('REC::Particle', 'px', nr, px, n_max)
207 call hipo_read_float('REC::Particle', 'py', nr, py, n_max)
208 call hipo_read_float('REC::Particle', 'pz', nr, pz, n_max)
209 call hipo_read_float('REC::Particle', 'vz', nr, vz, n_max)
210 call hipo_read_int('REC::Particle', 'status', nr, stat, n_max)
211 call hipo_read_float('RUN::config', 'torus', nr, torus, n_max)
212 call hipo_read_int('RUN::config', 'run', nr, runnum, n_max)
213 call hipo_read_int('RUN::config', 'event', nr, evnum, n_max)
214 call hipo_read_int('REC::Track', 'sector', nr,
215 & sector_trk, n_max)
216 call hipo_read_int('REC::Track', 'pindex', nr,
217 & pindex_trk, n_max)
218 call hipo_read_int('REC::Calorimeter', 'sector', nr,
219 & sector_cal, n_max)
220 call hipo_read_int('REC::Calorimeter', 'pindex', nr,
221 & pindex_cal, n_max)
222 call hipo_read_int('REC::Scintillator', 'sector', nr,
223 & sector_sci, n_max)
224 call hipo_read_int('REC::Scintillator', 'pindex', nr,
225 & pindex_sci, n_max)
226
227c print the event number
228 print *, 'evnum =', evnum(1)
229
230c fill simple list of pindices in REC::Particle
231 do i=1, nrows_p
232 pindex(i) = i-1 ! NOTE: pindex starts at ZERO
233 enddo
234
235c before using the Z-vertext filter, we must "prepare" the
236c algorithm's configuration for this event; the resulting
237c 'key_vz_filter' must be passed to the action function;
238 print *, '===> call iguana prepare-event functions'
239 call iguana_clas12_zvertexfilter_prepareevent(
240 & algo_vz_filter, runnum(1), key_vz_filter)
241c similarly for the inclusive kinematics algorithm
242c - use '-1' for the beam energy argument, so RCDB is used
243c to get the beam energy (otherwise hard-code a value)
244c - be sure the literal is of kind `real(c_double)`, e.g.,
245c use `-1.0_c_double` instead of `-1`, otherwise the
246c correct number will not be passed to the C++ code
247 call iguana_physics_inclusivekinematics_prepareevent(
248 & algo_inc_kin, runnum(1), -1.0_c_double, key_inc_kin)
249! print *, ' key_vz_filter =', key_vz_filter
250! print *, ' key_inc_kin =', key_inc_kin
251
252c call iguana filters
253c - the `logical` variable `accept` must be initialized to
254c `.true.`, since we will use it to "chain" the filters
255c - the event builder filter trivial: by default it accepts only
256c `REC::Particle::pid == 11 or -211` (simple example algorithm)
257c - the AND with the z-vertex filter is the final filter, `accept`
258 print *, '===> filter particles with iguana:'
259 do i=1, nrows_p
260 accept(i) = .true.
261 call iguana_clas12_eventbuilderfilter_filter(
262 & algo_eb_filter, pid(i), accept(i))
263 call iguana_clas12_zvertexfilter_filter(
264 & algo_vz_filter, vz(i), pid(i), stat(i),
265 & key_vz_filter, accept(i))
266 print *, ' pindex =', pindex(i), ' pid =', pid(i),
267 & ' vz =', vz(i), ' status =', stat(i),
268 & ' => accept =', accept(i)
269 enddo
270
271c get sector number; this calls a vector action function, where
272c many of its arguments are arrays
273 print *, '===> determine particle sectors:'
274! write(*,*) ' pindex_trk', (pindex_trk(j),j=1,nrows_trk)
275! write(*,*) ' sector_trk', (sector_trk(j),j=1,nrows_trk)
276! print *, '---'
277! write(*,*) ' pindex_cal', (pindex_cal(j),j=1,nrows_cal)
278! write(*,*) ' sector_cal', (sector_cal(j),j=1,nrows_cal)
279! print *, '---'
280! write(*,*) ' pindex_sci', (pindex_sci(j),j=1,nrows_sci)
281! write(*,*) ' sector_sci', (sector_sci(j),j=1,nrows_sci)
282 call iguana_clas12_sectorfinder_getstandardsectorvec(
283 & algo_sec_finder,
284 & sector_trk, nrows_trk, pindex_trk, nrows_trk,
285 & sector_cal, nrows_cal, pindex_cal, nrows_cal,
286 & sector_sci, nrows_sci, pindex_sci, nrows_sci,
287 & pindex, nrows_p,
288 & sector, nrows_sec)
289 write(*,*) ' pindex:', (pindex(j),j=1,nrows_p)
290 write(*,*) ' sector:', (sector(j),j=1,nrows_sec)
291
292c momentum corrections
293 if(nrows_c.lt.1) then
294 print *, '===> no RUN::config bank; cannot ',
295 & 'apply momentum corrections'
296 else
297 print *, '===> momentum corrections:'
298 print *, 'evnum =', evnum(1)
299 do i=1, nrows_p
300 if(accept(i)) then
301 print *, 'Particle PDG =', pid(i)
302 print *, ' sector =', sector(i)
303 print *, ' p_old = (', px(i), ',', py(i), ',', pz(i), ')'
304 call iguana_clas12_momentumcorrection_transform(
305 & algo_mom_cor,
306 & px(i), py(i), pz(i),
307 & sector(i), pid(i), torus(1),
308 & px(i), py(i), pz(i))
309 print *, ' p_new = (', px(i), ',', py(i), ',', pz(i), ')'
310 endif
311 enddo
312 endif
313
314c simple electron finder: trigger and highest |p|
315 p_ele = 0
316 found_ele = .false.
317 print *, '===> finding electron...'
318 do i=1, nrows_p
319 if(accept(i)) then
320 print *, ' pindex =', pindex(i), ' status =', stat(i)
321 if(pid(i).eq.11 .and. stat(i).lt.0) then
322 p = sqrt(px(i)**2 + py(i)**2 + pz(i)**2)
323 if(p.gt.p_ele) then
324 i_ele = i
325 p_ele = p
326 found_ele = .true.
327 endif
328 endif
329 endif
330 enddo
331 if(found_ele) then
332 print *, '===> found DIS electron:'
333 print *, ' pindex =', pindex(i_ele)
334 print *, ' |p| =', p_ele
335 print *, ' p = (', px(i_ele), py(i_ele), pz(i_ele), ')'
336 else
337 print *, '===> no DIS electron'
338 endif
339
340c compute DIS kinematics with iguana, if electron is found
341 if(found_ele) then
342 call iguana_physics_inclusivekinematics_computefromlepton(
343 & algo_inc_kin,
344 & px(i_ele), py(i_ele), pz(i_ele),
345 & key_inc_kin,
346 & qx, qy, qz, qe,
347 & q2, x, y, w, nu,
348 & beampz, targetm)
349 print *, '===> inclusive kinematics:'
350 print *, ' q = (', qx, qy, qz, qe, ')'
351 print *, ' Q2 = ', q2
352 print *, ' x = ', x
353 print *, ' y = ', y
354 print *, ' W = ', w
355 print *, ' nu = ', nu
356 endif
357
358 counter = counter + 1
359 goto 10
360 endif
361
362c ------------------------------------------------------------------
363c cleanup
364c ------------------------------------------------------------------
365
366c don't forget to call `iguana_stop()` to stop the algorithms
367c and free the allocated memory
368 call iguana_stop()
369
370 end program
program iguana_ex_fortran_01_action_functions
Fortran example program.