Jpp  17.1.0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
software/scripts/gradient.sh
Go to the documentation of this file.
1 #!/bin/zsh
2 script=${0##*/}
3 
4 zmodload zsh/mathfunc
5 
6 if [[ ! $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
7  echo "Auxiliary script for running the conjugate gradient fit in zsh."
8  echo "This script should be sourced by the steering script."
9  exit
10 fi
11 
12 # This script contains auxiliary functions for running the conjugate gradient fit.
13 # It should be sourced by the steering script.
14 # The steering script should provide for the method getChi2 and set the fit parameters before calling method gradient.
15 # The method getChi2 should set the current value of chi2 to its first positional parameter.
16 # The fit parameters are defined by the associative array PARAMETERS.
17 # In this, each key corresponds to a valid zsh command that can be used for changing a specific fit parameter.
18 # The command should contain the wild card '%' which is repeatedly replaced by a value, referred to as step size.
19 # The associated value is used to evaluate the derivative of chi2 per unit step size of each fit parameter.
20 # These step sizes should be tuned beforehand to yield similar absolute values of the derivatives.
21 # To this end, the methods evaluate and gprint (in this order) can be used.
22 
23 typeset -a CHI2 # internal chi2 values; index [1] corresponds to best value
24 typeset -a GRADIENT # derivative of chi2 per unit step size of each fit parameter
25 let "EPSILON = 5.0E-4" # default maximal distance to minimum
26 let "NUMBER_OF_ITERATIONS = 1000" # default maximum number of iterations
27 let "MOBILITY = 0" # maximum number of extra steps
28 typeset -A PARAMETERS # fit parameters
29 
30 if [[ -z "$DEBUG" ]]; then
31  DEBUG=0
32 fi
33 
34 
35 #
36 # Auxiliary function to evaluate chi2 and gradient thereof at current position.
37 #
38 # The external method getChi2 is used to evaluate the chi2.
39 # The value corresponding to each key in the associative array PARAMETERS
40 # is used as unit step size for the evaluation of the derivative of the chi2.
41 # The results are stored in the internal variables CHI2[1] and GRADIENT, respectively.
42 #
43 function evaluate()
44 {
45  GRADIENT=()
46 
47  getChi2 CHI2\[1\]
48 
49  let "WIDTH = 1"
50 
51  for KEY in ${(k)PARAMETERS}; do
52  if (( ${#KEY} > $WIDTH )); then
53  let "WIDTH = ${#KEY}"
54  fi
55  done
56 
57  let "V = 0.0"
58  let "i = 1"
59 
60  for KEY in ${(ko)PARAMETERS}; do
61 
62  BUFFER=(${(s/;/)${(Q)KEY}})
63 
64  VALUE=$PARAMETERS[$KEY]
65 
66  for K1 in ${(o)BUFFER}; do
67  eval ${(Q)${(qq)K1//\%/$((+0.5 * $VALUE))}}
68  done
69 
70  getChi2 CHI2\[2\]
71 
72  for K1 in ${(O)BUFFER}; do
73  eval ${(Q)${(qq)K1//\%/$((-0.5 * $VALUE))}}
74  done
75 
76  for K1 in ${(o)BUFFER}; do
77  eval ${(Q)${(qq)K1//\%/$((-0.5 * $VALUE))}}
78  done
79 
80  getChi2 CHI2\[3\]
81 
82  for K1 in ${(O)BUFFER}; do
83  eval ${(Q)${(qq)K1//\%/$((+0.5 * $VALUE))}}
84  done
85 
86  GRADIENT[$i]=$(($CHI2[2] - $CHI2[3]))
87 
88  if (( $DEBUG >= 3 )); then
89  printf "%-${WIDTH}s %12.5f %12.5f\n" $KEY $PARAMETERS[$KEY] $GRADIENT[$i]
90  fi
91 
92  let "V += $GRADIENT[$i]*$GRADIENT[$i]"
93  let "i += 1"
94  done
95 
96  if (( $DEBUG >= 3 )); then
97  printf "%-${WIDTH}s %12s %12.5f\n" "|gradient|" "" $((sqrt($V)))
98  fi
99 }
100 
101 
102 #
103 # Move current position along gradient by given scaling factor of the unit step sizes.
104 #
105 # \param 1 scaling factor
106 #
107 function move()
108 {
109  if (( $1 > 0.0 )); then
110 
111  let "i = 1"
112 
113  for KEY in ${(ko)PARAMETERS}; do
114 
115  BUFFER=(${(s/;/)${(Q)KEY}})
116 
117  for K1 in ${(o)BUFFER}; do
118  eval ${(Q)${(qq)K1//\%/$(($GRADIENT[$i] * $1 * $PARAMETERS[$KEY]))}}
119  done
120 
121  let "i += 1"
122  done
123 
124  else
125 
126  let "i = ${#GRADIENT}"
127 
128  for KEY in ${(kO)PARAMETERS}; do
129 
130  BUFFER=(${(s/;/)${(Q)KEY}})
131 
132  for K1 in ${(O)BUFFER}; do
133  eval ${(Q)${(qq)K1//\%/$(($GRADIENT[$i] * $1 * $PARAMETERS[$KEY]))}}
134  done
135 
136  let "i -= 1"
137  done
138  fi
139 }
140 
141 
142 #
143 # Main fit function.
144 #
145 # The algorithm is based on the conjugate gradient method.
146 # The position is moved to the optimal value and the final chi2 is returned.
147 #
148 # If the option is one, the step sizes are fine-tuned according to the gradient of the chi2.
149 # The value corresponding to each key in the associative array PARAMETERS is then
150 # multiplied by the corresponding element in GRADIENT and only the sign thereof is maintained.
151 #
152 # \param 1 variable containing final chi2 value on return
153 #
154 function gradient()
155 {
156  typeset -a G
157  typeset -a H
158 
159  if (( ${#PARAMETERS} == 0 )); then
160  return
161  fi
162 
163  evaluate
164 
165  # initialise
166 
167  for (( i = 1; i <= ${#GRADIENT}; ++i)); do
168  G[$i]=$((-1.0 * $GRADIENT[$i]))
169  H[$i]=$G[$i]
170  GRADIENT[$i]=$H[$i]
171  done
172 
173  for (( N = 0; $N != $NUMBER_OF_ITERATIONS; N += 1 )); do
174 
175  if (( $DEBUG >= 3 )); then
176  printf "chi2[1] %4d %12.5f\n" $N $CHI2[1]
177  fi
178 
179  # minimise chi2 in direction of gradient
180 
181  CHI2[2]=$CHI2[1]
182  CHI2[3]=$CHI2[2]
183 
184  for (( DS = 1.0, M = 0 ; $DS > 1.0e-3; )); do
185 
186  move $DS
187 
188  getChi2 CHI2\[4\]
189 
190  if (( $DEBUG >= 3 )); then
191  printf "chi2[4] %4d %12.5f %12.5e\n" $M $CHI2[4] $DS
192  fi
193 
194  if (( $CHI2[4] < $CHI2[3] )); then
195 
196  # continue
197 
198  CHI2[2]=$CHI2[3]
199  CHI2[3]=$CHI2[4]
200 
201  let "M = 0"
202 
203  continue
204  fi
205 
206  # if chi2 increases, try additional steps first to overcome possible hurdle, then try single step with reduced size
207 
208  if (( $DS == 1.0 )); then
209 
210  if (( $M == 0 )); then
211  CHI2[5]=$CHI2[4]
212  fi
213 
214  if (( $M != $MOBILITY )); then
215 
216  let "M += 1"
217 
218  continue;
219 
220  else
221 
222  for (( ; $M != 0; --M )); do
223  move $((-1.0 * $DS))
224  done
225 
226  CHI2[4]=$CHI2[5]
227  fi
228  fi
229 
230  move $((-1.0 * $DS))
231 
232  if (( $CHI2[3] < $CHI2[2] )); then
233 
234  # final step based on parabolic interpolation through following points
235  #
236  # X1 = -1 * DS -> CHI[2]
237  # X2 = 0 * DS -> CHI[3]
238  # X3 = +1 * DS -> CHI[4]
239 
240  let "F21 = $CHI2[3] - $CHI2[2]" # F(X2) - F(X1)
241  let "F23 = $CHI2[3] - $CHI2[4]" # F(X2) - F(X3)
242 
243  let "XS = 0.5 * ($F21 - $F23) / ($F23 + $F21)"
244 
245  move $((+1.0 * $XS * $DS))
246 
247  getChi2 CHI2\[4\]
248 
249  if (( $CHI2[4] < $CHI2[3] )); then
250 
251  CHI2[3]=$CHI2[4]
252 
253  else
254 
255  move $((-1.0 * $XS * $DS))
256 
257  getChi2 CHI2\[3\]
258  fi
259 
260  if (( $DEBUG >= 3 )); then
261  printf "chi2[3] %4d %12.5f %12.5e\n" $N $CHI2[3] $DS
262  fi
263 
264  break
265 
266  else
267 
268  # reduce step size
269 
270  let "DS *= 0.5"
271  fi
272  done
273 
274  if (( fabs($CHI2[3] - $CHI2[1]) < $EPSILON * 0.5 * (fabs($CHI2[1]) + fabs($CHI2[3])) )); then
275 
276  CHI2[1]=$CHI2[3]
277 
278  break;
279  fi
280 
281  evaluate
282 
283  let "GG = 0.0"
284  let "DGG = 0.0"
285 
286  for (( i = 1; $i <= ${#GRADIENT}; ++i )); do
287  let "GG += $G[$i]*$G[$i]"
288  let "DGG += ($GRADIENT[$i] + $G[$i]) * $GRADIENT[$i]"
289  done
290 
291  if (( $GG == 0.0 )); then
292  break
293  fi
294 
295  let "GAM = $DGG / $GG"
296 
297  for (( i = 1; $i <= ${#GRADIENT}; ++i )); do
298  G[$i]=$((-1.0 * $GRADIENT[$i]))
299  H[$i]=$(($G[$i] + $GAM * $H[$i]))
300  GRADIENT[$i]=$H[$i]
301  done
302  done
303 
304  if (( $DEBUG >= 3 )); then
305  printf "chi2[1] %4d %12.5f\n" $N $CHI2[1]
306  fi
307 
308  eval $1=$CHI2[1]
309 }
310 
311 
312 #
313 # Additional fit function to be called after gradient.
314 #
315 # The algorithm is based on sorting the derivatives of the chi2 and
316 # moving the position one-by-one to the optimal value.
317 # The final chi2 is returned.
318 #
319 # \param 1 variable containing final chi2 value on return
320 #
321 function simplex()
322 {
323  typeset -A G
324 
325 
326  let "WIDTH = 1"
327 
328  for KEY in ${(k)PARAMETERS}; do
329  if (( ${#KEY} > $WIDTH )); then
330  let "WIDTH = ${#KEY}"
331  fi
332  done
333 
334 
335  for (( N = 0; $N != $NUMBER_OF_ITERATIONS; N += 1 )); do
336 
337  G=()
338 
339  GRADIENT=()
340 
341  getChi2 CHI2\[1\]
342 
343  let "i = 1"
344 
345  for KEY in ${(ko)PARAMETERS}; do
346 
347  VALUE=$PARAMETERS[$KEY]
348 
349  BUFFER=(${(s/;/)${(Q)KEY}})
350 
351  for K1 in ${(o)BUFFER}; do
352  eval ${(Q)${(qq)K1//\%/$((+1.0 * $VALUE))}}
353  done
354 
355  getChi2 CHI2\[2\]
356 
357  for K1 in ${(O)BUFFER}; do
358  eval ${(Q)${(qq)K1//\%/$((-1.0 * $VALUE))}}
359  done
360 
361  for K1 in ${(o)BUFFER}; do
362  eval ${(Q)${(qq)K1//\%/$((-1.0 * $VALUE))}}
363  done
364 
365  getChi2 CHI2\[3\]
366 
367  for K1 in ${(O)BUFFER}; do
368  eval ${(Q)${(qq)K1//\%/$((+1.0 * $VALUE))}}
369  done
370 
371  if (( $DEBUG >= 3 )); then
372  printf "%-${WIDTH}s %12.5f %12.5f -> %+9.5f <- %+9.5f\n" $KEY $VALUE $CHI2[1] $(($CHI2[2] - $CHI2[1])) $(($CHI2[3] - $CHI2[1]))
373  fi
374 
375  # map index to derivative of chi2 and maintain sign of step
376 
377  if (($CHI2[2] < $CHI2[1] && $CHI2[2] < $CHI2[3])); then
378 
379  G[$i]=$(($CHI2[2] - $CHI2[1]))
380 
381  GRADIENT[$i]=+1.0
382 
383  elif (($CHI2[3] < $CHI2[1] && $CHI2[3] < $CHI2[2])); then
384 
385  G[$i]=$(($CHI2[3] - $CHI2[1]))
386 
387  GRADIENT[$i]=-1.0
388 #
389 # elif (($CHI2[3] - $CHI2[2] > 0.5*($CHI2[2] + $CHI2[3]) - $CHI2[1])); then
390 #
391 # G[$i]=$(($CHI2[2] - $CHI2[1]))
392 #
393 # GRADIENT[$i]=+0.33
394 #
395 # elif (($CHI2[2] - $CHI2[3] > 0.5*($CHI2[2] + $CHI2[3]) - $CHI2[1])); then
396 #
397 # G[$i]=$(($CHI2[3] - $CHI2[1]))
398 #
399 # GRADIENT[$i]=-0.33
400  fi
401 
402  let "i += 1"
403  done
404 
405 
406  if (( ${#G} == 0 )); then
407  break
408  fi
409 
410 
411  # sort derivatives of chi2 and optimise position one-by-one
412 
413  CHI2[2]=$CHI2[1]
414 
415  for i VALUE in `printf "%d %12.3e\n" ${(kv)G} | sort -g -k2`; do
416 
417  KEY=${${(ko)PARAMETERS}[$i]}
418 
419  BUFFER=(${(s/;/)${(Q)KEY}})
420 
421  # initial step size
422 
423  let "DS = $GRADIENT[$i] * $PARAMETERS[$KEY]"
424 
425  if (($DEBUG >= 3)); then
426  printf "%-${WIDTH}s %12.5f %12.5f\n" $KEY $DS $G[$i]
427  fi
428 
429  CHI2[3]=$CHI2[2]
430 
431  for (( n = 1; ; ++n )); do
432 
433  for K1 in ${(o)BUFFER}; do
434  eval ${(Q)${(qq)K1//\%/$((+1.0 * $DS))}}
435  done
436 
437  getChi2 CHI2\[4\]
438 
439  if (( $DEBUG >= 3 )); then
440  printf "chi2[4] %4d %12.5f\n" $n $CHI2[4]
441  fi
442 
443  if (( $CHI2[4] < $CHI2[3] )); then
444 
445  CHI2[3]=$CHI2[4]
446 
447  continue
448  fi
449 
450  for K1 in ${(O)BUFFER}; do
451  eval ${(Q)${(qq)K1//\%/$((-1.0 * $DS))}}
452  done
453 
454  if (( $CHI2[3] < $CHI2[2] )); then
455 
456  # final step based on parabolic interpolation through following points
457  #
458  # X1 = -1 * DS -> CHI[2]
459  # X2 = 0 * DS -> CHI[3]
460  # X3 = +1 * DS -> CHI[4]
461 
462  let "F21 = $CHI2[3] - $CHI2[2]" # F(X2) - F(X1)
463  let "F23 = $CHI2[3] - $CHI2[4]" # F(X2) - F(X3)
464 
465  let "XS = 0.5 * ($F21 - $F23) / ($F23 + $F21)"
466 
467  for K1 in ${(o)BUFFER}; do
468  eval ${(Q)${(qq)K1//\%/$((+1.0 * $XS * $DS))}}
469  done
470 
471  getChi2 CHI2\[4\]
472 
473  if (( $CHI2[4] < $CHI2[3] )); then
474 
475  CHI2[3]=$CHI2[4]
476 
477  else
478 
479  for K1 in ${(O)BUFFER}; do
480  eval ${(Q)${(qq)K1//\%/$((-1.0 * $XS * $DS))}}
481  done
482  fi
483  fi
484 
485  if (( $DEBUG >= 3 )); then
486  printf "chi2[3] %4d %12.5f\n" $n $CHI2[3]
487  fi
488 
489  break
490  done
491 
492  CHI2[2]=$CHI2[3]
493  done
494 
495  if (( fabs($CHI2[2] - $CHI2[1]) < $EPSILON * 0.5 * (fabs($CHI2[1]) + fabs($CHI2[2])) )); then
496 
497  CHI2[1]=$CHI2[2]
498 
499  break;
500  fi
501  done
502 
503  if (( $DEBUG >= 3 )); then
504  printf "chi2[1] %4d %12.5f\n" $N $CHI2[1]
505  fi
506 
507  eval $1=$CHI2[1]
508 }
set Main(RunControl, Responder) is
Definition: JDAQCHSM.chsm:188
then fatal No hydrophone data file $HYDROPHONE_TXT fi sort gr k
Q(UTCMax_s-UTCMin_s)-livetime_s
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
o $QUALITY_ROOT d $DEBUG!JPlot1D f
Definition: JDataQuality.sh:66
then JShowerPostfit f $INPUT_FILE o $OUTPUT_FILE N
static const double H
Planck constant [eV s].
*fatal Wrong number of arguments esac JCookie sh typeset Z DETECTOR typeset Z SOURCE_RUN typeset Z TARGET_RUN set_variable PARAMETERS_FILE $WORKDIR parameters
Definition: diff-Tuna.sh:38
exit
Definition: JPizza.sh:36
is
Definition: JDAQCHSM.chsm:167
then fatal Wrong number of arguments fi JConvertDetectorFormat a o
then echo
const int n
Definition: JPolint.hh:676
function getChi2()
then awk F
skip elif((BINFRAC< 1.0))
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable TRIPOD $argv[2] set_variable TX $argv[3] set_variable TY $argv[4] if[[!-f $DETECTOR]]
Definition: JFootprint.sh:28
then JMuonMCEvt f $INPUT_FILE o $INTERMEDIATE_FILE d
Definition: JMuonPath.sh:47
then JCalibrateToT a
Definition: JTuneHV.sh:116
then if[[!-f $DETECTOR]] then JDetector sh $DETECTOR fi cat $WORKDIR trigger_parameters txt<< EOFtrigger3DMuon.enabled=1;trigger3DMuon.numberOfHits=5;trigger3DMuon.gridAngle_deg=1;ctMin=0.0;TMaxLocal_ns=15.0;EOF set_variable TRIGGEREFFICIENCY_TRIGGERED_EVENTS_ONLY INPUT_FILES=() for((i=1;$i<=$NUMBER_OF_RUNS;++i));do JSirene.sh $DETECTOR $JPP_DATA/genhen.km3net_wpd_V2_0.evt.gz $WORKDIR/sirene_ ${i}.root JTriggerEfficiency.sh $DETECTOR $DETECTOR $WORKDIR/sirene_ ${i}.root $WORKDIR/trigger_efficiency_ ${i}.root $WORKDIR/trigger_parameters.txt $JPP_DATA/PMT_parameters.txt INPUT_FILES+=($WORKDIR/trigger_efficiency_ ${i}.root) done for ANGLE_DEG in $ANGLES_DEG[*];do set_variable SIGMA_NS 3.0 set_variable OUTLIERS 3 set_variable OUTPUT_FILE $WORKDIR/matrix\[${ANGLE_DEG}\deg\].root $JPP_DIR/examples/JReconstruction-f"$INPUT_FILES[*]"-o $OUTPUT_FILE-S ${SIGMA_NS}-A ${ANGLE_DEG}-O ${OUTLIERS}-d ${DEBUG}--!fiif[[$OPTION=="plot"]];then if((0));then for H1 in h0 h1;do JPlot1D-f"$WORKDIR/matrix["${^ANGLES_DEG}" deg].root:${H1}"-y"1 2e3"-Y-L TR-T""-\^"number of events [a.u.]"-> o chi2
Definition: JMatrixNZ.sh:106
esac typeset A BUFFER $JPP_DIR examples JAcoustics JCreep f $INPUT_FILE BUFFER
Definition: JCreep.sh:34
possible values
int sign(const T &value)
Get sign of value.
Definition: JLib.hh:20
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY JAcoustics sh $DETECTOR_ID source JAcousticsToolkit sh CHECK_EXIT_CODE typeset A EMITTERS get_tripods $WORKDIR tripod txt EMITTERS get_transmitters $WORKDIR transmitter txt EMITTERS for EMITTER in
Definition: JCanberra.sh:46
source $JPP_DIR setenv csh $JPP_DIR &dev null eval JShellParser o a A
script
Definition: JAcoustics.sh:2
esac done
Definition: JAddHDE.sh:21
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
do alias $i