Jpp  17.3.2
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 typeset -A PARAMETERS # fit parameters
28 
29 if [[ -z "$DEBUG" ]]; then
30  DEBUG=0
31 fi
32 
33 
34 #
35 # Auxiliary function to evaluate chi2 and gradient thereof at current position.
36 #
37 # The external method getChi2 is used to evaluate the chi2.
38 # The value corresponding to each key in the associative array PARAMETERS
39 # is used as unit step size for the evaluation of the derivative of the chi2.
40 # The results are stored in the internal variables CHI2[1] and GRADIENT, respectively.
41 #
42 function evaluate()
43 {
44  GRADIENT=()
45 
46  getChi2 CHI2\[1\]
47 
48  let "WIDTH = 1"
49 
50  for KEY in ${(k)PARAMETERS}; do
51  if (( ${#KEY} > $WIDTH )); then
52  let "WIDTH = ${#KEY}"
53  fi
54  done
55 
56  let "V = 0.0"
57  let "i = 1"
58 
59  for KEY in ${(ko)PARAMETERS}; do
60 
61  BUFFER=(${(s/;/)${(Q)KEY}})
62 
63  VALUE=$PARAMETERS[$KEY]
64 
65  if (( $VALUE != 0.0 )); then
66 
67  for K1 in ${(o)BUFFER}; do
68  eval ${(Q)${(qq)K1//\%/$((+0.5 * $VALUE))}}
69  done
70 
71  getChi2 CHI2\[2\]
72 
73  for K1 in ${(O)BUFFER}; do
74  eval ${(Q)${(qq)K1//\%/$((-0.5 * $VALUE))}}
75  done
76 
77  for K1 in ${(o)BUFFER}; do
78  eval ${(Q)${(qq)K1//\%/$((-0.5 * $VALUE))}}
79  done
80 
81  getChi2 CHI2\[3\]
82 
83  for K1 in ${(O)BUFFER}; do
84  eval ${(Q)${(qq)K1//\%/$((+0.5 * $VALUE))}}
85  done
86 
87  GRADIENT[$i]=$(($CHI2[2] - $CHI2[3]))
88  else
89 
90  GRADIENT[$i]=0.0
91  fi
92 
93  if (( $DEBUG >= 3 )); then
94  printf "%-${WIDTH}s %12.5f %12.5f\n" $KEY $PARAMETERS[$KEY] $GRADIENT[$i]
95  fi
96 
97  let "V += $GRADIENT[$i]*$GRADIENT[$i]"
98  let "i += 1"
99  done
100 
101  if (( $DEBUG >= 3 )); then
102  printf "%-${WIDTH}s %12s %12.5f\n" "|gradient|" "" $((sqrt($V)))
103  fi
104 }
105 
106 
107 #
108 # Move current position along gradient by given scaling factor of the unit step sizes.
109 #
110 # \param 1 scaling factor
111 #
112 function move()
113 {
114  if (( $1 > 0.0 )); then
115 
116  let "i = 1"
117 
118  for KEY in ${(ko)PARAMETERS}; do
119 
120  BUFFER=(${(s/;/)${(Q)KEY}})
121 
122  for K1 in ${(o)BUFFER}; do
123  eval ${(Q)${(qq)K1//\%/$(($GRADIENT[$i] * $1 * $PARAMETERS[$KEY]))}}
124  done
125 
126  let "i += 1"
127  done
128 
129  else
130 
131  let "i = ${#GRADIENT}"
132 
133  for KEY in ${(kO)PARAMETERS}; do
134 
135  BUFFER=(${(s/;/)${(Q)KEY}})
136 
137  for K1 in ${(O)BUFFER}; do
138  eval ${(Q)${(qq)K1//\%/$(($GRADIENT[$i] * $1 * $PARAMETERS[$KEY]))}}
139  done
140 
141  let "i -= 1"
142  done
143  fi
144 }
145 
146 
147 #
148 # Main fit function.
149 #
150 # The algorithm is based on the conjugate gradient method.
151 # The position is moved to the optimal value and the final chi2 is returned.
152 #
153 # If the option is one, the step sizes are fine-tuned according to the gradient of the chi2.
154 # The value corresponding to each key in the associative array PARAMETERS is then
155 # multiplied by the corresponding element in GRADIENT and only the sign thereof is maintained.
156 #
157 # \param 1 maximum number of extra steps
158 # \param 2 variable containing final chi2 value on return
159 #
160 function gradient()
161 {
162  typeset -a G
163  typeset -a H
164 
165  if (( ${#PARAMETERS} == 0 )); then
166  return
167  fi
168 
169  evaluate
170 
171  # initialise
172 
173  for (( i = 1; i <= ${#GRADIENT}; ++i)); do
174  G[$i]=$((-1.0 * $GRADIENT[$i]))
175  H[$i]=$G[$i]
176  GRADIENT[$i]=$H[$i]
177  done
178 
179  for (( N = 0; $N != $NUMBER_OF_ITERATIONS; N += 1 )); do
180 
181  if (( $DEBUG >= 3 )); then
182  printf "chi2[1] %4d %12.5f\n" $N $CHI2[1]
183  fi
184 
185  # minimise chi2 in direction of gradient
186 
187  CHI2[2]=$CHI2[1]
188  CHI2[3]=$CHI2[2]
189 
190  for (( DS = 1.0, M = 0 ; $DS > 1.0e-3; )); do
191 
192  move $DS
193 
194  getChi2 CHI2\[4\]
195 
196  if (( $DEBUG >= 3 )); then
197  printf "chi2[4] %4d %12.5f %12.5e\n" $M $CHI2[4] $DS
198  fi
199 
200  if (( $CHI2[4] < $CHI2[3] )); then
201 
202  # continue
203 
204  CHI2[2]=$CHI2[3]
205  CHI2[3]=$CHI2[4]
206 
207  let "M = 0"
208 
209  continue
210  fi
211 
212  # if chi2 increases, try additional steps first to overcome possible hurdle, then try single step with reduced size
213 
214  if (( $DS == 1.0 )); then
215 
216  if (( $M == 0 )); then
217  CHI2[5]=$CHI2[4]
218  fi
219 
220  if (( $M != $1 )); then
221 
222  let "M += 1"
223 
224  continue;
225 
226  else
227 
228  for (( ; $M != 0; --M )); do
229  move $((-1.0 * $DS))
230  done
231 
232  CHI2[4]=$CHI2[5]
233  fi
234  fi
235 
236  move $((-1.0 * $DS))
237 
238  if (( $CHI2[3] < $CHI2[2] )); then
239 
240  # final step based on parabolic interpolation through following points
241  #
242  # X1 = -1 * DS -> CHI[2]
243  # X2 = 0 * DS -> CHI[3]
244  # X3 = +1 * DS -> CHI[4]
245 
246  let "F21 = $CHI2[3] - $CHI2[2]" # F(X2) - F(X1)
247  let "F23 = $CHI2[3] - $CHI2[4]" # F(X2) - F(X3)
248 
249  let "XS = 0.5 * ($F21 - $F23) / ($F23 + $F21)"
250 
251  move $((+1.0 * $XS * $DS))
252 
253  getChi2 CHI2\[4\]
254 
255  if (( $CHI2[4] < $CHI2[3] )); then
256 
257  CHI2[3]=$CHI2[4]
258 
259  else
260 
261  move $((-1.0 * $XS * $DS))
262 
263  getChi2 CHI2\[3\]
264  fi
265 
266  if (( $DEBUG >= 3 )); then
267  printf "chi2[3] %4d %12.5f %12.5e\n" $N $CHI2[3] $DS
268  fi
269 
270  break
271 
272  else
273 
274  # reduce step size
275 
276  let "DS *= 0.5"
277  fi
278  done
279 
280  if (( fabs($CHI2[3] - $CHI2[1]) < $EPSILON * 0.5 * (fabs($CHI2[1]) + fabs($CHI2[3])) )); then
281 
282  CHI2[1]=$CHI2[3]
283 
284  break;
285  fi
286 
287  evaluate
288 
289  let "GG = 0.0"
290  let "DGG = 0.0"
291 
292  for (( i = 1; $i <= ${#GRADIENT}; ++i )); do
293  let "GG += $G[$i]*$G[$i]"
294  let "DGG += ($GRADIENT[$i] + $G[$i]) * $GRADIENT[$i]"
295  done
296 
297  if (( $GG == 0.0 )); then
298  break
299  fi
300 
301  let "GAM = $DGG / $GG"
302 
303  for (( i = 1; $i <= ${#GRADIENT}; ++i )); do
304  G[$i]=$((-1.0 * $GRADIENT[$i]))
305  H[$i]=$(($G[$i] + $GAM * $H[$i]))
306  GRADIENT[$i]=$H[$i]
307  done
308  done
309 
310  if (( $DEBUG >= 3 )); then
311  printf "chi2[1] %4d %12.5f\n" $N $CHI2[1]
312  fi
313 
314  eval $2=$CHI2[1]
315 }
316 
317 
318 #
319 # Additional fit function to be called after gradient.
320 #
321 # The algorithm is based on sorting the derivatives of the chi2 and
322 # moving the position one-by-one to the optimal value.
323 # The final chi2 is returned.
324 #
325 # \param 1 variable containing final chi2 value on return
326 #
327 function simplex()
328 {
329  typeset -A G
330 
331 
332  let "WIDTH = 1"
333 
334  for KEY in ${(k)PARAMETERS}; do
335  if (( ${#KEY} > $WIDTH )); then
336  let "WIDTH = ${#KEY}"
337  fi
338  done
339 
340 
341  for (( N = 0; $N != $NUMBER_OF_ITERATIONS; N += 1 )); do
342 
343  G=()
344 
345  GRADIENT=()
346 
347  getChi2 CHI2\[1\]
348 
349  let "i = 1"
350 
351  for KEY in ${(ko)PARAMETERS}; do
352 
353  VALUE=$PARAMETERS[$KEY]
354 
355  BUFFER=(${(s/;/)${(Q)KEY}})
356 
357  for K1 in ${(o)BUFFER}; do
358  eval ${(Q)${(qq)K1//\%/$((+1.0 * $VALUE))}}
359  done
360 
361  getChi2 CHI2\[2\]
362 
363  for K1 in ${(O)BUFFER}; do
364  eval ${(Q)${(qq)K1//\%/$((-1.0 * $VALUE))}}
365  done
366 
367  for K1 in ${(o)BUFFER}; do
368  eval ${(Q)${(qq)K1//\%/$((-1.0 * $VALUE))}}
369  done
370 
371  getChi2 CHI2\[3\]
372 
373  for K1 in ${(O)BUFFER}; do
374  eval ${(Q)${(qq)K1//\%/$((+1.0 * $VALUE))}}
375  done
376 
377  if (( $DEBUG >= 3 )); then
378  printf "%-${WIDTH}s %12.5f %12.5f -> %+9.5f <- %+9.5f\n" $KEY $VALUE $CHI2[1] $(($CHI2[2] - $CHI2[1])) $(($CHI2[3] - $CHI2[1]))
379  fi
380 
381  # map index to derivative of chi2 and maintain sign of step
382 
383  if (($CHI2[2] < $CHI2[1] && $CHI2[2] < $CHI2[3])); then
384 
385  G[$i]=$(($CHI2[2] - $CHI2[1]))
386 
387  GRADIENT[$i]=+1.0
388 
389  elif (($CHI2[3] < $CHI2[1] && $CHI2[3] < $CHI2[2])); then
390 
391  G[$i]=$(($CHI2[3] - $CHI2[1]))
392 
393  GRADIENT[$i]=-1.0
394 #
395 # elif (($CHI2[3] - $CHI2[2] > 0.5*($CHI2[2] + $CHI2[3]) - $CHI2[1])); then
396 #
397 # G[$i]=$(($CHI2[2] - $CHI2[1]))
398 #
399 # GRADIENT[$i]=+0.33
400 #
401 # elif (($CHI2[2] - $CHI2[3] > 0.5*($CHI2[2] + $CHI2[3]) - $CHI2[1])); then
402 #
403 # G[$i]=$(($CHI2[3] - $CHI2[1]))
404 #
405 # GRADIENT[$i]=-0.33
406  fi
407 
408  let "i += 1"
409  done
410 
411 
412  if (( ${#G} == 0 )); then
413  break
414  fi
415 
416 
417  # sort derivatives of chi2 and optimise position one-by-one
418 
419  CHI2[2]=$CHI2[1]
420 
421  for i VALUE in `printf "%d %12.3e\n" ${(kv)G} | sort -g -k2`; do
422 
423  KEY=${${(ko)PARAMETERS}[$i]}
424 
425  BUFFER=(${(s/;/)${(Q)KEY}})
426 
427  # initial step size
428 
429  let "DS = $GRADIENT[$i] * $PARAMETERS[$KEY]"
430 
431  if (($DEBUG >= 3)); then
432  printf "%-${WIDTH}s %12.5f %12.5f\n" $KEY $DS $G[$i]
433  fi
434 
435  CHI2[3]=$CHI2[2]
436 
437  for (( n = 1; ; ++n )); do
438 
439  for K1 in ${(o)BUFFER}; do
440  eval ${(Q)${(qq)K1//\%/$((+1.0 * $DS))}}
441  done
442 
443  getChi2 CHI2\[4\]
444 
445  if (( $DEBUG >= 3 )); then
446  printf "chi2[4] %4d %12.5f\n" $n $CHI2[4]
447  fi
448 
449  if (( $CHI2[4] < $CHI2[3] )); then
450 
451  CHI2[3]=$CHI2[4]
452 
453  continue
454  fi
455 
456  for K1 in ${(O)BUFFER}; do
457  eval ${(Q)${(qq)K1//\%/$((-1.0 * $DS))}}
458  done
459 
460  if (( $CHI2[3] < $CHI2[2] )); then
461 
462  # final step based on parabolic interpolation through following points
463  #
464  # X1 = -1 * DS -> CHI[2]
465  # X2 = 0 * DS -> CHI[3]
466  # X3 = +1 * DS -> CHI[4]
467 
468  let "F21 = $CHI2[3] - $CHI2[2]" # F(X2) - F(X1)
469  let "F23 = $CHI2[3] - $CHI2[4]" # F(X2) - F(X3)
470 
471  let "XS = 0.5 * ($F21 - $F23) / ($F23 + $F21)"
472 
473  for K1 in ${(o)BUFFER}; do
474  eval ${(Q)${(qq)K1//\%/$((+1.0 * $XS * $DS))}}
475  done
476 
477  getChi2 CHI2\[4\]
478 
479  if (( $CHI2[4] < $CHI2[3] )); then
480 
481  CHI2[3]=$CHI2[4]
482 
483  else
484 
485  for K1 in ${(O)BUFFER}; do
486  eval ${(Q)${(qq)K1//\%/$((-1.0 * $XS * $DS))}}
487  done
488  fi
489  fi
490 
491  if (( $DEBUG >= 3 )); then
492  printf "chi2[3] %4d %12.5f\n" $n $CHI2[3]
493  fi
494 
495  break
496  done
497 
498  CHI2[2]=$CHI2[3]
499  done
500 
501  if (( fabs($CHI2[2] - $CHI2[1]) < $EPSILON * 0.5 * (fabs($CHI2[1]) + fabs($CHI2[2])) )); then
502 
503  CHI2[1]=$CHI2[2]
504 
505  break;
506  fi
507  done
508 
509  if (( $DEBUG >= 3 )); then
510  printf "chi2[1] %4d %12.5f\n" $N $CHI2[1]
511  fi
512 
513  eval $1=$CHI2[1]
514 }
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
then usage $script[< detector identifier >< run range >]< QA/QCfile > nExample script to produce data quality plots nWhen a detector identifier and run range are data are downloaded from the database nand subsequently stored in the given QA QC file
Definition: JDataQuality.sh:19
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!CHECK_EXIT_CODE JPlot1D f
Definition: JDataQuality.sh:76
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:697
then JCalibrateToT a
Definition: JTuneHV.sh:116
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 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
double getChi2(const double P)
Get chi2 corresponding to given probability.
Definition: JFitToolkit.hh:56
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