Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@
#
# Mozilla Public License Version 2.0

#Ignore .csv files
*.csv
*.csv~
#ignore files
example_ACTS.json
example_ACTS.json~
example.json~
main_test.py
main_test.py~
seeding_param.json
seeding_param.json~
Comment on lines +11 to +17
Copy link
Member

@stephenswat stephenswat Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
example_ACTS.json
example_ACTS.json~
example.json~
main_test.py
main_test.py~
seeding_param.json
seeding_param.json~
*~

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Added

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not really what I meant; you can remove all the other excludes if you just add the one I suggested.

*~

# Prerequisites
*.d

Expand Down
2 changes: 1 addition & 1 deletion core/include/traccc/seeding/detail/seeding_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct seedfinder_config {
float deltaRMax = 80 * unit<float>::mm;

// maximum distance in mm in z between measurements in one seed
float deltaZMax = 450 * unit<float>::mm;
float deltaZMax = 850 * unit<float>::mm;

// FIXME: this is not used yet
// float upperPtResolutionPerSeed = 20* Acts::GeV;
Expand Down
12 changes: 11 additions & 1 deletion examples/options/src/track_seeding.cpp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++ changes should now be removed from this PR.

Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ track_seeding::track_seeding() : interface("Track Seeding Options") {
po::value(&m_seedfinder.impactMax)
->default_value(m_seedfinder.impactMax / unit<float>::mm),
"Maximum impact parameter [mm]");
m_desc.add_options()(
"seedfinder-deltaZMax",
po::value(&m_seedfinder.deltaZMax)
->default_value(m_seedfinder.deltaZMax / unit<float>::mm),
"Maximum Z distance between measurements [mm]");

m_desc.add_options()("seedfinder-sigmaScattering",
po::value(&m_seedfinder.sigmaScattering)
->default_value(m_seedfinder.sigmaScattering),
Expand Down Expand Up @@ -128,7 +134,8 @@ void track_seeding::read(const po::variables_map&) {
m_seedfinder.impactMax *= unit<float>::mm;
m_seedfinder.maxPtScattering *= unit<float>::GeV;
m_seedfinder.bFieldInZ *= unit<float>::T;

m_seedfinder.deltaZMax *= unit<float>::mm;

m_seedfilter.deltaInvHelixDiameter /= unit<float>::mm;

m_seedfinder.setup();
Expand Down Expand Up @@ -170,6 +177,9 @@ std::unique_ptr<configuration_printable> track_seeding::as_printable() const {
cat->add_child(std::make_unique<configuration_kv_pair>(
"Maximum impact parameter",
std::format("{:.2f} mm", m_seedfinder.impactMax / unit<float>::mm)));
cat->add_child(std::make_unique<configuration_kv_pair>(
"Maximum Z distance between measurements",
std::format("{:.2f} mm", m_seedfinder.deltaZMax / unit<float>::mm)));
cat->add_child(std::make_unique<configuration_kv_pair>(
"Scattering angle sigma",
std::format("{:.2f}", m_seedfinder.sigmaScattering)));
Expand Down
12 changes: 11 additions & 1 deletion extras/cut_optimiser/find_pareto_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def main():
and n["efficiency"] >= m["efficiency"]
and n["fake_rate"] <= m["fake_rate"]
and n["duplicate_rate"] <= m["duplicate_rate"]
and n["seeding_efficiency"] >= m["seeding_efficiency"]
and n["seed_fake_rate"] <= m["seed_fake_rate"]
and n["seed_duplicate_rate"] <= m["seed_duplicate_rate"]
Comment on lines +62 to +64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep in mind that the Pareto set of the seeding parameters and the finding parameters is much larger than the Pareto set of just the seeding parameters or the finding parameters. Would it make sense to add a CLI switch that can be used to select the user's preference?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that might be better. Maybe Adding two CLI options to seeding performance and finding performance?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think that's a good idea!


):
log.debug(
"Removing %s from the Pareto set because %s is superior",
Expand All @@ -73,11 +77,14 @@ def main():

for i in sorted(pareto_set, key=lambda x: x["rec_throughput"], reverse=True):
log.info(
" Eff. %.2f, fake rate %.2f, duplicate rate %.2f with reciprocal througput %.1fms is achieved by setup {%s}",
" Eff. %.2f, fake rate %.2f, duplicate rate %.2f with reciprocal througput %.1fms and Seeding Eff. %.2f, Seed fake rate %.2f, Seed duplicate rate %.2f is achieved by setup {%s}",
100.0 * i["efficiency"],
i["fake_rate"],
i["duplicate_rate"],
i["rec_throughput"] * 1000.0,
i["seeding_efficiency"],
i["seed_fake_rate"],
i["seed_duplicate_rate"],
", ".join(
"%s: %s" % (k, str(v))
for k, v in i.items()
Expand All @@ -87,6 +94,9 @@ def main():
"fake_rate",
"duplicate_rate",
"rec_throughput",
"seeding_efficiency",
"seed_fake_rate",
"seed_duplicate_rate",
"success",
]
),
Expand Down
97 changes: 68 additions & 29 deletions extras/cut_optimiser/main.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs to be formatted with Black.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get this part. What do you mean formatted with black?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Black is a Python formatter. You can run it by executing uv run black [file] or uv run black [directory]. It will then automatically update the formatting of your code for you.

Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
import subprocess
import re


import traccc_bench_tools.parse_profile
import traccc_bench_tools.types


log = logging.getLogger("traccc_cut_optimiser")


def main():
def main():
parser = argparse.ArgumentParser()

parser.add_argument(
Expand Down Expand Up @@ -108,7 +107,7 @@ def main():
params = json.load(f)

parameter_space = params["parameters"]
parameter_names = sorted(parameter_space)
parameter_names = list(parameter_space)

log.info(
"Running optimisation for %d parameters: %s",
Expand All @@ -122,29 +121,39 @@ def main():
"efficiency",
"fake_rate",
"duplicate_rate",
"seeding_efficiency",
"seed_fake_rate",
"seed_duplicate_rate",
]

parameters = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you already fixed this bug and you should now be using results, so this change is no longer necessary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I need parameters. I am using results and parameters as separate lists

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But isn't parameters the same as results.keys()?

if args.db.is_file():
log.info('Database file "%s" already exists; creating a backup', args.db)
shutil.copy(str(args.db), str(args.db) + ".bak")
results = {}
with open(args.db, "r") as f:
reader = csv.DictReader(f)
for i in reader:
key = (i[k] for k in parameter_names)
key = tuple(i[k] for k in parameter_names)
pkey = tuple(float(i[k]) for k in parameter_names)
parameters.append(pkey)
if set(i.keys()) != set(csv_field_names):
raise ValueError(
"Input database has unexpected columns or is missing columns"
)
if i["success"] != 0:
set_skip = False
results[key] = {
"rec_throughput": i["rec_throughput"],
"efficiency": i["efficiency"],
"fake_rate": i["fake_rate"],
"duplicate_rate": i["duplicate_rate"],
"seeding_efficiency": i["seeding_efficiency"],
"seed_fake_rate": i["seed_fake_rate"],
"seed_duplicate_rate": i["seed_duplicate_rate"],
}
else:
results[key] = None
results[key] = None
log.info("Database contained %d pre-existing results", len(results))
else:
log.info('Database file "%s" does not exist; starting from scratch', args.db)
Expand Down Expand Up @@ -178,8 +187,7 @@ def main():
if args.random:
param_dict = {n: random.choice(vs) for n, vs in parameter_space.items()}
param_list = tuple(param_dict.values())

if param_list in results:
if param_list in parameters:
random_retry_count += 1
if random_retry_count < 10:
log.info(
Expand All @@ -203,7 +211,7 @@ def main():
except StopIteration:
log.info("Design space has been exhausted; exiting")
break
if param_list in results:
if param_list in parameters:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you not using results here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

results doesn't contain the parameter values, it just contain efficiencies and fake rates. I could have used key to access parameters, but param_list is a list of floating point numbers hence comparing against another list.

log.info(
"Configuration %s is already known; continuing", str(param_dict)
)
Expand Down Expand Up @@ -241,8 +249,7 @@ def main():
"--grid-file=%s" % params["input"]["grid_file"],
"--material-file=%s" % params["input"]["material_file"],
"--input-events=1",
"--check-performance",
"--use-acts-geom-source=on",
"--check-performance",
]

for k, v in params["config"].items():
Expand All @@ -253,27 +260,26 @@ def main():

if args.ncu_wrapper is not None:
profile_args = args.ncu_wrapper.split() + profile_args

try:
result = subprocess.run(
profile_args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=tmppath,
check=True,
timeout=args.timeout,
profile_args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=tmppath,
check=True,
timeout=args.timeout,
)
except subprocess.CalledProcessError as e:
log.warning("Process failed to execute; continuing")
results[param_list] = None
continue
#except subprocess.CalledProcessError as e:
# log.warning("Process failed to execute; continuing")
# results[param_list] = None
# continue
Comment on lines +273 to +276
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

un-commented now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still commented.

except subprocess.TimeoutExpired as e:
log.warning("Process timed out; marking as failure and continuing")
results[param_list] = None
continue

stdout = result.stdout.decode("utf-8")

if match := re.search(
r"Total track efficiency was (\d+(?:\.\d*)?)%", stdout
):
Expand All @@ -294,12 +300,39 @@ def main():
result_fake_rate = float(match.group(1))
else:
raise ValueError("Fake rate could not be parsed from stdout!")

if match := re.search(
r"Total seed efficiency was (\d+(?:\.\d*)?)%", stdout
):
result_seeding_efficiency = float(match.group(1)) / 100.0
else:
raise ValueError("Seeding Efficiency could not be parsed from stdout!")

if match := re.search(
r"Total seed fake rate was (\d+(?:\.\d*)?)", stdout
):
result_seed_fake_rate = float(match.group(1))
else:
raise ValueError("Seed fake rate could not be parsed from stdout!")

if match := re.search(
r"Total seed duplicate rate was (\d+(?:\.\d*)?)", stdout
):
result_seed_duplicate_rate = float(match.group(1))
else:
raise ValueError("Seed Duplicate rate could not be parsed from stdout!")


log.info(
"Physics performance was %.1f%% efficiency, %.1f fake rate, %.1f duplicate rate",
result_efficiency * 100.0,
result_duplicate_rate,
result_fake_rate,
"Physics performance was %(efficiency).1f%% efficiency, %(fake).1f fake rate, %(duplicate).1f duplicate rate, %(seeding_efficiency).1f%% seeding efficiency, %(seed_fake).1f seed fake rate, %(seed_duplicate).1f seed duplicate rate",
{
"efficiency": result_efficiency * 100.0,
"fake": result_fake_rate,
"duplicate": result_duplicate_rate,
"seeding_efficiency": result_seeding_efficiency * 100.0,
"seed_fake": result_seed_fake_rate,
"seed_duplicate": result_seed_duplicate_rate,
},
)

end_time = time.time()
Expand Down Expand Up @@ -337,6 +370,9 @@ def main():
"efficiency": result_efficiency,
"fake_rate": result_fake_rate,
"duplicate_rate": result_duplicate_rate,
"seeding_efficiency": result_seeding_efficiency,
"seed_fake_rate": result_seed_fake_rate,
"seed_duplicate_rate": result_seed_duplicate_rate,
}

except Exception as e:
Expand All @@ -348,16 +384,16 @@ def main():

log.info("Gathered a total of %d results (incl. pre-existing)", len(results))


log.info("Writing data to %s", args.db)
with open(args.db, "w") as f:
writer = csv.DictWriter(
f,
fieldnames=csv_field_names,
)
writer.writeheader()

for k, v in results.items():

param_dict = {parameter_names[i]: p for i, p in enumerate(k)}
if v is None:
writer.writerow(
Expand All @@ -368,6 +404,9 @@ def main():
efficiency=0.0,
fake_rate=0.0,
duplicate_rate=0.0,
seeding_efficiency=0.0,
seed_fake_rate=0.0,
seed_duplicate_rate=0.0,
Comment on lines +407 to +409
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you need to update the Pareto front finder if you make this change?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed in find_pareto_set.py

)
)
else:
Expand Down
2 changes: 1 addition & 1 deletion extras/cut_optimiser/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "cut-optimiser"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
requires-python = ">=3.12"
dependencies = [
"pydantic>=2.11.7",
"traccc-bench-tools",
Expand Down
Loading