Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Optuna_tuning.py
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Optuna_tuning.py
1 #!/usr/bin/env python3
2 import sys
3 
4 import sys
5 import os
6 import yaml
7 import pprint
8 import time
9 import datetime
10 import warnings
11 
12 import optuna
13 import logging
14 import uproot
15 
16 import pathlib
17 import matplotlib
18 
19 matplotlib.use("pdf")
20 import matplotlib.pyplot as plt
21 import random
22 import subprocess
23 import multiprocessing
24 import numpy as np
25 import json
26 import array
27 import sys
28 import argparse
29 import pandas as pd
30 
31 from typing import Optional, Union
32 from pathlib import Path
33 
34 from optuna.visualization import plot_contour
35 from optuna.visualization import plot_edf
36 from optuna.visualization import plot_intermediate_values
37 from optuna.visualization import plot_optimization_history
38 from optuna.visualization import plot_parallel_coordinate
39 from optuna.visualization import plot_param_importances
40 from optuna.visualization import plot_slice
41 
42 srcDir = Path(__file__).resolve().parent
43 
44 
45 def run_ckf(params, names, outDir):
46 
47  if len(params) != len(names):
48  raise Exception("Length of Params must equal names")
49 
50  ckf_script = srcDir / "ckf.py"
51  nevts = "--nEvents=1"
52  indir = "--indir=" + str(srcDir)
53  outdir = "--output=" + str(outDir)
54 
55  ret = ["python"]
56  ret.append(ckf_script)
57  ret.append(nevts)
58  ret.append(indir)
59  ret.append(outdir)
60 
61  i = 0
62  for param in params:
63  arg = "--sf_" + names[i] + "=" + str(param)
64  ret.append(arg)
65  i += 1
66 
67  # Run CKF for the given parameters
68  subprocess.call(ret)
69 
70 
71 class Objective:
72  def __init__(self, k_dup, k_time):
73  self.res = {
74  "eff": [],
75  "fakerate": [],
76  "duplicaterate": [],
77  "runtime": [],
78  }
79 
80  self.k_dup = k_dup
81  self.k_time = k_time
82 
83  def __call__(self, trial):
84  params = []
85 
86  maxSeedsPerSpM = trial.suggest_int("maxSeedsPerSpM", 0, 10)
87  params.append(maxSeedsPerSpM)
88  cotThetaMax = trial.suggest_float("cotThetaMax", 5.0, 10.0)
89  params.append(cotThetaMax)
90  sigmaScattering = trial.suggest_float("sigmaScattering", 0.2, 50)
91  params.append(sigmaScattering)
92  radLengthPerSeed = trial.suggest_float("radLengthPerSeed", 0.001, 0.1)
93  params.append(radLengthPerSeed)
94  impactMax = trial.suggest_float("impactMax", 0.1, 25)
95  params.append(impactMax)
96  maxPtScattering = trial.suggest_float("maxPtScattering", 1, 50)
97  params.append(maxPtScattering)
98  deltaRMin = trial.suggest_float("deltaRMin", 0.25, 30)
99  params.append(deltaRMin)
100  deltaRMax = trial.suggest_float("deltaRMax", 50, 300)
101  params.append(deltaRMax)
102  keys = [
103  "maxSeedsPerSpM",
104  "cotThetaMax",
105  "sigmaScattering",
106  "radLengthPerSeed",
107  "impactMax",
108  "maxPtScattering",
109  "deltaRMin",
110  "deltaRMax",
111  ]
112 
113  outputDir = Path(srcDir / "Output_CKF")
114  outputfile = srcDir / "Output_CKF/performance_ckf.root"
115  outputDir.mkdir(exist_ok=True)
116  run_ckf(params, keys, outputDir)
117  rootFile = uproot.open(outputfile)
118  self.res["eff"].append(rootFile["eff_particles"].member("fElements")[0])
119  self.res["fakerate"].append(rootFile["fakerate_tracks"].member("fElements")[0])
120  self.res["duplicaterate"].append(
121  rootFile["duplicaterate_tracks"].member("fElements")[0]
122  )
123 
124  timingfile = srcDir / "Output_CKF/timing.tsv"
125  timing = pd.read_csv(timingfile, sep="\t")
126  time_ckf = float(
127  timing[timing["identifier"].str.match("Algorithm:TrackFindingAlgorithm")][
128  "time_perevent_s"
129  ]
130  )
131  time_seeding = float(
132  timing[timing["identifier"].str.match("Algorithm:SeedingAlgorithm")][
133  "time_perevent_s"
134  ]
135  )
136  self.res["runtime"].append(time_ckf + time_seeding)
137 
138  efficiency = self.res["eff"][-1]
139  penalty = (
140  self.res["fakerate"][-1]
141  + self.res["duplicaterate"][-1] / self.k_dup
142  + self.res["runtime"][-1] / self.k_time
143  )
144 
145  return efficiency - penalty
146 
147 
148 def main():
149 
150  k_dup = 5
151  k_time = 5
152 
153  # Initializing the objective (score) function
154  objective = Objective(k_dup, k_time)
155 
156  """
157  start_values = {
158  "maxSeedsPerSpM": 1,
159  "cotThetaMax": 7.40627,
160  "sigmaScattering": 50,
161  "radLengthPerSeed": 0.1,
162  "impactMax": 3.0,
163  "maxPtScattering": 10.0,
164  "deltaRMin": 1.0,
165  "deltaRMax": 60.0
166 }
167 
168  """
169  # Optuna logger
170  optuna.logging.get_logger("optuna").addHandler(logging.StreamHandler(sys.stdout))
171  study_name = "test_study"
172  storage_name = "sqlite:///{}.db".format(study_name)
173 
174  # creating a new optuna study
175  study = optuna.create_study(
176  study_name=study_name,
177  storage="sqlite:///{}.db".format(study_name),
178  direction="maximize",
179  load_if_exists=True,
180  )
181 
182  # study.enqueue_trial(start_values)
183  # Start Optimization
184  study.optimize(objective, n_trials=3)
185 
186  # Printout the best trial values
187  print("Best Trial until now", flush=True)
188  for key, value in study.best_trial.params.items():
189  print(f" {key}: {value}", flush=True)
190 
191  outputDir = Path("OptunaResults")
192  outputDir.mkdir(exist_ok=True)
193 
194  with open(outputDir / "results.json", "w") as fp:
195  json.dump(study.best_params, fp)
196 
197 
198 if __name__ == "__main__":
199  main()