4
$\begingroup$

Consider the following table:

E 0 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 -1.0000000000000000e+00 0 0 13 1 2 0 2 1.0000000000000000e+00 5.8956999999999993e-01
P 17 22 -1.2485021051898233e-02 -5.1630826532250172e-02 6.1918258041651630e-05 5.3118940435030619e-02 0 1 0 0 0 0
P 18 22 4.9562715584439615e-02 5.0012892263022642e-02 8.6245790603881711e-02 1.1133772301203836e-01 0 1 0 0 0 0
P 19 22 -1.5552509953220044e-02 -2.3850666659370811e-02 6.5939681353609694e-03 2.9226961554557555e-02 0 1 0 0 0 0
P 20 22 2.7596054487740468e-01 -2.1762061713315523e-01 8.7662314134485303e-02 3.6221214315627603e-01 0 1 0 0 0 0
P 21 22 -5.1578463837396671e-02 1.3519803581552983e-02 -1.9108577184834183e-01 1.9838572333609578e-01 0 1 0 0 0 0
P 22 22 1.2113834175920507e-01 -3.2018418728691583e-01 2.7446441033903723e-01 4.3877457102196354e-01 0 1 0 0 0 0
E 1 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 -1.0000000000000000e+00 0 0 6 1 2 0 2 1.0000000000000000e+00 5.8956999999999993e-01
P 7 130 -1.8129648644252511e-02 5.2696520170431738e-01 7.5951516109473693e-01 1.0500000000000000e+00 4.9761000000000000e-01 1 0 0 0 0
P 8 211 1.6865230841167808e-01 -4.0708930815825645e-01 -6.2344440715555249e-01 7.7609794463256632e-01 1.3957000000000000e-01 1 0 0 0 0
P 9 -211 -1.5052265976742557e-01 -1.1987589354606093e-01 -1.3607075393918455e-01 2.7390205536743384e-01 1.3957000000000000e-01 1 0 0 0 0
E 2 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 -1.0000000000000000e+00 0 0 5 1 2 0 2 1.0000000000000000e+00 5.8956999999999993e-01
P 7 211 5.0607845359036219e-01 3.6848311348479607e-01 8.3133928632546694e-01 1.0499999999999987e+00 1.3957000000000000e-01 1 0 0 0 0
P 8 -211 -5.0607845359036241e-01 -3.6848311348479629e-01 -8.3133928632546772e-01 1.0500000000000000e+00 1.3957000000000000e-01 1 0 0 0 0
E 3 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 -1.0000000000000000e+00 0 0 12 1 2 0 2 1.0000000000000000e+00 5.8956999999999993e-01
P 11 211 -1.2670630161528043e-01 -5.5755103314066323e-01 -2.0333395392349726e-02 5.8890650641118336e-01 1.3957000000000000e-01 1 0 0 0 0
P 13 -211 -1.8625168359526698e-01 2.5964633799700204e-01 -1.4171605493559536e-01 3.7638960613151057e-01 1.3957000000000000e-01 1 0 0 0 0
P 15 211 1.4689307696016242e-02 2.6397035763873505e-01 1.7916303460509408e-01 3.4853307352590812e-01 1.3957000000000000e-01 1 0 0 0 0
P 16 -211 1.1984605870831583e-01 6.2191999311472013e-02 5.2260939697877366e-02 2.0110174858608362e-01 1.3957000000000000e-01 1 0 0 0 0

It has the structure

E ...
P ...
P ...
...
E ...
P ...
...

Let us call the corresponding table "table.txt":

data = Import["table.txt","Table"];

I would like to make a command extract[data,i] that extracts the rows with P ... after the given E ... defined by the index i (given by its order, say, the first E ... is 1, and so on) and before the subsequent E ... having the index i+1. Could you please tell me how to do it?

$\endgroup$
2
  • 1
    $\begingroup$ You could start by using Position on the first column to find where all the E’s are. $\endgroup$
    – Ghoster
    Aug 21, 2023 at 21:25
  • $\begingroup$ You may be able to use SplitByPatterns in the Wolfram function repository. $\endgroup$
    – LouisB
    Aug 22, 2023 at 2:08

4 Answers 4

4
$\begingroup$

Using your imported data, first we find the rows with "E" in the first column, and from that list, we make a list of ranges.

ranges = Partition[Flatten[Position[data[[All, 1]], "E"]], 2, 1, 1] - Threaded[{0, 1}];
ranges[[-1, 2]] = Length[data]; (*set the end of the last range*)
ranges
(*{{1, 7}, {8, 11}, {12, 14}, {15, 19}}*)

The command extract[data, i] is the same as selecting a range. For example, to extract the first set of rows from data use:

data[[#1 ;; #2]] &@@ ranges[[1]]
{{E,0,-1,-1.,-1.,-1.,0,0,13,1,2,0,2,1.,0.58957},
 {P,17,22,-0.012485,-0.0516308,0.0000619183,0.0531189,0,1,0,0,0,0},
 {P,18,22,0.0495627,0.0500129,0.0862459,0.111338,0,1,0,0,0,0},
 {P,19,22,-0.0155525,-0.0238507,0.00659397,0.029227,0,1,0,0,0,0},
 {P,20,22,0.275961,-0.217621,0.0876623,0.362212,0,1,0,0,0,0},
 {P,21,22,-0.0515785,0.0135198,-0.191086,0.198386,0,1,0,0,0,0},
 {P,22,22,0.121138,-0.320184,0.274464,0.438775,0,1,0,0,0,0}}

Then the second set of rows is data[[#1 ;; #2]] &@@ ranges[[2]], etc.

$\endgroup$
1
  • $\begingroup$ Thanks! It's super-fast. $\endgroup$ Aug 22, 2023 at 18:26
4
$\begingroup$

Working with the file from your previous post:

file = Import["C:/tag_1_pythia8_events.hepmc", "Table"];
(filtered = 
    SequenceCases[file, {{"E", ___}} | {{"P", ___, 1, 0 ..}}]) // 
  Grid[#, Alignment -> Left] &;

EsnPs = TakeList[filtered, 
   Length /@ Split[filtered[[All, 1, 1]], #2 == "P" &]];

Example: To get the third row, for index i==1,

EsnPs[[1, 3 + 1]]
$\endgroup$
4
$\begingroup$

Straightforward approach:

d = Import["test.txt", "Table"];

extract[ps_] := Module[{pos = ps, dp, ddp, p},
                     (*List all E-lines*)                      
                  dp = Select[d, #[[1]] == "E" &];  
                     (*Define the position of desired line in global list*)         
                  p = Position[d, dp[[pos]]][[1, 1]];
                     (*Taking the first P-line going after desired E-line*)
                  ddp = Select[d[[p ;; -1]], #[[1]] == "P" &, 1]
                ]

Finally it gives:

 extract[2]

{"P", 7, 130, -0.0181296, 0.526965, 0.759515, 1.05, 0.49761, 1, 0, 0, 0, 0}

and so on..

If you wish all P-lines going after desired E-line up to the next E-line, than you need:

extract[ps_] := Module[{pos = ps, dp, ddp, p1, p2},
                 dp = Select[d, #[[1]] == "E" &];
                 p1 = Position[d, dp[[pos]]][[1, 1]];
                 p2 = Position[d, dp[[pos + 1]]][[1, 1]];
                 ddp = Select[d[[p1 ;; p2]], #[[1]] == "P" &]
                ]

that gives:

 extract[2]

{{"P", 7, 130, -0.0181296, 0.526965, 0.759515, 1.05, 0.49761, 1, 0, 0, 0, 0}, {"P", 8, 211, 0.168652, -0.407089, -0.623444, 0.776098, 0.13957, 1, 0, 0, 0, 0}, {"P", 9, -211, -0.150523, -0.119876, -0.136071, 0.273902, 0.13957, 1, 0, 0, 0, 0}}

$\endgroup$
4
$\begingroup$

Assuming the format will be the same as the example posted:

data = "E0-1-1.0000000000000000e+00-1.0000000000000000e+00-1.\
0000000000000000e+00 0 0 13 1 2 0 2 1.0000000000000000e+00 \
5.8956999999999993e-01
P 17 22-1.2485021051898233e-02-5.1630826532250172e-02 \
6.1918258041651630e-05 5.3118940435030619e-02 0 1 0 0 0 0
P 18 22 4.9562715584439615e-02 5.0012892263022642e-02 \
8.6245790603881711e-02 1.1133772301203836e-01 0 1 0 0 0 0
P 19 22-1.5552509953220044e-02-2.3850666659370811e-02 \
6.5939681353609694e-03 2.9226961554557555e-02 0 1 0 0 0 0
P 20 22 2.7596054487740468e-01-2.1762061713315523e-01 \
8.7662314134485303e-02 3.6221214315627603e-01 0 1 0 0 0 0
P 21 22-5.1578463837396671e-02 \
1.3519803581552983e-02-1.9108577184834183e-01 1.9838572333609578e-01 \
0 1 0 0 0 0
P 22 22 1.2113834175920507e-01-3.2018418728691583e-01 \
2.7446441033903723e-01 4.3877457102196354e-01 0 1 0 0 0 0
E 1-1-1.0000000000000000e+00-1.0000000000000000e+00-1.\
0000000000000000e+00 0 0 6 1 2 0 2 1.0000000000000000e+00 \
5.8956999999999993e-01
P 7 130-1.8129648644252511e-02 5.2696520170431738e-01 \
7.5951516109473693e-01 1.0500000000000000e+00 4.9761000000000000e-01 \
1 0 0 0 0
P 8 211 1.6865230841167808e-01-4.0708930815825645e-01-6.\
2344440715555249e-01 7.7609794463256632e-01 1.3957000000000000e-01 1 \
0 0 0 0
P 9-211-1.5052265976742557e-01-1.1987589354606093e-01-1.\
3607075393918455e-01 2.7390205536743384e-01 1.3957000000000000e-01 1 \
0 0 0 0
E 2-1-1.0000000000000000e+00-1.0000000000000000e+00-1.\
0000000000000000e+00 0 0 5 1 2 0 2 1.0000000000000000e+00 \
5.8956999999999993e-01
P 7 211 5.0607845359036219e-01 3.6848311348479607e-01 \
8.3133928632546694e-01 1.0499999999999987e+00 1.3957000000000000e-01 \
1 0 0 0 0
P 8-211-5.0607845359036241e-01-3.6848311348479629e-01-8.\
3133928632546772e-01 1.0500000000000000e+00 1.3957000000000000e-01 1 \
0 0 0 0
E 3-1-1.0000000000000000e+00-1.0000000000000000e+00-1.\
0000000000000000e+00 0 0 12 1 2 0 2 1.0000000000000000e+00 \
5.8956999999999993e-01
P 11 211-1.2670630161528043e-01-5.5755103314066323e-01-2.\
0333395392349726e-02 5.8890650641118336e-01 1.3957000000000000e-01 1 \
0 0 0 0
P 13-211-1.8625168359526698e-01 \
2.5964633799700204e-01-1.4171605493559536e-01 3.7638960613151057e-01 \
1.3957000000000000e-01 1 0 0 0 0
P 15 211 1.4689307696016242e-02 2.6397035763873505e-01 \
1.7916303460509408e-01 3.4853307352590812e-01 1.3957000000000000e-01 \
1 0 0 0 0
P 16-211 1.1984605870831583e-01 6.2191999311472013e-02 \
5.2260939697877366e-02 2.0110174858608362e-01 1.3957000000000000e-01 \
1 0 0 0 0";

split the data each time there's a newline command. Get the first character in each line, and determine where the "E"s are

splitData = StringSplit[data, "\n"];
letters = StringPart[splitData, 1]
ePos = Flatten[Position[letters, "E"]]

(*{"E", "P", "P", "P", "P", "P", "P", "E", "P", "P", "P", "E", "P", \
"P", "E", "P", "P", "P", "P"}*)
(*{1, 8, 12, 15}*)

Then make the upper and lower index bounds for the "P" lines between "E" lines (there is probably a lot simpler way to do this):

eBounds = MapThread[{#1+1, #2 - 1} &, {ePos, ePos // RotateLeft}];
eBounds[[-1]] = {Last@ePos+1, Length@letters};
eBounds
(*{{2, 7}, {9, 11}, {13, 14}, {16, 19}}*)

And grab those parts from data:

groupedData = 
  Map[Part[splitData, #] &, Range[First[#], Last[#]]] & /@ eBounds;

To make it a function, we just first create our grouped data with another function first (using the same code as above):

createGroupedData[dataIn_] := Module[{data = dataIn},
  splitData = StringSplit[data, "\n"];
  letters = StringPart[splitData, 1];
  ePos = Flatten[Position[letters, "E"]];
  eBounds = 
   MapThread[{#1 + 1, #2 - 1} &, {ePos, ePos // RotateLeft}];
  eBounds[[-1]] = {Last@ePos + 1, Length@letters};
  
  Map[Part[splitData, #] &, Range[First[#], Last[#]]] & /@ eBounds
  
  ]

And then you can just get the ith part of the output from createGroupData:

groupedPs = createGroupedData[data];
groupedPs[[2]]

(*{"P 7 130-1.8129648644252511e-02 5.2696520170431738e-01 \
7.5951516109473693e-01 1.0500000000000000e+00 4.9761000000000000e-01 \
1 0 0 0 0", "P 8 211 \
1.6865230841167808e-01-4.0708930815825645e-01-6.2344440715555249e-01 \
7.7609794463256632e-01 1.3957000000000000e-01 1 0 0 0 0", "P \
9-211-1.5052265976742557e-01-1.1987589354606093e-01-1.\
3607075393918455e-01 2.7390205536743384e-01 1.3957000000000000e-01 1 \
0 0 0 0"}*)
$\endgroup$
2
  • $\begingroup$ I suggest that eBounds[[-1]] = {Last@ePos, Length@letters} should be eBounds[[-1]] = {Last@ePos+1, Length@letters} so that eBounds[[-1]] starts at the first 'P' (Last@ePos + 1) row after the last 'E' row (Last@ePos). $\endgroup$
    – creidhne
    Aug 22, 2023 at 15:35
  • $\begingroup$ Thanks for pointing this out I have fixed it $\endgroup$
    – ydd
    Aug 22, 2023 at 15:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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