0
$\begingroup$

Consider a file. Apart from an information which is non-relevant for me, it contains blocks <event></event> with the numerical data inside. Is there a simple way to remove all the text except the data inside the <event></event> tags, i.e. to get a simple file with the numerical data only?

For example, the part of the file at which blocks begin looks like

</init>
<event>
 3      1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01
        2 -1    0    0  501    0 +0.0000000000e+00 +0.0000000000e+00 +1.5693915630e+02 1.5693915630e+02 0.0000000000e+00 0.0000e+00 -1.0000e+00
       -1 -1    0    0    0  501 -0.0000000000e+00 -0.0000000000e+00 -1.0302107050e+01 1.0302107050e+01 0.0000000000e+00 0.0000e+00 1.0000e+00
       24  1    1    2    0    0 +0.0000000000e+00 +0.0000000000e+00 +1.4663704925e+02 1.6724126335e+02 8.0419002446e+01 0.0000e+00 -1.0000e+00
<mgrwt>
<rscale>  0 0.80419002E+02</rscale>
<asrwt>0</asrwt>
<pdfrwt beam="1">  1        2 0.24144484E-01 0.80419002E+02</pdfrwt>
<pdfrwt beam="2">  1       -1 0.15849397E-02 0.80419002E+02</pdfrwt>
<totfact> 0.20046334E+05</totfact>
</mgrwt>
</event>
<event>
 3      1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01
       -3 -1    0    0    0  501 -0.0000000000e+00 +0.0000000000e+00 +2.5673118905e+01 2.5673118905e+01 0.0000000000e+00 0.0000e+00 1.0000e+00
        4 -1    0    0  501    0 +0.0000000000e+00 -0.0000000000e+00 -6.2976531778e+01 6.2976531778e+01 0.0000000000e+00 0.0000e+00 -1.0000e+00
       24  1    1    2    0    0 +0.0000000000e+00 -0.0000000000e+00 -3.7303412873e+01 8.8649650684e+01 8.0419002446e+01 0.0000e+00 1.0000e+00
<mgrwt>
<rscale>  0 0.80419002E+02</rscale>
<asrwt>0</asrwt>
<pdfrwt beam="1">  1        4 0.96886972E-02 0.80419002E+02</pdfrwt>
<pdfrwt beam="2">  1       -3 0.39497106E-02 0.80419002E+02</pdfrwt>
<totfact> 0.43040333E+04</totfact>
</mgrwt>
</event>
<event>

I would like to obtain just

 3      1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01
        2 -1    0    0  501    0 +0.0000000000e+00 +0.0000000000e+00 +1.5693915630e+02 1.5693915630e+02 0.0000000000e+00 0.0000e+00 -1.0000e+00
       -1 -1    0    0    0  501 -0.0000000000e+00 -0.0000000000e+00 -1.0302107050e+01 1.0302107050e+01 0.0000000000e+00 0.0000e+00 1.0000e+00
       24  1    1    2    0    0 +0.0000000000e+00 +0.0000000000e+00 +1.4663704925e+02 1.6724126335e+02 8.0419002446e+01 0.0000e+00 -1.0000e+00
 3      1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01
       -3 -1    0    0    0  501 -0.0000000000e+00 +0.0000000000e+00 +2.5673118905e+01 2.5673118905e+01 0.0000000000e+00 0.0000e+00 1.0000e+00
        4 -1    0    0  501    0 +0.0000000000e+00 -0.0000000000e+00 -6.2976531778e+01 6.2976531778e+01 0.0000000000e+00 0.0000e+00 -1.0000e+00
       24  1    1    2    0    0 +0.0000000000e+00 -0.0000000000e+00 -3.7303412873e+01 8.8649650684e+01 8.0419002446e+01 0.0000e+00 1.0000e+00
$\endgroup$
  • $\begingroup$ Can you provide an example of what an ideal output would look like. I downloaded the file and it is not entirely clear what you are looking for. $\endgroup$ – kickert Jul 2 at 22:26
  • $\begingroup$ @kickert : I apologize for such an unclear question, and just have added the relevant information. $\endgroup$ – John Taylor Jul 2 at 22:29
  • $\begingroup$ So everything would be between <event> and<mgrwt>? $\endgroup$ – kickert Jul 2 at 22:45
  • $\begingroup$ @kickert : to be precise, yes. $\endgroup$ – John Taylor Jul 2 at 22:46
2
$\begingroup$

First import your data as a long string:

data = Import["D:\\documents\\Downloads\\W-boson-13-TeV.lhe", "String"]

Then use StringCases to extract what is between the tags <event> and <mgrwt>.

datablocks = StringCases[data2, "<event>" ~~ Shortest[x__] ~~ "<mgrwt>" -> x]

If you want to turn this String data into numerical data, you can use the following:

numbers = 
 DeleteCases[
    ToExpression[
     StringSplit[StringSplit[StringReplace[#, "e" -> "E"], "\n"], 
      " "]], Null, {2}] & /@ datablocks
$\endgroup$
  • $\begingroup$ Thank you! Is there any simple way to convert the obtained set into the ordinary numerical table immediately after applying the second command? The only way I have in mind is to first export it and then to import it as a table and remove empty elements. $\endgroup$ – John Taylor Jul 2 at 23:02
  • $\begingroup$ @JohnTaylor Is this what you are looking for? datablocks = StringCases[data2, "<event>" ~~ Shortest[x__] ~~ "<mgrwt>" -> x] Then run splits = DeleteCases[StringSplit[StringSplit[#, "\n"], " "], "", {2}]&/@datablocks $\endgroup$ – kickert Jul 2 at 23:08
  • $\begingroup$ No, I just want to work with the imported file as with the numerical data, just something like ToExpression[] but working in a correct manner. $\endgroup$ – John Taylor Jul 2 at 23:11
  • $\begingroup$ @JohnTaylor What about this: splits2 = DeleteCases[ ToExpression[ StringSplit[StringSplit[StringReplace[#, "e" -> "E"], "\n"], " "]], Null, {2}] & /@ datablocks $\endgroup$ – kickert Jul 2 at 23:47
  • $\begingroup$ This can be done cleaner using XML import. $\endgroup$ – b3m2a1 Jul 3 at 8:05
3
$\begingroup$

You have XML here. Why not use that fact?

xmlData = ImportString["<container>
 <event>
  3      1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01
         2 -1    0    0  501    0 +0.0000000000e+00 +0.0000000000e+00 \
+1.5693915630e+02 1.5693915630e+02 0.0000000000e+00 0.0000e+00 -1.0000e+00
        -1 -1    0    0    0  501 -0.0000000000e+00 -0.0000000000e+00 \
-1.0302107050e+01 1.0302107050e+01 0.0000000000e+00 0.0000e+00 1.0000e+00
        24  1    1    2    0    0 +0.0000000000e+00 +0.0000000000e+00 \
+1.4663704925e+02 1.6724126335e+02 8.0419002446e+01 0.0000e+00 -1.0000e+00
 <mgrwt>
 <rscale>  0 0.80419002E+02</rscale>
 <asrwt>0</asrwt>
 <pdfrwt beam=\"1\">  1        2 0.24144484E-01 0.80419002E+02</pdfrwt>
 <pdfrwt beam=\"2\">  1       -1 0.15849397E-02 0.80419002E+02</pdfrwt>
 <totfact> 0.20046334E+05</totfact>
 </mgrwt>
 </event>
 <event>
  3      1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01
        -3 -1    0    0    0  501 -0.0000000000e+00 +0.0000000000e+00 \
+2.5673118905e+01 2.5673118905e+01 0.0000000000e+00 0.0000e+00 1.0000e+00
         4 -1    0    0  501    0 +0.0000000000e+00 -0.0000000000e+00 \
-6.2976531778e+01 6.2976531778e+01 0.0000000000e+00 0.0000e+00 -1.0000e+00
        24  1    1    2    0    0 +0.0000000000e+00 -0.0000000000e+00 \
-3.7303412873e+01 8.8649650684e+01 8.0419002446e+01 0.0000e+00 1.0000e+00
 <mgrwt>
 <rscale>  0 0.80419002E+02</rscale>
 <asrwt>0</asrwt>
 <pdfrwt beam=\"1\">  1        4 0.96886972E-02 0.80419002E+02</pdfrwt>
 <pdfrwt beam=\"2\">  1       -3 0.39497106E-02 0.80419002E+02</pdfrwt>
 <totfact> 0.43040333E+04</totfact>
 </mgrwt>
 </event>
 </container>",
 {"XML"}
 ];

Then you can use the nice XML structure to your advantage:

Cases[xmlData, XMLElement["event", _, {s_String, ___}] :> s, Infinity] // 
 StringRiffle[#, "\n"] &

"3 1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01 2 -1 0 0 501 \
0 +0.0000000000e+00 +0.0000000000e+00 +1.5693915630e+02 1.5693915630e+02 \
0.0000000000e+00 0.0000e+00 -1.0000e+00 -1 -1 0 0 0 501 -0.0000000000e+00 \
-0.0000000000e+00 -1.0302107050e+01 1.0302107050e+01 0.0000000000e+00 \
0.0000e+00 1.0000e+00 24 1 1 2 0 0 +0.0000000000e+00 +0.0000000000e+00 \
+1.4663704925e+02 1.6724126335e+02 8.0419002446e+01 0.0000e+00 -1.0000e+00
3 1 +8.3561000e+04 8.04190000e+01 7.54677100e-03 1.32786700e-01 -3 -1 0 0 0 \
501 -0.0000000000e+00 +0.0000000000e+00 +2.5673118905e+01 2.5673118905e+01 \
0.0000000000e+00 0.0000e+00 1.0000e+00 4 -1 0 0 501 0 +0.0000000000e+00 \
-0.0000000000e+00 -6.2976531778e+01 6.2976531778e+01 0.0000000000e+00 \
0.0000e+00 -1.0000e+00 24 1 1 2 0 0 +0.0000000000e+00 -0.0000000000e+00 \
-3.7303412873e+01 8.8649650684e+01 8.0419002446e+01 0.0000e+00 1.0000e+00"
$\endgroup$
2
$\begingroup$

If your input file is called "in.txt" the following expression, which writes a file called "out.txt" might suit you:

Export["out.txt", StringCases[Import["in.txt", "String"], Shortest["<event>\n" ~~ blk__ ~~ "\n<mgrwt>"] :> blk]]
$\endgroup$
  • $\begingroup$ beat me to it. Slight differences in the code, but basically the same approach. $\endgroup$ – kickert Jul 2 at 23:00
2
$\begingroup$

Using the excerpt from the file shown in the question.

f = Import["test.txt", "String"];
data = StringCases[f, 
   RegularExpression["(?s)<event>(.+?)<mgrwt>"] -> "$1"];
data2 = ToExpression[StringSplit[StringReplace[data, "e" -> "*10^"]]]

{{3,1,83561.,80.419,0.00754677,0.132787,2,-1,0,0,501,0,0.,0.,156.939,156.939,0.,0.,-1.,-1,-1,0,0,0,501,0.,0.,-10.3021,10.3021,0.,0.,1.,24,1,1,2,0,0,0.,0.,146.637,167.241,80.419,0.,-1.},{3,1,83561.,80.419,0.00754677,0.132787,-3,-1,0,0,0,501,0.,0.,25.6731,25.6731,0.,0.,1.,4,-1,0,0,501,0,0.,0.,-62.9765,62.9765,0.,0.,-1.,24,1,1,2,0,0,0.,0.,-37.3034,88.6497,80.419,0.,1.}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.