Skip to content

Commit 9fb1b2e

Browse files
authored
simple truth efficiency calculator (#396)
* update URL * truth efficiency matrix calculator * cleanup, add warning printout * rename, cleanup, add json * merge scripts * use an array * parallelize * cleanup * actually loop * now it works * use gemc files with truth-matching enabled * cleanup, run truth efficiency * bugfix * cleanup and bugfix * bugfix, now it works * avoid unnecessary lookups * more convenient JSON structure * cleanup for thread safety * make adding threadsafe
1 parent 3896b8f commit 9fb1b2e

File tree

7 files changed

+279
-56
lines changed

7 files changed

+279
-56
lines changed

bin/trutheff

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
. `dirname $0`/../libexec/env.sh
4+
5+
export MALLOC_ARENA_MAX=1
6+
7+
java -Xmx1536m -Xms1024m -XX:+UseSerialGC \
8+
-cp "$CLAS12DIR/lib/clas/*:$CLAS12DIR/lib/services/*:$CLAS12DIR/lib/utils/*" \
9+
org.jlab.analysis.efficiency.Truth \
10+
$*
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package org.jlab.analysis.efficiency;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
import java.util.TreeMap;
7+
import org.jlab.jnp.hipo4.data.Bank;
8+
import org.jlab.jnp.hipo4.data.Event;
9+
import org.jlab.jnp.hipo4.data.Schema;
10+
import org.jlab.jnp.hipo4.data.SchemaFactory;
11+
import org.jlab.jnp.hipo4.io.HipoReader;
12+
import org.jlab.jnp.utils.json.JsonArray;
13+
import org.jlab.jnp.utils.json.JsonObject;
14+
import org.jlab.utils.options.OptionParser;
15+
16+
/**
17+
* Efficiency matrix calculator based solely on the MC::GenMatch truth-matching
18+
* bank (which is purely hit-based), and a pid assignment match in MC::Particle
19+
* and REC::Particle.
20+
*
21+
* @author baltzell
22+
*/
23+
public class Truth {
24+
25+
static final int UDF = 0;
26+
static final List<Integer> NEGATIVES = Arrays.asList(11, -211, -321, -2212);
27+
static final List<Integer> POSITIVES = Arrays.asList(-11, 211, 321, 2212, 45);
28+
static final List<Integer> NEUTRALS = Arrays.asList(22, 2112);
29+
30+
List<Integer> validPids;
31+
Schema mcGenMatch;
32+
Schema mcParticle;
33+
Schema recParticle;
34+
long[][] recTallies;
35+
long[] mcTallies;
36+
37+
public static void main(String[] args) {
38+
OptionParser o = new OptionParser("trutheff");
39+
o.setRequiresInputList(true);
40+
o.parse(args);
41+
Truth t = new Truth(o.getInputList().get(0));
42+
t.add(o.getInputList());
43+
System.out.println(t.toTable());
44+
System.out.println(t.toJson());
45+
}
46+
47+
public Truth(SchemaFactory s) {
48+
init(s);
49+
}
50+
51+
public Truth(HipoReader r) {
52+
init(r.getSchemaFactory());
53+
}
54+
55+
public Truth(String filename) {
56+
HipoReader r = new HipoReader();
57+
r.open(filename);
58+
init(r.getSchemaFactory());
59+
}
60+
61+
private void init(SchemaFactory schema) {
62+
validPids = new ArrayList(NEGATIVES);
63+
validPids.addAll(POSITIVES);
64+
validPids.addAll(NEUTRALS);
65+
validPids.add(UDF);
66+
mcTallies = new long[validPids.size()];
67+
recTallies = new long[validPids.size()][validPids.size()];
68+
mcGenMatch = schema.getSchema("MC::GenMatch");
69+
mcParticle = schema.getSchema("MC::Particle");
70+
recParticle = schema.getSchema("REC::Particle");
71+
}
72+
73+
/**
74+
* Get one element of the efficiency matrix.
75+
* @param truth true PID
76+
* @param rec reconstructed PID
77+
* @return probability
78+
*/
79+
public float get(int truth, int rec) {
80+
long sum = mcTallies[validPids.indexOf(truth)];
81+
return sum>0 ? ((float)recTallies[validPids.indexOf(truth)][validPids.indexOf(rec)])/sum : 0;
82+
}
83+
84+
/**
85+
* Add an event in the form of truth and reconstructed particle species.
86+
* @param truth truth PID
87+
* @param rec reconstructed PID
88+
*/
89+
public synchronized void add(int truth, int rec) {
90+
final int t = validPids.indexOf(truth);
91+
if (t < 0) return;
92+
final int r = validPids.indexOf(rec);
93+
mcTallies[t]++;
94+
if (r < 0) recTallies[t][UDF]++;
95+
else recTallies[t][r]++;
96+
}
97+
98+
/**
99+
* Add a HIPO event.
100+
* @param e
101+
*/
102+
public void add(Event e) {
103+
Bank bm = new Bank(mcParticle);
104+
Bank br = new Bank(recParticle);
105+
e.read(bm);
106+
e.read(br);
107+
TreeMap<Short,Short> good = getMapping(e);
108+
for (short row=0; row<bm.getRows(); ++row) {
109+
if (!good.containsKey(row)) add(bm.getInt("pid",row), UDF);
110+
else add(bm.getInt("pid",row), br.getInt("pid",good.get(row)));
111+
}
112+
}
113+
114+
/**
115+
* Add input HIPO files by path.
116+
* @param filenames
117+
*/
118+
public void add(List<String> filenames) {
119+
Event e = new Event();
120+
for (String f : filenames) {
121+
HipoReader r = new HipoReader();
122+
r.open(f);
123+
while (r.hasNext()) {
124+
r.nextEvent(e);
125+
add(e);
126+
}
127+
}
128+
}
129+
130+
/**
131+
* Truth-matching banks contain pointers to MC::Particle and REC::Particle,
132+
* and here we cache that mapping to avoid nested loops.
133+
*/
134+
private TreeMap getMapping(Event e) {
135+
Bank b = new Bank(mcGenMatch);
136+
e.read(b);
137+
TreeMap<Short,Short> m = new TreeMap<>();
138+
for (int row=0; row<b.getRows(); ++row)
139+
m.put(b.getShort("mcindex", row), b.getShort("pindex",row));
140+
return m;
141+
}
142+
143+
/**
144+
* Get efficiencies as a human-readable table.
145+
* @return
146+
*/
147+
public String toTable() {
148+
StringBuilder s = new StringBuilder();
149+
s.append(" ");
150+
for (int i=0; i<validPids.size(); ++i) {
151+
s.append(String.format("%7d",validPids.get(i)));
152+
if (validPids.size()==i+1) s.append("\n");
153+
}
154+
for (int i=0; i<validPids.size(); ++i) {
155+
s.append(String.format("%6d",validPids.get(i)));
156+
for (int j=0; j<validPids.size(); ++j) {
157+
s.append(String.format("%7.4f",get(validPids.get(i),validPids.get(j))));
158+
if (validPids.size()==j+1) s.append("\n");
159+
}
160+
}
161+
return s.toString();
162+
}
163+
164+
/**
165+
* Get efficiencies as a JSON object.
166+
* @return
167+
*/
168+
public JsonObject toJson() {
169+
JsonObject effs = new JsonObject();
170+
JsonArray pids = new JsonArray();
171+
for (int i=0; i<validPids.size(); ++i) {
172+
pids.add(validPids.get(i));
173+
JsonArray a = new JsonArray();
174+
for (int j=0; j<validPids.size(); ++j)
175+
a.add(get(validPids.get(i),validPids.get(j)));
176+
effs.add(Integer.toString(validPids.get(i)),a);
177+
}
178+
JsonObject ret = new JsonObject();
179+
ret.add("pids", pids);
180+
ret.add("effs", effs);
181+
return ret;
182+
}
183+
}

common-tools/clas-utils/src/main/java/org/jlab/utils/options/OptionParser.java

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
/*
2-
* To change this license header, choose License Headers in Project Properties.
3-
* To change this template file, choose Tools | Templates
4-
* and open the template in the editor.
5-
*/
61
package org.jlab.utils.options;
72

83
import java.util.ArrayList;
@@ -16,17 +11,15 @@
1611
*/
1712
public class OptionParser {
1813

19-
private Map<String,OptionValue> optionsDescriptors = new TreeMap<String,OptionValue>();
20-
private Map<String,OptionValue> requiredOptions = new TreeMap<String,OptionValue>();
21-
private Map<String,OptionValue> parsedOptions = new TreeMap<String,OptionValue>();
22-
private List<String> parsedInputList = new ArrayList<String>();
14+
private Map<String,OptionValue> optionsDescriptors = new TreeMap<>();
15+
private Map<String,OptionValue> requiredOptions = new TreeMap<>();
16+
private Map<String,OptionValue> parsedOptions = new TreeMap<>();
17+
private List<String> parsedInputList = new ArrayList<>();
2318
private String program = "undefined";
2419
private boolean requiresInputList = true;
2520
private String programDescription = "";
2621

27-
public OptionParser(){
28-
29-
}
22+
public OptionParser(){}
3023

3124
public OptionParser(String pname){
3225
this.program = pname;
@@ -130,7 +123,6 @@ public void parse(String[] args){
130123
System.exit(0);
131124
}
132125

133-
//this.show(arguments);
134126
for(Map.Entry<String,OptionValue> entry : this.requiredOptions.entrySet()){
135127
boolean status = entry.getValue().parse(arguments);
136128
if(status==false) {
@@ -153,7 +145,11 @@ public void parse(String[] args){
153145
this.parsedInputList.add(item);
154146
}
155147
}
156-
//this.show(arguments);
148+
149+
// FIXME: seems like we should really be throwing a RuntimeException ...
150+
if (this.requiresInputList && this.parsedInputList.isEmpty()) {
151+
System.err.println(" \n*** ERROR *** Empty Input List.");
152+
}
157153
}
158154

159155
public List<String> getInputList(){
@@ -167,9 +163,7 @@ public static void main(String[] args){
167163
parser.addOption("-r", "10");
168164
parser.addOption("-t", "25.0");
169165
parser.addOption("-d", "35");
170-
171166
parser.parse(options);
172-
173167
parser.show();
174168
}
175169
}

install-clara

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function cleanup() {
5959

6060
function build_clara {
6161
export CLARA_HOME=$1
62-
git clone https://github.com/baltzell/clara-java
62+
git clone https://code.jlab.org/hallb/clas12/clara-java
6363
cd clara-java
6464
git checkout java21
6565
./gradlew && ./gradlew deploy

validation/advanced-tests/run-eb-tests.sh

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

33
webDir=http://clasweb.jlab.org/clas12offline/distribution/coatjava/validation_files/eb
4-
webVersion=5.10-fid-r11
4+
webVersion=5.10-fid-tm-r11
55
webDir=$webDir/$webVersion
66

77
# coatjava must already be built at ../../coatjava/
@@ -40,11 +40,11 @@ do
4040
done
4141

4242
# last argument is input file stub:
43-
webFileStub="${@: -1}"
43+
stub="${@: -1}"
4444

4545
# sanity check on filestub name,
4646
# just to error with reasonable message before proceeding:
47-
case $webFileStub in
47+
case $stub in
4848
# electron in forward, hadron in forward:
4949
electronproton)
5050
;;
@@ -79,7 +79,7 @@ case $webFileStub in
7979
electrondeuteronC)
8080
;;
8181
*)
82-
echo Invalid input evio file: $webFileStub
82+
echo Invalid input evio file: $stub
8383
exit 1
8484
esac
8585

@@ -122,28 +122,28 @@ then
122122
fi
123123

124124
# download test files, if necessary:
125-
wget -N --no-check-certificate $webDir/${webFileStub}.hipo
125+
wget -N --no-check-certificate $webDir/${stub}.hipo
126126
if [ $? != 0 ] ; then echo "wget validation files failure" ; exit 1 ; fi
127127

128128
# update the schema dictionary: (no longer necessary now that recon-util does it)
129-
#rm -f up_${webFileStub}.hipo
130-
#../../coatjava/bin/hipo-utils -update -d ../../coatjava/etc/bankdefs/hipo4/ -o up_${webFileStub}.hipo ${webFileStub}.hipo
129+
#rm -f up_${stub}.hipo
130+
#../../coatjava/bin/hipo-utils -update -d ../../coatjava/etc/bankdefs/hipo4/ -o up_${stub}.hipo ${stub}.hipo
131131

132132
# run reconstruction:
133-
rm -f out_${webFileStub}.hipo
133+
rm -f out_${stub}.hipo
134134
if [ $useClara -eq 0 ]
135135
then
136136
GEOMDBVAR=$geoDbVariation
137137
export GEOMDBVAR
138-
../../coatjava/bin/recon-util -i ${webFileStub}.hipo -o out_${webFileStub}.hipo -c 2
138+
../../coatjava/bin/recon-util -i ${stub}.hipo -o out_${stub}.hipo -c 2
139139
else
140140
echo "set inputDir $PWD/" > cook.clara
141141
echo "set outputDir $PWD/" >> cook.clara
142142
echo "set threads 7" >> cook.clara
143143
echo "set javaMemory 2" >> cook.clara
144144
echo "set session s_cook" >> cook.clara
145145
echo "set description d_cook" >> cook.clara
146-
ls ${webFileStub}.hipo > files.list
146+
ls ${stub}.hipo > files.list
147147
echo "set fileList $PWD/files.list" >> cook.clara
148148
echo "run local" >> cook.clara
149149
echo "exit" >> cook.clara
@@ -152,8 +152,10 @@ then
152152
fi
153153

154154
# run Event Builder tests:
155-
java -DCLAS12DIR="$COAT" -Xmx1536m -Xms1024m -cp $classPath2 -DINPUTFILE=out_${webFileStub}.hipo org.junit.runner.JUnitCore eb.EBTwoTrackTest
155+
java -DCLAS12DIR="$COAT" -Xmx1536m -Xms1024m -cp $classPath2 -DINPUTFILE=out_${stub}.hipo org.junit.runner.JUnitCore eb.EBTwoTrackTest
156156
if [ $? != 0 ] ; then echo "EBTwoTrackTest unit test failure" ; exit 1 ; else echo "EBTwoTrackTest passed unit tests" ; fi
157157

158+
$COAT/bin/trutheff ./out_${stub}.hipo
159+
158160
exit 0
159161

validation/advanced-tests/src/eb/scripts/gemc-all.sh

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)