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

Compute Orientations from CSV #10

Merged
merged 6 commits into from
Mar 17, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
90 changes: 58 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,66 @@
## Geometry File Information

The files `DetId_sensors_list.csv` and `module_info.csv` are sourced from Tracker version OT800_IT615:

- URL: [Tracker Version OT800_IT615](https://cms-tklayout.web.cern.ch/cms-tklayout/layouts-work/recent-layouts/OT800_IT615/info.html)

Sources for specific files:
- `allCoordinates.csv` (renamed `module_info.csv`) is available at [OT800_IT615 Layout](https://cms-tklayout.web.cern.ch/cms-tklayout/layouts-work/recent-layouts/OT800_IT615/layout.html)
- `DetId_sensors_list.csv` can be found linked from the homepage of the above URL.
- The `average_r_OT800_IT615.txt` and `average_z_OT800_IT615.txt` files can be taken directly from the table at the top of the [OT800_IT615 Layout](https://cms-tklayout.web.cern.ch/cms-tklayout/layouts-work/recent-layouts/OT800_IT615/layout.html) page. These represent the average r positions of the Barrel layers and the average z positions of the Endcap layers.

## Setting up the relevant environment

# Download and install Miniconda
curl -O -L https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b

# add conda to the end of ~/.bashrc, so relogin after executing this line
~/miniconda3/bin/conda init

# stop conda from activating the base environment on login
# (optional) stop conda from activating the base environment on login
conda config --set auto_activate_base false

# Add conda-forge as a priority channel for package management
conda config --add channels conda-forge

# Create a new conda environment with necessary packages
conda create --name analysisenv uproot pandas matplotlib jupyter graphviz iminuit scipy shapely root
conda activate analysisenv # To be repeated when re-doing this study
conda activate analysisenv
conda install -c plotly plotly=4.14.3
pip install yahist particle graphviz pydot tqdm

# Optional steps
git clone [email protected]:SegmentLinking/LSTStudy.git
cd LSTStudy

jupyter notebook --no-browser

# remember the port number and do something like the following on your local computer
ssh -N -f -L localhost:$port:localhost:$port uaf-$uaf.t2.ucsd.edu

## Geometry File Information

The files `DetId_sensors_list.csv` and `module_info.csv` are sourced from Tracker version OT800_IT615:

- URL: [Tracker Version OT800_IT615](https://cms-tklayout.web.cern.ch/cms-tklayout/layouts-work/recent-layouts/OT800_IT615/info.html)

Sources for specific files:
- `allCoordinates.csv` (renamed `module_info.csv`) is available at [OT800_IT615 Layout](https://cms-tklayout.web.cern.ch/cms-tklayout/layouts-work/recent-layouts/OT800_IT615/layout.html)
- `DetId_sensors_list.csv` can be found linked from the homepage of the above URL.
- The `average_r_OT800_IT615.txt` and `average_z_OT800_IT615.txt` files can be taken directly from the table at the top of the [OT800_IT615 Layout](https://cms-tklayout.web.cern.ch/cms-tklayout/layouts-work/recent-layouts/OT800_IT615/layout.html) page. These represent the average r positions of the Barrel layers and the average z positions of the Endcap layers.
# Note: After installation, activate your environment with:
# conda activate analysisenv
# To deactivate, use:
# conda deactivate

## Compute Geometry (CSV)

The `compute_geometry.py` file computes both the sensor corner coordinates and centroid coordinates using the `compute_corners.py` and `compute_centroids.py` files respectively.
The `compute_geometry.py` file computes both the sensor corner coordinates and centroid coordinates, as well as two orientation files used by the segment linking algorithm, using the `compute_corners.py`, `compute_centroids.py`, and `compute_orientation.py` files respectively. This is the only file that you need to run prior to generating the module maps and pixel maps. Documentation for the individual geometry python files it calls are also given below, but do not need to be run in addition to compute_geometry.

Usage:

Run: python3 compute_geometry.py for default file paths.

For custom paths: python3 compute_geometry.py [module_info_file] [sensor_info_file] [outputfile_corners] [outputfile_centroid]
Replace [module_info_file], [sensor_info_file], [outputfile_corners], and [outputfile_centroid] with your specific file paths.
For custom paths: python3 compute_geometry.py [module_info_file] [sensor_info_file] [outputfile_corners] [outputfile_centroid] [outputfile_tilted_barrel] [outputfile_endcap]
Default module info file: data/module_info_OT800_IT615.csv
Default sensor info file: data/DetId_sensors_list_OT800_IT615.csv
Default output file for corners: output/sensor_corners.txt
Default output file for centroids: output/sensor_centroids.txt
Default output file for tilted barrel orientations: output/tilted_barrel_orientation.txt
Default output file for endcap orientations: output/endcap_orientation.txt

## Computing the Module Maps and Pixel Maps

After running the `compute_geometry.py` file (see above) the following can be run.

Use the scripts:

python3 compute_pixelmap.py
python3 compute_modulemap.py

This will place the modulemap output to the output/ directory and the pixelmaps to their own pixelmap directory.

## Compute Centroids (CSV)

Expand All @@ -59,10 +71,13 @@ Usage:
Run: python3 compute_centroids.py for default file paths.

For custom paths: python3 compute_centroids.py [inputfile] [outputfile]
Replace [inputfile] and [outputfile] with your specific file paths.
Default input: data/DetId_sensors_list_OT800_IT615.csv
Default output: output/sensor_centroids.txt

Output Format:

sensor_centroids.txt - [sensor detid], [x coordinate of centroid (cm)], [y coordinate of centorid (cm)], [z coordinate of centroid (cm)], [moduletype (23 (PSP), 24 (PSS), or 25 (TwoS))]

## Compute Corners (CSV)

The `compute_corners.py` file calculates the four corner coordinates of each sensor based on the provided module and sensor CSV files. It uses rotation matrices to account for various rotations of each sensor and outputs the corner coordinates for each sensor.
Expand All @@ -72,18 +87,29 @@ Usage:
Run: python3 compute_corners.py for default file paths.

For custom paths: python3 compute_corners.py [module_info_file] [sensor_info_file] [outputfile]
Replace [module_info_file], [sensor_info_file], and [outputfile] with your specific file paths.
Default module info file: data/module_info_OT800_IT615.csv
Default sensor info file: data/DetId_sensors_list_OT800_IT615.csv
Default output file: output/sensor_corners.txt

## Computing the module maps and pixel maps
Output Format:

After running the `compute_geometry.py` file (see above) the following can be run.
sensor_corners.txt - "sensor detid": [Z, X, Y coordinates for each of the sensor's four corners (cm)]

Use the scripts:
## Compute Orientations (CSV)

python3 compute_pixelmap.py
python3 compute_modulemap.py
The `compute_orientation.py` script calculates the orientations (dr/dz and dx/dy slopes) of each relevant sensor based on their corner coordinates. It outputs two files: one for the slopes of tilted barrel sensors and another for the slopes of endcap sensors. Note that only the dxdy slope is given for endcap sensors because dz is always 0 in the current geometry for the endcap sensors. Additionally, for endcap sensors, the centroid phi value also appended to orientation information.

This will place the modulemap output to the output/ directory and the pixelmaps to their own pixelmap directory.
Usage:

Run: python3 compute_orientation.py for default file paths.

For custom paths: python3 compute_orientation.py [sensor_corners_file] [centroids_file] [output_tilted_barrel_file] [output_endcap_file]
Default sensor corners file: output/sensor_corners.txt
Default centroids file: data/DetId_sensors_list_OT800_IT615.csv
Default output file for tilted barrel orientations: output/tilted_barrel_orientation.txt
Default output file for endcap orientations: output/endcap_orientation.txt

Output Format:

endcap_orientation.txt - [endcap sensor detid] [dx/dy slope of sensor] [centroid phi value of sensor]
tilted_barrel_orientation.txt - [tilted barrel sensor detid] [dr/dz slope of sensor] [dx/dy slope of sensor]
53 changes: 44 additions & 9 deletions compute_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,24 @@
# Import relevant functions from other scripts
from compute_corners import transform_sensor_corners, assign_corners_to_sensor
from compute_centroids import compute_centroids
from compute_orientation import process_corners, save_slopes_to_file

def compute_geometry(module_info_path, sensor_info_path, output_path_corners, output_path_centroid):
def compute_geometry(module_info_path, sensor_info_path, output_path_corners, output_path_centroid, output_path_tilted_barrel, output_path_endcap):
"""
Computes the full geometry outputs including corners and centroids, and calculates orientations (slopes) for both barrel and endcap sensors.
The results are saved to specified output files.

Parameters:
module_info_path (str): Path to the CSV file containing module information.
sensor_info_path (str): Path to the CSV file containing sensor information.
output_path_corners (str): File path for saving computed corners.
output_path_centroid (str): File path for saving computed centroids.
output_path_tilted_barrel (str): File path for saving calculated slopes for tilted barrel sensors.
output_path_endcap (str): File path for saving calculated slopes for endcap sensors.

This function integrates several steps including reading module and sensor information from CSV files,
computing and assigning transformed corners to sensors, calculating centroids, and finally computing and saving orientations for barrel and endcap sensors.
"""
# Read input module/sensor csv files
module_csv = pd.read_csv(module_info_path)
sensor_csv = pd.read_csv(sensor_info_path)
Expand All @@ -24,34 +40,53 @@ def compute_geometry(module_info_path, sensor_info_path, output_path_corners, ou
for i in range(len(x)):
output.write(f"{detid[i]},{x[i]},{y[i]},{z[i]},{moduleType[i]}\n")

# Compute barrel and endcap orientations (slopes) and save to files
barrel_slopes, endcap_slopes = process_corners(assigned_corners)
save_slopes_to_file(barrel_slopes, output_path_tilted_barrel, sensor_csv)
save_slopes_to_file(endcap_slopes, output_path_endcap, sensor_csv)

print(f"\nProcessed files: {module_info_path}, {sensor_info_path}")
print(f"Output written to: {output_path_corners}, {output_path_centroid}\n")
print(f"Output written to: {output_path_corners}, {output_path_centroid}, {output_path_tilted_barrel}, {output_path_endcap}\n")

if __name__ == "__main__":
def main():
# Default file paths
default_module_info_path = "data/module_info_OT800_IT615.csv"
default_sensor_info_path = "data/DetId_sensors_list_OT800_IT615.csv"
default_output_path_corners = "output/sensor_corners.txt"
default_output_path_centroid = "output/sensor_centroids.txt"
default_output_path_tilted_barrel = "output/tilted_barrel_orientation.txt"
default_output_path_endcap = "output/endcap_orientation.txt"

# Check for help flag
if '-h' in sys.argv or '--help' in sys.argv:
print("\nUsage: python compute_geometry.py [module_info_file] [sensor_info_file] [outputfile_corners] [outputfile_centroid]")
print("\nUsage: python compute_geometry.py [module_info_file] [sensor_info_file] [outputfile_corners] [outputfile_centroid] [outputfile_tilted_barrel] [outputfile_endcap]")
print("\nOptions:")
print(f" module_info_file Path to the module information CSV file. Default is {default_module_info_path}")
print(f" sensor_info_file Path to the sensor information CSV file. Default is {default_sensor_info_path}")
print(f" outputfile_corners Path for the corners output file. Default is {default_output_path_corners}")
print(f" outputfile_centroid Path for the centroid output file. Default is {default_output_path_centroid}\n")
print(f" module_info_file Path to the module information CSV file. Default is {default_module_info_path}")
print(f" sensor_info_file Path to the sensor information CSV file. Default is {default_sensor_info_path}")
print(f" outputfile_corners Path for the corners output file. Default is {default_output_path_corners}")
print(f" outputfile_centroid Path for the centroid output file. Default is {default_output_path_centroid}")
print(f" outputfile_tilted_barrel Path for the tilted barrel orientation output file. Default is {default_output_path_tilted_barrel}")
print(f" outputfile_endcap Path for the endcap orientation output file. Default is {default_output_path_endcap}\n")
sys.exit()

# Determine input and output file paths based on arguments provided
module_info_path = sys.argv[1] if len(sys.argv) > 1 else default_module_info_path
sensor_info_path = sys.argv[2] if len(sys.argv) > 2 else default_sensor_info_path
output_path_corners = sys.argv[3] if len(sys.argv) > 3 else default_output_path_corners
output_path_centroid = sys.argv[4] if len(sys.argv) > 4 else default_output_path_centroid
output_path_tilted_barrel = sys.argv[5] if len(sys.argv) > 5 else default_output_path_tilted_barrel
output_path_endcap = sys.argv[6] if len(sys.argv) > 6 else default_output_path_endcap

# Make output folder if it doesn't exist
os.makedirs(os.path.dirname("output/"), exist_ok=True)

# Compute geometry with specified file paths
compute_geometry(module_info_path, sensor_info_path, output_path_corners, output_path_centroid)
compute_geometry(module_info_path,
sensor_info_path,
output_path_corners,
output_path_centroid,
output_path_tilted_barrel,
output_path_endcap)

if __name__ == "__main__":
main()
139 changes: 139 additions & 0 deletions compute_orientation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import os
import sys
import json
import numpy as np
import pandas as pd

import Module as m
from compute_centroids import parse_module_type

# Constants for Barrel and Endcap subdet type
BARREL, ENDCAP = 5, 4
# Default value for slopes if undefined
DEFAULT_SLOPE = 123456789

def calculate_slope(dx, dy, dz):
"""
Calculate the slopes drdz and dxdy based on the differences in x, y, and z corner coordinates.
If slope is undefined, use the default slope value.

Parameters:
dx (float): Difference in x corner coordinates.
dy (float): Difference in y corner coordinates.
dz (float): Difference in z corner coordinates.

Returns:
tuple: A tuple containing the drdz_slope and dxdy_slope values.
"""
dr = np.sqrt(dx**2 + dy**2)
drdz_slope = dr / dz if dz != 0 else DEFAULT_SLOPE
dxdy_slope = -dx / dy if dy != 0 else DEFAULT_SLOPE
return drdz_slope, dxdy_slope

def process_corners(corners):
"""
Use each sensor's corners to calculate and categorize drdz and dxdy slopes.

Parameters:
corners (dict): A dictionary with sensor DetID as keys and their corner coordinates as values.

Returns:
tuple: Two dictionaries containing the slopes for barrel and endcap sensors respectively.
"""
barrel_slopes, endcap_slopes = {}, {}

for detid, row in corners.items():
# Grab first two corners of the sensor
corner_1, corner_2 = row[0], row[1]

# Compute dx, dy, dz for first two corner coordinates
dx = corner_2[1] - corner_1[1]
dy = corner_2[2] - corner_1[2]
dz = corner_2[0] - corner_1[0]

# Calculate drdz and dxdy slopes using the dx, dy, dz variables
drdz_slope, dxdy_slope = calculate_slope(dx, dy, dz)

# Initialize module object to get subdet, tilted and strip variables
moduletype = parse_module_type(int(detid))
module = m.Module(int(detid), int(moduletype))

# Distinguishes barrel and endcap
subdet = module.subdet()
# Is the sensor tilted
tilted = module.side() != 3
# Is the sensor a strip sensor
strip = module.moduleLayerType() == 1

if not strip:
continue

# Save slopes to relevant dict if the sensor meets requirements
slope_data = {'drdz_slope': drdz_slope, 'dxdy_slope': dxdy_slope}
if subdet == BARREL and tilted:
barrel_slopes[detid] = slope_data
elif subdet == ENDCAP:
endcap_slopes[detid] = slope_data

return barrel_slopes, endcap_slopes

def save_slopes_to_file(slopes, output_path, centroids_df):
"""
Saves the calculated slopes to a file.

Parameters:
slopes (dict): A dictionary with sensor DetID as keys and slopes as values.
output_path (str): The file path to save the slope data.
"""
with open(output_path, 'w') as file:
for detid, values in slopes.items():
# The endcap sensors will have drdz as the default always
if values['drdz_slope'] != DEFAULT_SLOPE:
line = f"{detid} {values['drdz_slope']} {values['dxdy_slope']}\n"
else:
# LST algorithm expects centroid phi appended to orientation info for endcap.
centroid_phi = np.radians(centroids_df.loc[centroids_df['DetId/i'] == int(detid), ' phi_deg/D'].values[0])
line = f"{detid} {values['dxdy_slope']} {centroid_phi}\n"
file.write(line)

if __name__ == "__main__":
# Default file paths
default_sensor_corners_file = 'output/sensor_corners.txt'
default_centroids_file = "data/DetId_sensors_list_OT800_IT615.csv"
output_tilted_barrel_file = 'output/tilted_barrel_orientation.txt'
output_endcap_file = 'output/endcap_orientation.txt'

# Check for help flag
if '-h' in sys.argv or '--help' in sys.argv:
print("\nUsage: python compute_orientation.py [sensor_corners_file] [centroids_file] [output_tilted_barrel_file] [output_endcap_file]")
print("\nOptions:")
print(f" sensor_corners_file Path to the sensor corners file. Default is {default_sensor_corners_file}")
print(f" centroids_file Path to the centroids file containing detId and phi values. Default is {default_centroids_file}")
print(f" output_tilted_barrel_file Path to the output file for tilted barrel orientations. Default is {output_tilted_barrel_file}")
print(f" output_endcap_file Path to the output file for endcap orientations. Default is {output_endcap_file}")
sys.exit()

# Determine file paths based on arguments provided
sensor_corners_file = sys.argv[1] if len(sys.argv) > 1 else default_sensor_corners_file
centroids_file = sys.argv[2] if len(sys.argv) > 2 else default_centroids_file
output_tilted_barrel_file = sys.argv[3] if len(sys.argv) > 3 else output_tilted_barrel_file
output_endcap_file = sys.argv[4] if len(sys.argv) > 4 else output_endcap_file

# Ensure geometry file exists or create it
if not os.path.exists(sensor_corners_file):
from compute_geometry import main as make_geometry
make_geometry()

# Load sensor corners from file
with open(sensor_corners_file, 'r') as file:
corners = json.load(file)

# Load centroids information for phi values
centroids_df = pd.read_csv(default_centroids_file, usecols=['DetId/i', ' phi_deg/D'])

# Process corners to calculate slopes
barrel_slopes, endcap_slopes = process_corners(corners)

# Save calculated slopes to files
save_slopes_to_file(barrel_slopes, output_tilted_barrel_file, centroids_df)
save_slopes_to_file(endcap_slopes, output_endcap_file, centroids_df)
Loading