Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the helix-example project into demos. #1202

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
Binary file not shown.
1 change: 1 addition & 0 deletions demos/helix-example/helix-example/Graph_from_file.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions demos/helix-example/helix-example/Helix.ipynb

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions demos/helix-example/helix-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/compiler-research/helix-example/HEAD)
# Helix fitter example

## Goal

Particle tracking is an important part of the processing and analysis of data received from particle detectors, such as the Compact Muon Solenoid (CMS). Tracking is the step that determines the momentum of charged particles escaping from the collision point. It identifies individual particles by reconstructing their trajectories from points where charged particle “hits” were measured by the detector and interpreting them.[1] Due to the Lorentz force, charged particles move in a helical motion when affected by the magnetic field (neglecting other effects due to material interactions, etc). This means we can figure out a specific particle trajectory through the detector by fitting a helix function to data points in such a way that the distance from the data points and the helix would be minimized. In mathematical terms, we need to find optimal helix parameters by minimizing a loss function composed of the sum of least squared distances, thus giving the best estimation of these parameters. For this purpose we can use Clad to efficiently minimize the loss function.

In this repository one can find the code containing one such helix fitter implementation.

## Content

Besides the main fitter code, there are a few more files:

- Documentation.pdf - a more in depth explanation of the code and methods used.
- Helix.ipynb - a Jupyter notebook containing the code and the documentation comments. Can be used to try out the code online but is considerably slower.
- Graph_from_file.ipynb - accompanies Helix.ipynb. Reads from the output.txt (produced by Helix.ipynb) and plots the results.


## Usage

One can compile the files with:

```
clang++ main.cc -o main -I /full/path/to/clad/include/ -fplugin=/full/path/to/lib/clad.so -I /full/path/to/kokkos-4.3.01/include
```
Running the code and plotting the output can be done by:

```
./main | python3 graph.py
```
23 changes: 23 additions & 0 deletions demos/helix-example/helix-example/distance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <cmath>

inline double DistanceSquare(double x1, double y1, double z1, double x2, double y2, double z2)
{
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
}

inline double Distance(double x1, double y1, double z1, double x2, double y2, double z2)
{
return std::sqrt(DistanceSquare(x1, y1, z1, x2, y2, z2));
}

inline double DistanceSquareA(double v[3], double x2, double y2, double z2)
{
return DistanceSquare(v[0], v[1], v[2], x2, y2, z2);
}

inline double DistanceA(double v[3], double x2, double y2, double z2)
{
return Distance(v[0], v[1], v[2], x2, y2, z2);
}
6 changes: 6 additions & 0 deletions demos/helix-example/helix-example/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
channels:
- conda-forge
dependencies:
- xeus-cling
- clad
- matplotlib
90 changes: 90 additions & 0 deletions demos/helix-example/helix-example/equations.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#pragma once

#include <cmath>
#include <cassert>

auto MY_PI = 3.14159265359;

double EvaluateSinPlusLin(double A, double B, double C, double D, double x)
{
/*When this equation is equal to zero, the distance between the point and the helix is the shortest.*/
return A * std::sin(x + B) + C * x + D;
}

double SolveSinPlusLin(double A, double B, double C, double D, double mi, double ma)
{
/*Binary search to determine x, with which EvaluateSinPlusLin equation equals zero.*/
for (int i = 0; i < 100; i++)
{
double mid = (mi + ma) / 2;
double vmi = EvaluateSinPlusLin(A, B, C, D, mi);
double vmid = EvaluateSinPlusLin(A, B, C, D, mid);
double vma = EvaluateSinPlusLin(A, B, C, D, ma);

if (vmi < 0 and 0 < vmid)
{
ma = mid;
}
else if (vmid < 0 and 0 < vma)
{
mi = mid;
}
else if (vmid < 0 and 0 < vmi)
{
ma = mid;
}
else if (vma < 0 and 0 < vmid)
{
mi = mid;
}
else
{
break;
mi = mid;
}
}

double x = (mi + ma) / 2;
return x;
}

double NextValPiK(double offs, double x)
{
/*Find the next 2 * PI * k + offset (where k is an integer) that is greater than x.*/

if (x < 0)
{
double v = -NextValPiK(-offs, -x) + 2 * MY_PI;
return v > x ? v : v + 2 * MY_PI;
}

double kie = std::floor(x / 2 / MY_PI);

for (int i = -2; i <= 2; i++)
{
double v = (kie + i) * 2 * MY_PI + offs;

if (v > x)
{
return v;
}
}

return 1000000000;
}

// A cos(x + B) + C = 0
double NextSinPlusInflection(double A, double B, double C, double x)
{
/* Identifies the next inflection point of the sine curve.*/
// cos(x + B) = -C / A
if (-C / A >= -1 && -C / A <= 1)
{
double inv = std::acos(-C / A);
return std::min(NextValPiK(inv - B, x), NextValPiK(-inv - B, x));
}
else
{
return 1000000000;
}
}
Loading