]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/qa/RunQAMT.sh
Merge branch 'master' of https://git.cern.ch/reps/AliRoot
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / qa / RunQAMT.sh
1 #!/bin/bash
2 #
3 # This script runs the Forward QA for the specified production number
4 #
5 # The scripts downloads and runs the single run QA in parallel 
6 #
7
8 # --- Some aux files -------------------------------------------------
9 style=$ALICE_ROOT/PWGLF/FORWARD/analysis2/qa/style.css 
10 favicon=$ALICE_ROOT/PWGLF/FORWARD/analysis2/qa/fmd_favicon.png
11 logo=$ALICE_ROOT/PWGLF/FORWARD/analysis2/qa/fmd_logo.png
12 script=$ALICE_ROOT/PWGLF/FORWARD/analysis2/qa/script.js
13 topmk=$ALICE_ROOT/PWGLF/FORWARD/analysis2/qa/makeIndex.sh
14
15 # --- Help output ----------------------------------------------
16 usage()
17 {
18     cat <<EOF
19 Usage: $0 [OPTIONS] -j [JOBID]
20        $0 [OPTIONS] -p PRODUCTION -P PASS 
21
22 Options:
23         -h,--help                  This help 
24         -j,--jobid      NUMBER     The master job id of the production [$jobid]
25         -v,--verbose               Increase verbosity [$verb]
26         -m,--max-files  NUMBER     Max number of files to get [$maxf]
27         -M,--max-jobs   NUMBER     Max number of consequtive jobs [$maxjobs]
28         -t,--top        DIRECTORY  Output directory [$top]
29         -R,--also-results          Also get QAresults.root for each run
30         -Q,--qa-number  NUMBER     Custom QA id [$qanumber]
31         -p,--production IDENTIFIER Production identifier [$prodfull]
32         -P,--pass       IDENTIFIER Pass identifier [$passfull]
33         -l,--log-file              Log file output [$redir]
34         -b,--barrel     MODE       Fetch barrel data  [$barrel]
35         -f,--force                 Force re-run analysis [$force]
36         -V,--variance              Errors=variance (not min/max) [$variance]
37         -L,--local                 Local trending_<X>.root files [$from_local]
38         -d,--directory  DIR        Search custom AliEn directory [$path]
39
40 Note the option -j and the options -p and -P are mutually exclusive,
41 The option -Q is only used if the options -p and -P are given.
42 Production identifiers are of the form LHC11h, LHC11h3, or LHC11h_2. 
43 Pass identifers are of the form pass2, pass1_HLT, or cpass1.  
44 If barrel mode>0, then do not assume ESD directory.  
45 If barrel mode>1, then get trending_barrel.root and QAresults_barrel.root
46 Option -d is for hand-made QA passes. 
47 If optiond -d is not specified then official QA passes are assumed.
48 EOF
49 }
50
51 # --- Check AliEn token ----------------------------------------------
52 check_token()
53 {
54     uid=`id -u`
55     genv_file=/tmp/gclient_env_${uid}
56     
57     if test ! -f ${genv_file} ; then 
58         echo "No such file: ${genv_file}, please do alien-token-init" \
59             >/dev/stderr
60         exit 1
61     fi
62     . ${genv_file}
63     alien-token-info | grep -q "Token is still valid"
64     if test $? -ne 0 ; then 
65         echo "Token not valid, please re-new" > /dev/stderr 
66         exit 1
67     fi
68 }
69
70 # --- Diagnostics output ---------------------------------------------
71 verb=0
72 mess()
73 {
74     if test $1 -gt $verb ; then return ; fi 
75     shift
76     echo $*
77 }
78
79 # --- Handling of exit -----------------------------------------------
80 lock=
81 handle_exit()
82 {
83     if test "x$lock" = "x" ; then return ; fi 
84     if test "x$store" != "x" && test "x${top}" != "x" ; then 
85         chmod -R g+rwX ${top}/${proddir} >> ${redir} 2>&1
86         chmod -R g+rwX ${top}/$store >> ${redir} 2>&1
87     fi
88     rm -rf $lock 
89 }
90 trap handle_exit EXIT
91
92 # --- Handling of errors ---------------------------------------------
93 last=
94 handle_err()
95 {
96     echo "Error: $last" 
97     exit 1
98 }
99 enable_trap()
100 {
101     trap handle_err ERR
102 }
103 disable_trap()
104 {
105     trap - ERR
106 }
107
108 # --- Check the lock -------------------------------------------------
109 check_lock()
110 {
111     local loc=$1 
112     lock=$loc/.lock
113
114     if test -f $lock ; then 
115         echo "Another QA process is already running:" > /dev/stderr 
116         echo "Content of ${lock}:" > /dev/stderr 
117         cat $lock > /dev/stderr 
118         trap - EXIT
119     exit 1
120     local now=`date` 
121     cat <<EOF > $lock
122 Process: $$
123 User:    $USER
124 Start:   $now
125 EOF
126     fi
127 }
128
129 # --- Parse production information -----------------------------------
130 parse_prod()
131 {
132     prodyear=`echo $prodfull | sed 's/LHC\(..\).*/\1/'` 
133     prodletter=`echo $prodfull | sed "s/LHC${prodyear}\(.\).*/\1/"` 
134     prodpost=`echo $prodfull | sed "s/LHC${prodyear}${prodletter}//"` 
135 }
136
137 parse_pass()
138 {
139     passno=`echo $passfull | sed 's/.*pass\([0-9]*\).*/\1/'`  
140     passpost=`echo $passfull | sed -n "s/.*pass${passno}_//p"` 
141     passpre=`echo $passfull | sed -n "s/pass.*//p"` 
142 }
143
144 # --- Extract parts from the found path ------------------------------
145 force=0
146 year=0
147 passfull=
148 passno=0
149 passpost=
150 passpre=
151 prodfull=
152 prodyear=0
153 prodletter=
154 prodpost=
155 remainder=
156 qanumber=0
157 barrel=0
158 get_parts()
159 {
160     mess 1 "Parsing information from job $@" 
161     year=$1 ; shift 
162     prodfull=$1 ; shift 
163     local lrunn=$1 ; shift
164     local ltype=$1 ; shift 
165     passfull=$1 ; shift 
166     remainder=$1 
167
168     mess 10 "year=$year" 
169     mess 10 "prodfull=$prodfull" 
170     mess 10 "lrunn=$lrunn" 
171     mess 10 "ltype=$ltype" 
172     mess 10 "passfull=$passfull" 
173     mess 10 "remainder=$remainder"
174
175     if test "x$passfull" = "x" ; then 
176         remainder=
177         passfull=$ltype 
178     fi
179     case x$passfull in 
180         *pass*) ;; 
181         *) remainder=$passfull 
182             passfull= 
183             ;;
184     esac
185     parse_pass 
186     parse_prod
187
188     case x$remainder in 
189         xQA*) qanumber=`echo $remainder | sed 's/QA//'`  ;; 
190         *) ;; 
191     esac
192
193 }
194 # --- Get the index for information ----------------------------------
195 skip=0
196 jobu="http://alimonitor.cern.ch/prod/jobs.jsp?t="
197 jobid=
198 get_job() 
199
200     mess 1 "Getting the job information" 
201     wget -q ${jobu}${jobid} -O job.html
202     local lskip
203     let lskip=$skip+1
204     p=`grep "/catalogue/index.jsp?path" job.html | head -n $lskip | tail -n 1 | sed -e 's,.*/alice/\(data\|sim\)/\([^<]*\)<.*,\2,' | tr '/' ' '` 
205     rm -f job.html
206     get_parts $p 
207 }
208
209 # --- Append path element --------------------------------------------
210 append_to_path()
211 {
212     local tmp=$1 ; shift 
213     local add=$1
214     if test "x$tmp" != "x" ; then tmp="${tmp}/" ; fi 
215     echo ${tmp}${add}
216 }
217
218 # --- Get a list of files to get -------------------------------------
219 file=trending.root
220 other=QAresults.root
221 files=
222 path=
223 numf=0
224 from_local=0
225 get_filelist()
226 {
227     mess 3 "Getting file list" 
228
229     local datd=data
230     local esdd=ESDs/
231     if test ${barrel} -gt 0 ; then
232         esdd=
233     fi
234     if test ${barrel} -gt 1 ; then      
235         file=trending_barrel.root
236         other=QAresults_barrel.root
237     fi
238     case x$prodpost in 
239         x_*) ;; 
240         x) ;; 
241         *)  mess 3 "Assuming simulation output"
242             datd=sim 
243             esdd= 
244             ;; 
245     esac
246     
247     local paid=
248     if echo "$passno" | grep -q -E '^[0-9]*[.]?[0-9]*$' ; then 
249         if test "x$passfull" != "x" && test $passno -gt 0 ; then 
250             paid=pass${passno}
251         fi
252     else
253         paid=${passfull}
254         passpre=
255         post=
256     fi
257     local post=${passpost}
258     case x$post in 
259         x_*) ;; 
260         x) ;; 
261         *) post="_${post}" ;; 
262     esac
263
264     local search=
265     if test "x$path" = "x" ; then 
266         # Assume official productions 
267         path=/alice/${datd}/${year}/${prodfull}/
268         search="${esdd}${passpre}${paid}${post}"
269     else
270         search="*"
271     fi
272
273     if test $qanumber -gt 0 ; then 
274         qapost=`printf "QA%02d" $qanumber` 
275         search=`append_to_path "$search" $qapost` 
276     fi
277     
278     search=`append_to_path "$search" $file` 
279
280     cat <<EOF
281         Path:                   $path
282         Search:                 $search
283 EOF
284     if test $from_local -lt 1 ; then 
285
286         mess 1 "Getting list of files from AliEn - can take minutes - be patient"
287         mess 2 "alien_find ${path} ${search}"
288         files=`alien_find ${path} ${search} | grep -v "\(files found\|AND THE\)" 2>> ${redir}` 
289     else 
290         files=`ls ${top}/${store}/trending_*.root | sed 's,${top}/${store}/,,g'`
291     fi
292     for i in $files ; do 
293         let numf=$numf+1
294     done 
295     mess 1 -n "Total of $numf files ... "
296     if test $maxf -lt 0 ; then 
297         mess 1 "using all" 
298     else
299         mess 1 "using $maxf first of these"
300     fi
301 }
302
303 # --- Change permissions on files ------------------------------------
304 fix_perm()
305 {
306     # if test ! -f $1 ; then return ; fi 
307     chmod g+rwX $1 >> /dev/null 2>&1 
308     chmod o+rX $1 >> /dev/null 2>&1 
309     # 
310     # chmod g+rwX $1 >> ${redir} 2>&1 
311     # chmod o+rX $1 >> ${redir} 2>&1 
312 }
313
314 # --- Check if a file is OK ------------------------------------------
315 docheck=1
316 check_file()
317 {
318     if test $docheck -lt 1 ; then return 0; fi 
319     root -l -b  <<EOF >> ${redir} 2>&1 
320 .L $ALICE_ROOT/PWGLF/FORWARD/analysis2/qa/CheckQAFile.C
321 CheckQAFile("$1");
322 .q
323 EOF
324     local ret=$? 
325     mess 2 "Check of $1 -> $ret"
326     # rm -f ${scr}.C 
327     return $ret
328 }
329
330 # --- Analyse a file -------------------------------------------------
331 analyse_file()
332 {
333     local dir=`dirname $1` 
334     local inp=`basename $1` 
335     local out=`echo $inp | sed 's/trending_/tree_/'` 
336     local ret=0
337     mess 2 -n "Analysing $inp -> $out ... "
338
339     if test -f $dir/$out ; then 
340         if test $force -lt 1 ; then 
341             mess 2 "exits"
342             return 0
343         fi
344         rm -f $dir/$out
345     fi
346
347     (cd $dir 
348         root -l -b  <<EOF 
349 .L RunFileQA.C
350 RunFileQA("$inp", "$out", $prodyear, "$prodletter");
351 .q
352 EOF
353         ret=$? 
354         mess 2 " -> $ret"
355         # rm -f ${scr}.C 
356     ) 2>> $redir
357     return $ret
358 }
359
360 # --- Download a single file -----------------------------------------
361 also_results=0
362 analyse_run()
363 {
364     local source=$1 ; shift 
365     local store=$1 ; shift 
366     local r=$1 ; shift 
367     local o=${store}/`basename $file .root`_${r}.root 
368
369     mess 2 -n "$source -> $o ... "
370     if test -f $o && test $force -lt 2; then 
371         mess 2 "exists" 
372         # sleep 1
373     else
374         rm -f ${o}
375         mess 2 -n "copying ... " 
376         alien_cp alien:${source} file:${o} >> ${redir} 2>&1 
377         fix_perm $o 
378         mess 2 "done"
379     fi
380     if test ! -f $o ; then return 1 ; fi 
381
382     if test $also_results -gt 0 ; then 
383         local s=`dirname ${source}`/${other}
384         local q=${store}/`basename $other .root`_${r}.root
385
386         mess 2 -n "$s -> $q ... "
387         if test -f $q && test $force -lt 2 ; then 
388             mess 2 "exists" 
389         else
390             rm -rf ${q}
391             mess 2 -n "copying ... " 
392             alien_cp alien:${s} file:${q} >> ${redir} 2>&1 
393             fix_perm $q
394             mess 2 "done"
395         fi
396     fi
397
398         
399     check_file ${o} 
400     local ret=$? 
401     case $ret in 
402         0|2) ;; 
403         1|3|4|5|6) return 2 ;; 
404     esac
405
406     analyse_file ${o}
407
408     return 0
409 }
410
411 # --- Submit run analysis to background ------------------------------
412 submit_runs()
413 {
414     local out=$1 ; shift
415     local sta=$1 ; shift 
416     local max=$1 ; shift
417     
418     local joblist=
419     local counter=0
420     mess 5 "Submitting $maxjobs jobs from $sta/$maxf" 
421     for i in $@ ; do 
422         let cur=$sta+$counter
423
424         local r
425         if test $from_local -lt 1 ; then 
426             local b=`echo $i | sed -e "s,${path},,"` 
427             r=`echo $b | sed -e "s,/.*,,"` 
428         else
429             r=`basename $i .root | sed 's/trending_//'` 
430         fi
431
432         printf "%3d/%3d: %s\n" $cur $max $r 
433         runs[$counter]=$r
434
435         let counter=$counter+1
436         
437         analyse_run $i $out $r &
438         j=`jobs %% | sed -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'` 
439         joblist="$joblist $j"
440     done
441     
442     counter=0
443     mess 5 "will wait for jobs $joblist"
444     for i in $joblist ; do 
445         mess 5 "waiting for $i of $joblist"
446         wait %$i
447         mess 5 "Analysing ${runs[$counter]} returned $?" 
448         let counter=$counter+1
449     done
450 }
451     
452 # --- Analyse each run in turn ---------------------------------------
453 maxjobs=`grep "processor" /proc/cpuinfo | wc -l`
454 analyse_runs()
455 {
456     local out=$1 ; shift 
457     local max=$1 ; shift 
458     
459     local queued=0
460     local counter=0
461     local start=0
462     local list=
463     while test $# -gt 0 ; do 
464         if test $counter -ge $max ; then 
465             break;
466         fi
467
468         list="$list $1" 
469         shift 
470         let queued=$queued+1 
471         let counter=$counter+1 
472
473         if test $queued -eq 1 ; then 
474             start=$counter
475         fi
476         
477         if test $queued -ge $maxjobs ; then 
478             mess 1 "Submitting $queued jobs from $start/$max"
479             submit_runs $out $start $max $list 
480             list=
481             queued=0 
482         fi
483     done
484     if test $queued -gt 0 ; then 
485         mess 1 "Submitting $queued jobs from $start/$max"
486         submit_runs $out $start $max $list 
487     fi
488 }
489
490 # --- Copy style -----------------------------------------------------
491 copy_aliroot_file()
492 {
493     local file=$1 
494     if test ! -f $file ; then return ; fi 
495     base=`basename $file`
496     rm -f $base 
497     cp $file $base 
498     fix_perm $base
499 }
500 copy_style()
501 {
502     copy_aliroot_file $style
503 }       
504
505 # --- Run the final trending -----------------------------------------
506 variance=0
507 make_trend()
508 {
509     local dir=$1 
510     local ret=0
511     mess 1 -n "Analysing for trend $dir ... "
512     (cd $dir 
513         rm -f trend_*_*.html 
514         rm -f trend_*_*.pdf
515         rm -f trend_*_*.root
516
517         root -l -b <<EOF 
518 .L RunFinalQA.C
519 RunFinalQA(".", $prodyear, "$prodletter", $variance);
520 .q
521 EOF
522         mess 1 -n " ... "
523         # mess 3 -n "root -l -b -q ${scr}.C "
524         # root -l -b -q ${scr}.C  > /dev/null 2>&1 
525         # local ret=$? 
526         # mess 1 " -> $ret"
527         # rm -f ${scr}.C 
528
529         # do the index file 
530         local idx=`ls trend_*_*.html 2> /dev/null` 
531         for i in $idx ; do 
532             mess 1 "Making index.html point to $i" 
533             sed -e 's,index.html,../index.html,' \
534                 -e "s,!--JOBID--,a target='_blank' href='${jobu}${jobid}'>Job</a," \
535                 < $i > index.html 
536             cp index.html $i
537         done
538         
539         if test ! -f index.html ; then 
540             echo "No index file found" 
541             ret=1
542         else 
543             fix_perm index.html 
544             fix_perm . > /dev/null 2>&1 
545         fi
546
547         copy_style
548         copy_aliroot_file $favicon
549         copy_aliroot_file $logo
550     ) 2>> $redir
551     return $ret
552 }
553
554 # --- Make index file ------------------------------------------------
555 make_index()
556 {
557     local dir=$1   ; shift  
558     local title=$1 ; shift
559     local desc=$1  ; shift 
560     mess 1 "Making index in $dir ($title)"
561     
562     (cd $dir
563         local date=`date` 
564         
565         rm -f index.html 
566
567         cat <<EOF > index.html
568 <!DOCTYPE html>
569 <html>
570   <head>
571     <title>$title</title>
572     <link rel='stylesheet' href='style.css'>
573     <link rel='shortcut icon' href='fmd_favicon.png' type='image/x-png'>
574   </head>
575   <body>
576     <h1><img style='width: 200px;' src='fmd_logo.png'>  &nbsp;$title</h1>
577 EOF
578         if test ! "x$desc" = "x" ; then 
579             echo "<p>$desc</p>" >> index.html
580         fi
581         echo "      <ul>" >> index.html
582         for i in * ; do 
583             if test ! -d $i ; then continue ; fi 
584             echo "      <li><a href='$i'>$i</a></li>" >> index.html
585         done
586         echo "      </ul>" >> index.html 
587         if test "x$desc" = "x" ; then 
588             echo "      <div class='back'><a href='../'>Back</a></div>" \
589                 >> index.html
590         fi
591         cat <<EOF >> index.html    
592     <div class='change'>Last update: $date</div>
593   </body>
594 </html>
595 EOF
596         copy_style 
597         copy_aliroot_file $favicon
598         copy_aliroot_file $logo
599         fix_perm index.html
600         fix_perm . > /dev/null 2>&1 
601     )
602 }
603
604
605 # --- Pass command line options --------------------------------------
606 redir=/dev/null
607 maxf=-1
608 top=.
609 while test $# -gt 0 ; do 
610     case $1 in 
611         -h|--help) usage ; exit 0 ;; 
612         -v|--verbose)      let verb=$verb+1   ;; 
613         -j|--jobid)        jobid=$2           ; shift ;; 
614         -m|--max-files)    maxf=$2            ; shift ;; 
615         -M|--max-jobs)     maxjobs=$2         ; shift ;;
616         -t|--top)          top=$2             ; shift ;;
617         -R|--also-results) also_results=1     ;; 
618         -Q|--qa-number)    qanumber=$2        ; shift ;;
619         -l|--log-file)     redir=             ;; 
620         -L|--local)        from_local=1       ;;
621         -V|--variance)     variance=1         ;;
622         -b|--barrel)       barrel=$2          ; shift ;;
623         -f|--force)        let force=$force+1 ;; 
624         -p|--production) 
625             prodfull=$2; shift; parse_prod ; year=20${prodyear} ;;
626         -P|--pass) 
627             passfull=$2; shift; parse_pass ;;
628         -d|--directory)    path=$2              ; shift ;;
629         *) echo "$0: Unknown argument: $1" > /dev/stderr ; exit 1 ;; 
630     esac
631     shift
632 done
633 # --- Initial setup --------------------------------------------------
634 # First, check we have a valid AliEn token, then retrieve the job 
635 # information to parse out the location of the files we need, and 
636 # finally make our output directory and check the lock 
637 check_token
638
639 if test ! "x$jobid" = x ; then 
640     if test ! "x$prodfull" = "x" || test ! "x$passfull" = "x" ; then 
641         cat <<EOF > /dev/stderr
642 Option -j ${jobid} and options -p and -P are mutually exclusive 
643 EOF
644         exit 1
645     fi
646     get_job
647 else 
648     if test "x$prodfull" = "x" || test "x$passfull" = "x" ; then 
649         cat<<EOF > /dev/stderr
650 When specifying prodcution and/or pass both options -p and -P _must_ 
651 be specified. 
652 EOF
653         exit 1
654     elif test ! "x$jobid"  = "x" ; then 
655         cat <<EOF > /dev/stderr
656 Option -j and options -p ${prodfull} and -P ${passfull} are mutually exclusive 
657 EOF
658         exit 1
659     fi
660 fi      
661
662 proddir=LHC${prodyear}${prodletter}
663 store=${proddir}
664 if test ! "x$passno" = "x" ; then 
665     if test "x${passpre}" = "xv" || test "x${passpre}" = "xc"; then 
666         store=${store}/${passpre}pass${passno}
667     else
668         store=${store}/pass${passno}
669     fi
670 elif test ! "x$prodpost" = "x" ; then 
671     proddir=${proddir}${prodpost}
672     store=${proddir}/sim
673 elif test ! "x$remainder" = "x" ; then 
674     store=${store}/${remainder}
675 fi
676 if test ! "x$qanumber" = "x" && test $qanumber -gt 0 ; then 
677     store=${store}_QA${qanumber}
678 fi
679 mkdir -p ${top}/$store 
680 fix_perm ${top}/${proddir}
681 fix_perm ${top}/$store
682
683 if test "x$redir" = "x" ; then 
684     redir=${top}/$store/qa.log 
685     rm -f $redir
686     fix_perm $redir
687 fi
688
689 check_lock ${top}/$store
690
691 # --- Some friendly information --------------------------------------
692 cat <<EOF
693         Year:                   $year
694         Production:             $prodfull 
695           Year:                 $prodyear
696           Letter:               $prodletter
697           Suffix:               $prodpost
698         Pass:                   $passfull
699           Number:               $passno
700           Prefix:               $passpre
701           Postfix:              $passpost
702         Remainder               $remainder
703           QA number             $qanumber
704         Output directory:       ${store}
705         Lock file:              ${lock}
706         Log:                    ${redir}
707         Force:                  ${force}
708         Use variance:           ${variance}
709         Use pre-downloaded:     ${from_local}
710 EOF
711 # --- Do a search to find our files ----------------------------------
712 get_filelist
713
714 if test $maxf -gt 0 && test $maxf -lt $numf ; then 
715     numf=$maxf 
716 fi
717
718 # --- Copy scripts to target and compile -----------------------------
719 for i in QABase.h QAPlotter.C QARing.h QAStructs.h QATrender.C \
720     RunFileQA.C RunFinalQA.C ; do
721     cp $ALICE_ROOT/PWGLF/FORWARD/analysis2/qa/$i ${store}/${i}
722     rm -f ${store}/`echo $i | tr '.' '_'`.{so,d}
723     fix_perm ${store}/${i}
724 done
725 mess 1 "Compiling QATrender.C"
726 (cd $store && root -l -b <<EOF 
727 gROOT->LoadMacro("QABase.h++g");
728 gROOT->LoadMacro("QATrender.C++g");
729 .q
730 EOF
731 )
732 mess 1 "Compiling QAPlotter.C"
733 (cd $store && root -l -b <<EOF 
734 gROOT->LoadMacro("QABase.h++g");
735 gROOT->LoadMacro("QAPlotter.C++g");
736 .q
737 EOF
738 )
739 (cd ${store} && for i in *.so *.d ; do fix_perm $i ; done)
740
741 # --- Now get and analyse each run -----------------------------------
742 analyse_runs ${top}/$store $numf $files
743
744 # --- Now analyse all runs -------------------------------------------
745 make_trend ${top}/$store
746
747 # --- Make index files -----------------------------------------------
748 make_index ${top}/${proddir} ${proddir}
749 # make_index ${top} "QA for the FMD" \
750 #    "For more information see <a href='https://twiki.cern.ch/twiki/bin/viewauth/ALICE/FMDQA'>TWiki pages</a>."
751 $topmk --title "QA for the FMD" \
752     --description "For more information see <a href='https://twiki.cern.ch/twiki/bin/viewauth/ALICE/FMDQA'>TWiki pages</a>." \
753     --link \
754     --max-depth 2 \
755     --output index.html 
756 fix_perm index.html
757 copy_aliroot_file $script
758
759 chmod -R g+rwX ${top}/${proddir} >> ${redir} 2>&1
760
761 #
762 # EOF
763 #