diff --git a/benchmarks/rich/run_benchmark.rb b/benchmarks/rich/run_benchmark.rb
index e8edcfa25a908b5c226997a9df615e303618bf67..64d32b66c5c54c33dffaf350f87e775bf1acd5cd 100755
--- a/benchmarks/rich/run_benchmark.rb
+++ b/benchmarks/rich/run_benchmark.rb
@@ -18,13 +18,14 @@ IdealParticle = 'pi+'
 # default opt
 opt = OpenStruct.new
 opt.evgen         = ''
-opt.ana_only      = false
-opt.sim_file      = 'sim.edm4hep.root'
-opt.rec_file      = 'rec.edm4hep.root'
-opt.ana_file      = 'ana.edm4hep.root'
+opt.sim_file      = 'out/sim.edm4hep.root'
+opt.rec_file      = 'out/rec.edm4hep.root'
+opt.ana_file      = 'out/ana.edm4hep.root'
 opt.run_sim       = true
 opt.run_rec       = true
 opt.run_ana       = true
+opt.run_rec_down  = false
+opt.run_ana_down  = false
 opt.num_events    = 10
 opt.benchmark_exe = 'benchmark_rich_reconstruction'
 opt.algos         = Array.new
@@ -40,19 +41,30 @@ avail_evgens = [
 ]
 
 # parse options
+required_set = false
 OptionParser.new do |o|
   o.banner = "USAGE: #{$0} [OPTIONS]..."
   o.separator ''
   o.separator 'required options, one of either:'.upcase
   o.separator ''
-  o.on("-b", "--benchmark-only", "Run only the analysis benchmark") { |a| opt.ana_only=true }
+  o.on("-r", "--rec-only", "Run only the reconstruction, then the analysis benchmark") do |a|
+    opt.run_rec_down = true
+    required_set = true
+  end
+  o.separator ''
+  o.on("-b", "--ana-only", "Run only the analysis benchmark") do |a|
+    opt.run_ana_down = true
+    required_set = true
+  end
   o.separator ''
-  o.on("-e", "--evgen [EVGEN_MODE]", "Event generation mode, one of:") do |a|
+  o.on("-e", "--evgen [EVGEN_MODE]", "Run the event generation, reconstruction, and analysis",
+       "[EVGEN_MODE] must be one of:") do |a|
     unless avail_evgens.include? a
       $stderr.puts "ERROR: unknown event generation mode '#{a}'"
       exit 1
     end
     opt.evgen = a
+    required_set = true
   end
   avail_evgens.each{ |it| o.separator ' '*40+it }
   o.separator ''
@@ -91,12 +103,26 @@ opt.each_pair { |k,v| puts "#{k.to_s.rjust(20)} => #{v}" }
 puts '}'
 
 # check for required options
-if opt.evgen=='' and opt.ana_only==false
+unless required_set
   $stderr.puts "ERROR: required options have not been set"
   $stderr.puts "run '#{$0} --help' for guidance"
   exit 1
 end
 
+# figure out which steps to run
+run_step = { :sim=>false, :rec=>false, :ana=>false, }
+if opt.run_ana_down
+  run_step[:ana] = true
+elsif opt.run_rec_down
+  run_step[:rec] = true
+  run_step[:ana] = true
+else
+  run_step[:sim] = opt.run_sim
+  run_step[:rec] = opt.run_rec
+  run_step[:ana] = opt.run_ana
+end
+puts "steps to run: #{run_step}"
+
 # get compact file
 if ENV['DETECTOR_PATH'].nil? or ENV['DETECTOR_CONFIG'].nil?
   $stderr.puts "ERROR: unknown DETECTOR_PATH or DETECTOR_CONFIG"
@@ -105,7 +131,7 @@ end
 compact_file = "#{ENV['DETECTOR_PATH']}/#{ENV['DETECTOR_CONFIG']}.xml"
 
 
-# helper functions
+# event generator command generators
 # ---------------------------------------------------
 def theta2xyz(theta)
   rad = theta * Math::PI / 180
@@ -136,7 +162,7 @@ case opt.evgen
 when 'idealAngle'
   evgen_cmd = evgen_fixed_angle.call IdealTheta, IdealEnergy, IdealParticle
 else
-  exit 1 unless opt.ana_only
+  exit 1 if run_step[:sim]
 end
 
 
@@ -177,28 +203,28 @@ analysis_cmd.append '-' + 'v'*opt.verbosity if opt.verbosity > 0
 # execute commands
 # ---------------------------------------------------
 
-exe = Proc.new do |cmd_args, name|
-  cmd = cmd_args.join ' '
-  puts "#{name} command:".upcase
-  cmd_args.each_with_index do |arg,i|
-    line = i==0 ? '' : '  '
-    line += arg
-    line += ' \\' unless i+1==cmd_args.size
-    puts line
-  end
-  unless opt.dry_run
+# proc: execute a command; raise runtime exception if failure (exit nonzero)
+exe = Proc.new do |cmd_args, name, step|
+  if run_step[step]
+    cmd = cmd_args.join ' '
+    puts "benchmark #{name} command:".upcase
+    cmd_args.each_with_index do |arg,i|
+      line = i==0 ? '' : '  '
+      line += arg
+      line += ' \\' unless i+1==cmd_args.size
+      puts line
+    end
+    unless opt.dry_run
+      puts '-'*50
+      puts "#{name} execution:".upcase
+      system cmd or raise "benchmark #{name} failed!".upcase
+    end
     puts '-'*50
-    puts "#{name} execution:".upcase
-    system cmd or raise "#{name} failed!"
   end
-  puts '-'*50
 end
-
 puts '-'*50
-unless opt.ana_only
-  exe.call evgen_cmd, 'event generator' if opt.run_sim
-  exe.call recon_cmd, 'reconstruction'  if opt.run_rec
-end
-if opt.ana_only or opt.run_ana
-  exe.call analysis_cmd, 'benchmark analysis'
-end
+
+# execute the commands
+exe.call evgen_cmd,    'event generation', :sim
+exe.call recon_cmd,    'reconstruction',   :rec
+exe.call analysis_cmd, 'analysis',         :ana