-
Notifications
You must be signed in to change notification settings - Fork 4
/
mixLHEfiles2.cpp
180 lines (149 loc) · 5.23 KB
/
mixLHEfiles2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// c++ -o mixLHEfiles2 mixLHEfiles2.cpp
#include "LHEF.h"
#include <iomanip>
#include <vector>
#include <iostream>
#include <cmath>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <fstream>
using namespace std ;
int getIndex (const vector<int> & pops, int totot)
{
float pos = rand () ;
pos /= RAND_MAX ;
pos *= totot ;
int index = 0 ;
int tot = 0 ;
for (int i = 0 ; i < pops.size () ; ++i)
{
tot += pops.at (i) ;
if (pos < tot)
{
index = i ;
break ;
}
}
return index ;
}
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
int main (int argc, char ** argv)
{
if(argc < 3)
{
cout << "Usage: " << argv[0]
<< " filesList.txt outputFile.lhe" << endl ;
return -1;
}
vector<string> fileToAddNames ;
vector<double> mixEventsXS ;
double totXS = 0. ;
//PG read the list of files and corresponding cross-sections
string line;
ifstream myfile (argv[1]);
if (myfile.is_open ())
{
while ( myfile.good ())
{
getline (myfile,line) ;
cout << line << endl ;
stringstream ss (line) ;
string name ;
ss >> name ;
fileToAddNames.push_back (name) ;
double xs ;
ss >> xs ;
mixEventsXS.push_back (xs) ;
totXS += xs ;
cout << "--> " << fileToAddNames.back () << " " << mixEventsXS.back () << "\n" ;
}
myfile.close () ;
}
else
{
cout << "Unable to open file\n" ;
exit (1) ;
}
vector<int> totEventsNum (fileToAddNames.size (), 0) ;
int grandTotal = 0 ;
//PG get the number of events per file
for (int iFile = 0 ; iFile < fileToAddNames.size () ; ++iFile)
{
cout << "opening " << fileToAddNames.at (iFile) << endl ;
ifstream ifs (fileToAddNames.at (iFile).c_str ());
// Create the Reader object:
LHEF::Reader reader (ifs) ;
//PG loop over events
while ( reader.readEvent() )
{
if ( reader.outsideBlock.length() ) cout << reader.outsideBlock;
++totEventsNum.at (iFile) ;
} //PG loop over events
grandTotal += totEventsNum.at (iFile) ;
cout << "found " << totEventsNum.at (iFile) << " in " << fileToAddNames.at (iFile) << endl ;
} //PG loop over input files
//PG find the conversion factor between XS and Nevents, based on the file with the largest XS
//PG (this should work when all files have the same stats, there's a check for having enough events though)
int maxXS_pos = max_element (mixEventsXS.begin (), mixEventsXS.end ()) - mixEventsXS.begin () ;
double conv_factor = totEventsNum.at (maxXS_pos) / mixEventsXS.at (maxXS_pos) ;
//PG determine how many events have to be picked up from each file
vector<int> mixEventsNum (fileToAddNames.size (), 0) ;
for (int iFile = 0 ; iFile < fileToAddNames.size () ; ++iFile)
{
mixEventsNum.at (iFile) = round (mixEventsXS.at (iFile) * conv_factor) ;
if (mixEventsNum.at (iFile) > totEventsNum.at (iFile))
{
cout << "not enough events in file: " << fileToAddNames.at (iFile) << endl ;
}
}
//PG re-open inputs for reading
vector<ifstream*> ifs ;
vector<LHEF::Reader*> readers ;
for (int iFile = 0 ; iFile < fileToAddNames.size () ; ++iFile)
{
cout << "opening " << fileToAddNames.at (iFile) << endl ;
ifstream * dummy = new ifstream (fileToAddNames.at (iFile).c_str ()) ;
ifs.push_back (dummy) ;
readers.push_back (new LHEF::Reader (*ifs.at (iFile))) ;
}
//PG output file
ofstream outputStream (argv[2]) ;
LHEF::Writer writer (outputStream) ;
writer.headerBlock () << readers.at (0)->headerBlock ;
writer.initComments () << readers.at (0)->initComments ;
writer.heprup = readers.at (0)->heprup ;
writer.init () ;
//PG fill the output
vector<int> copiedEventsNum (fileToAddNames.size (), 0) ;
int events = 0 ;
int cont = 0 ;
do {
//PG choose randomly from which input file to read the event
int iInput = getIndex (mixEventsNum, grandTotal) ;
if (copiedEventsNum.at (iInput) == mixEventsNum.at (iInput)) continue ;
//PG copy the event from the input to the output
readers.at (iInput)->readEvent () ;
if (readers.at (iInput)->outsideBlock.length ()) cout << readers.at (iInput)->outsideBlock ;
writer.eventComments () << readers.at (iInput)->eventComments ;
writer.hepeup = readers.at (iInput)->hepeup ;
writer.writeEvent () ;
++copiedEventsNum.at (iInput) ;
++events ;
if (events % 10000 == 0) cout << events << " read" << endl ;
//PG continue util all the reading files have been read
cont = 0 ;
for (int iFile = 0 ; iFile < fileToAddNames.size () ; ++iFile)
if (copiedEventsNum.at (iFile) < mixEventsNum.at (iFile)) cont += 1 ;
} while (cont != 0) ;
for (int iFile = 0 ; iFile < fileToAddNames.size () ; ++iFile)
{
cout << "closing " << fileToAddNames.at (iFile) << endl ;
delete readers.at (iFile) ;
ifs.at (iFile)->close () ;
}
cout << "output file : " << argv[2]
<< " containing " << events
<< " for a total XS of " << totXS << endl ;
return 0 ;
}