Filter primary particles

Hi everyone,
trying to display only secondary particles almost works quite nicely with

/vis/filtering/trajectories/create/attributeFilter secondaries
/vis/filtering/trajectories/secondaries/setAttribute PID
/vis/filtering/trajectories/secondaries/addValue 0
/vis/filtering/trajectories/secondaries/invert true

however, this also filters out gamma particles that are only redirected. As I understand, the trajectory of the particle with PID 0 is continued even after scattering events where the gamma would not be fully absorbed.

Is there a way to display all particles starting from the point of first physical interaction, in a sense of all daughter particles plus the remaining track (trajectory?) of the incident primary particle?
Thanks a lot in advance!

Mmmm. All trajectories NOT with Parent ID PID == 0.

Not sure what you mean, “gamma particles that are only redirected”. OK, I see what you mean - for example, from a Compton scatter.

Mmmm. The G4Trajectory only looks at the track information. And so the modelling/filtering applies to the whole track. What you are, in effect, asking is drawing just part of a track.

Maybe you could use the time window:

/vis/scene/add/trajectories rich
/vis/modeling/trajectories/drawByCharge-0/default/setTimeSliceInterval 0.01 ns

then

/vis/viewer/set/timeWindow/startTime 0.01 ns

I would be interested to know if this works.

great idea, thanks!
I tried your suggestion and report: it partially works. I can estimate the time the photons require to travel to the first surface, and indeed with the right startTime, only the remaining part of the tracks is drawn.

However, being a single global value for all tracks, this does not account for different penetration depths. So unfortunately, this is not a compromise that I can work with, as most events are anyway very local to the first scatter event in the material… Either they get filtered out as well, or are cluttered with the “stubs” of the primary particle tracks.

Either that, or replace the primary particle with a secondary in compton and reyleigh scattering events

OK. Yes. That’s right. No single start time for all events.

Mmmm.

One last idea. In principle (be warned, I have never tried this), you can add your own attributes to a trajectory. This means implementing you own trajectory class, G4MyTrajectory and G4MyTrajectoryPoint, ultimately inherited from G4VTrajectory and G4VTrajectoryPoint but probably best to inherit from G4RichTrajectory/Point. Then set a flag when the track has interacted and select on it. (Would this work?)

Maybe there could be an AddAttDef and AddAttValue function to an existing G4VTrajectory.

A very interesting project, which could lead to a new type of trajectory, but it’s a big job.

class G4VTrajectory
  ...
    virtual const std::map<G4String,G4AttDef>* GetAttDefs() const
      { return nullptr; }
      // If implemented by a derived class, returns a pointer to a map of
      // attribute definitions for the attribute values below. The user
      // must test the validity of this pointer. See G4Trajectory for an
      // example of a concrete implementation of this method
    virtual std::vector<G4AttValue>* CreateAttValues() const
      { return nullptr; }
      // If implemented by a derived class, returns a pointer to a list
      // of attribute values suitable, e.g., for picking. Each must
       // refer to an attribute definition in the above map; its name is
      // the key. The user must test the validity of this pointer (it
      // must be non-zero and conform to the G4AttDefs, which may be
      // checked with G4AttCheck) and delete the list after use. See
      // G4Trajectory for an example of a concrete implementation of this
      // method and G4VTrajectory::ShowTrajectory for an example of its use.

Interesting idea, but I‘m afraid that is beyond my skill level. Thanks for your suggestions, though!
Wondering if this would actually work… as I understand, the trajectory is the whole „path“ the gamma takes, from primary event until it completely vanishes. The scattering events are points where additional trajectories are created. So I would assume I still have to split the gamma trajectory at some point in the code?

I have just realised a rich trajectory offers a whole slew of attributes. Would these do?

Process Defined Step (PDS): G4String
Process Type Defined Step (PTDS): G4String

Trying to think how to dump values. Try
/vis/viewer/set/picking
and pick a relevant trajectory.

Printed at startup:

G4TrajectoriesModel:
Event ID (EventID): G4int
Run ID (RunID): G4int
G4RichTrajectory:
Creator Model ID (CMID): G4int
Creator Model Name (CMN): G4String
Creator Process Name (CPN): G4String
Creator Process Type Name (CPTN): G4String
Charge (Ch): unit: e+ (G4double)
Ending Process Name (EPN): G4String
Ending Process Type Name (EPTN): G4String
Final kinetic energy (FKE): G4BestUnit (G4double)
Final Next Volume Path (FNVPath): G4String
Final Volume Path (FVPath): G4String
Track ID (ID): G4int
Initial kinetic energy (IKE): G4BestUnit (G4double)
Initial momentum magnitude (IMag): G4BestUnit (G4double)
Initial momentum (IMom): G4BestUnit (G4ThreeVector)
Initial Next Volume Path (INVPath): G4String
Initial Volume Path (IVPath): G4String
No. of points (NTP): G4int
PDG Encoding (PDG): G4int
Parent ID (PID): G4int
Particle Name (PN): G4String
G4RichTrajectoryPoint:
Auxiliary Point Position (Aux): G4BestUnit (G4ThreeVector)
Process Defined Step (PDS): G4String
Process Type Defined Step (PTDS): G4String
Position (Pos): G4BestUnit (G4ThreeVector)
Post-step-point status (PostStatus): G4String
Post-step-point global time (PostT): G4BestUnit (G4double)
Post-step Volume Path (PostVPath): G4String
Post-step-point weight (PostW): G4double
Pre-step-point status (PreStatus): G4String
Pre-step-point global time (PreT): G4BestUnit (G4double)
Pre-step Volume Path (PreVPath): G4String
Pre-step-point weight (PreW): G4double
Remaining Energy (RE): G4BestUnit (G4double)
Total Energy Deposit (TED): G4BestUnit (G4double)

in principle yes, but the original challenge remains: after scattering it is still the same track/trajectory.
So filtering trajectories does either remove the photon for good, or not at all.

I see now that the track has a list of G4RichTrajectoryPoints. Filtering for Pre-step-point global time (PreT) > 0 could allow to remove all initial line segments. However, /vis/filtering does not allow me to use the attributes for the G4RichTrajectoryPoint, only those for G4RichTrajectory…

Ah! OK. So sorry, nothing available on the command line.

Another idea, which only works in sequential mode (export G4RUN_MANAGER_TYPE=Serial). Draw your own trajectories. In end of event action:

  auto TC = event -> GetTrajectoryContainer ();
  if (!TC) return;
  auto pVVisManager = G4VVisManager::GetConcreteInstance();
  if (!pVVisManager) return;
  pVVisManager->BeginDraw();
  for (size_t iT = 0; iT < TC->entries(); ++iT) {
    auto traj = (*TC) [iT];
    G4Polyline trajectoryLine;
    for (G4int iPoint=0; iPoint<traj->GetPointEntries(); iPoint++) {
      auto aTrajectoryPoint = traj->GetPoint(iPoint);
      trajectoryLine.push_back(aTrajectoryPoint->GetPosition());
      pVVisManager->Draw(trajectoryLine);
    }
  }
  pVVisManager->EndDraw();

So instead of G4int iPoint=0 you could start at G4int iPoint=1, say.

Of course, they all come out white, so you have to add some vis attributes.

are there specific reasons to maintain the incident photon in compton / rayleigh interactions? could it be replaced by a secondary? maybe that is a much more trivial change to the code than custom display routines…

related post:

Mmmm. Maybe. But not my area of expertise. :thinking:

Dear experts,
the topic came up again in a different variant:
I would like to count photons with a sensitive detector, and distinguish between non-interacting photons directly from the primary vertex and photons that were redirected via Rayleigh or Compton events.
Unfortunately, here the same holds as for the filtering of primary particles prevents me from success.

I would expect that
const G4String process = aStep->GetTrack()->GetCreatorProcess()->GetProcessName()
should yield “compt” or “Rayl” but that does not work…

Additionally, I only want to count photons that hit a certain surface, so counting Rayleigh/Compton events within a volume does not work, I need them to propagate to the detecting surface first…

Any ideas? Thanks a lot in advance!