-
Notifications
You must be signed in to change notification settings - Fork 1
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
Full conversion #2
Open
abbyxh
wants to merge
46
commits into
kjvbrt:main
Choose a base branch
from
abbyxh:full_conversion
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
cc321cd
Add files via upload
abbyxh 2a6756d
Update index.js
abbyxh b6dcade
Update config_ild_trial.json
abbyxh 1fe8fcb
Update config_ild_trial.json
abbyxh 0215c4f
changes
abbyxh 4fd3bc1
changes
abbyxh 38d5fbf
cahnges
abbyxh 1963a27
change name test
abbyxh 8ac05be
changes
abbyxh 31881f9
Merge branch 'main' of https://github.com/abbyxh/root2gltf
abbyxh 9d09b97
change
abbyxh d56c302
TEST
abbyxh 4c194dd
is this working
abbyxh 75f7c3c
completed detector changes
abbyxh b996379
Finished
abbyxh 0cf2042
Added xml -> gltf detector conversion python scripts so that the full…
8dda039
Combined the .xml -> .root converter with the .root -> .gltf converte…
49bdb02
Added python script to get a dictionary of the layers in a given xml …
f33a7aa
Added a 'maxDepth' variable that can be used if you don't want to sho…
78bf31f
Created a processing function to turn the original tree dictionary in…
c262670
Tidied up the configfile generator python script so it could be added…
2e71168
Finished the 'conversion_xml2gltf_autoConfig.py' script to convert th…
027db15
Moved python files to 'bin' and added folders for root and gltf files…
a5a7979
Finished adding in 'inputs' that are given to the user throughout the…
a963223
Added in more detectors (some xml files seem unable to work currently…
568ed7b
Was able to add in an option for users to define parts of the detecto…
4265929
Added some comments on how the python scripts work as well as includi…
ad6ddb8
Changed the RegEx in index.js to be a different flag 'i' so that the …
0ff7ecd
Have been working out a way to allow users to add their own colours a…
c01dce2
Managed to fix up the colour changing code so that a user can put the…
b960abc
Functionised the colour changing code and made it so that if colourin…
fdec236
Added in a way for users to add the ILD colors to the automatic confi…
06f886b
Fixed a bug that added the subparts of the subdetector to the previou…
ed814ae
Made edits to the new code and edited the readme file to setup for me…
e683f9c
Create root_folder.txt
abbyxh 3bb8b87
Create gltf.txt
abbyxh 68ad178
Add files via upload
abbyxh dca3085
Add files via upload
abbyxh 97fd933
Add files via upload
abbyxh 07b9d9b
Add files via upload
abbyxh 391414b
Add files via upload
abbyxh 07b2013
Add files via upload
abbyxh 2699afa
Add files via upload
abbyxh fadf0d1
Add files via upload
abbyxh bfb540e
Delete gltf_files/gltf.txt
abbyxh 891e550
Delete root_files/root_folder.txt
abbyxh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -31,3 +31,39 @@ Three variables are expected in the configuration file: | |||||
the phoenix menu | ||||||
* `childrenToHide` stems of names of the subparts to be removed | ||||||
* `maxLevel` maximum depth of detail | ||||||
|
||||||
## Converting xml2gltf | ||||||
|
||||||
The conversion_xml2gltf_autoConfig.py python script provides a way for an xml file to be converted into a gltf file while providing an initial or automatic configuration file that the user is able to alter if they would like to. | ||||||
|
||||||
To run the python script in the bin folder with only a compact file: | ||||||
|
||||||
```bash | ||||||
python conversion_xml2gltf_autoConfig.py -cm <detector.xml> | ||||||
``` | ||||||
|
||||||
The script can also be run by inputing a configuration file, a root file or both. The converter automatically saves the files root, gltf and config files in automatic folders named: | ||||||
|
||||||
* `root_files` -root files can choose to be deleted at the end of the run if the user wishes to | ||||||
* `gltf_files` | ||||||
* `configs` -config files are automatically created if one is not provided but the run can be ended early if the user wants to edit this file | ||||||
|
||||||
The user can input where they'd like to save the files: | ||||||
|
||||||
```bash | ||||||
python conversion_xml2gltf_autoConfig.py -cm <your-detector-file.xml> | ||||||
-r_in <input-root-file.root> | ||||||
-r_out <output-root-file-loactaion.root> | ||||||
-cn_in <input-config-file.json> | ||||||
-cn_out <output-config-file-loactaion.json> | ||||||
-g <output-gltf-file-location.gltf> | ||||||
``` | ||||||
|
||||||
The user can also define how many layers of the detector they would like to see, what colour scheme they would like to use- 'ild' or leave blank for purple -and if they would like to hide any parts of the detector: | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
```bash | ||||||
python conversion_xml2gltf_autoConfig.py -cm <detector.xml> | ||||||
-d <maximum-depth-of-detector-layers> | ||||||
-c <default-colours> | ||||||
-hide <detector-parts-to-hide> | ||||||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#!/usr/bin/env python | ||
# coding: utf-8 | ||
|
||
from dd4hep import Detector | ||
import re | ||
from argparse import ArgumentParser | ||
import pprint | ||
import json | ||
|
||
def main(): | ||
parser = ArgumentParser() | ||
|
||
parser.add_argument( | ||
"--compact", help="DD4hep compact description xml", required=True | ||
) | ||
parser.add_argument( | ||
"--max_depth", help="Maximum traversal depth of the detector tree", default=10, type=int, | ||
) | ||
parser.add_argument( | ||
"--config_path", help="Location of produced config file", default='nothing', type=str, | ||
) | ||
parser.add_argument( | ||
"--hide_list", help="List of detector geometries that aren't shown", default='', type=str, nargs='+' | ||
) | ||
parser.add_argument( | ||
"--coloring", help="Default colours for detector (choose ild or leave blank)", default='', type=str | ||
) | ||
args = parser.parse_args() | ||
|
||
## Gets the detector geometry | ||
theDetector = Detector.getInstance() | ||
theDetector.fromXML(args.compact) | ||
start = theDetector.world() | ||
|
||
## Runs through the detector to make a tree dictionary of the detector parts | ||
detector_dict = tree(start, 0, args.max_depth) | ||
## Processes the detector tree to make a usable config file | ||
subPart_processed, hidden_children = post_processing(detector_dict, list(detector_dict.keys()), '|'.join(args.hide_list[0].split(", ")), args.coloring) | ||
## Produce a config.json file using the edited detector tree | ||
produce_config(subPart_processed, hidden_children, args.config_path) | ||
|
||
def process_name(raw_name): | ||
## Changes any numbers for parts of a detector into .* (which in regex can mean any ending) | ||
name = re.sub(r"\d+", ".*", raw_name) | ||
return name | ||
|
||
def add_ild_colors(subdetector): | ||
subdetector_dict = {"Tube": [1,0.7,0.5], | ||
"BeamPipe": [0,1,0], | ||
"Vac": [0,0,0], | ||
"VXD": [0.1,0.5,0.5], | ||
"FTD": [0.39,0.1,0.57], | ||
"BeamCal": [1,1,1], | ||
"SIT": [0.86,0.86,0.86], | ||
"SET": [0.86, 0.86, 0.86], | ||
"TPC": [0.96,0.95,0], | ||
"Ecal": [0.48,0.95,0], | ||
"Hcal": [0.76,0.76,0.19], | ||
"Yoke": [0.09,0.76,0.76], | ||
"Coil": [0.28,0.28,0.86], | ||
"Fcal": [0.67, 0.66, 0.67] | ||
} | ||
for s in subdetector_dict: | ||
find_subdetector = re.search(f'{s}', f'{subdetector}',re.IGNORECASE) | ||
if find_subdetector: return subdetector_dict[s] | ||
return [0.57,0.63,0.81] | ||
|
||
|
||
def tree(detElement, depth, maxDepth): | ||
## Creates a detector tree using the geometry while also being able to set a max depth that the config file reaches | ||
nd = {} | ||
depth += 1 | ||
children = detElement.children() | ||
for raw_name, child in children: | ||
if depth > maxDepth: | ||
tree(child, depth, maxDepth) | ||
else: | ||
dictionary = tree(child, depth, maxDepth) | ||
nd.update({raw_name: dictionary}) | ||
return nd | ||
|
||
def post_processing(obj, main_parts, hidden, coloring, subParts={}, sublist= [], hide_children= []): | ||
## Processes the tree dictionary to make a usable config file | ||
for k, v in obj.items(): | ||
if k in main_parts: | ||
## Look for hidden children that we want to add to the hidden_children list and ignore | ||
y = re.search(f'{hidden}', f'{k}', re.IGNORECASE) | ||
if y == None: | ||
## Removes envelopes from being featured in the final geometry | ||
sublist = [f'({k}_(?!envelope))\\w+|({k}(?!_))\w+'] | ||
outer_list = [] | ||
outer_list.append(sublist) | ||
outer_list.append(0.8) | ||
|
||
## Adds automatic ILD coloring if the user asks | ||
if coloring == "ild": | ||
color = add_ild_colors(k) | ||
outer_list.append(color) | ||
|
||
subParts.update({str(k): outer_list}) | ||
post_processing(v, main_parts, hidden, coloring, subParts, sublist) | ||
|
||
else: | ||
hide_children.append(f'{k}') | ||
sublist = [] | ||
post_processing(v, main_parts, hidden, coloring, subParts, sublist, hide_children) | ||
|
||
else: | ||
k_new = process_name(f"{k}\\w+") | ||
## The function ignores components with common names that can often be in multiple detectors: module, stave, layer... | ||
x = re.search("module|stave|layer|Calorimeter|component", k_new, re.IGNORECASE) | ||
if k_new not in sublist and x == None: | ||
sublist.append(f'{k_new}') | ||
post_processing(v, main_parts, hidden, coloring, subParts, sublist, hide_children) | ||
return subParts, hide_children | ||
|
||
def produce_config(subParts, hidden, config_path): | ||
## Create the final dictionary that will be converted into a config.json file | ||
final_dict = {"childrenToHide": hidden, | ||
"subParts": subParts, | ||
"maxLevel": 3} | ||
|
||
pprint.pprint(final_dict) | ||
with open(config_path, "w") as outfile: | ||
json.dump(final_dict, outfile, indent=4) | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
|
||
import argparse | ||
import ROOT | ||
import subprocess | ||
import os | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='Convert detector') | ||
parser.add_argument('-cm', '--compact_files', help='Compact file location(s)', | ||
default='', type=str) | ||
parser.add_argument('-cn_in', '--config_file_in', help='Json file of detector structure to be given', | ||
default='', type=str) | ||
parser.add_argument('-cn_out', '--config_file_out', help='Automatic json file of detector structure file path out', | ||
default='', type=str) | ||
parser.add_argument('-r_in', '--in_root', help='Input root file path (if a root file has already been obtained)', | ||
default='', type=str) | ||
parser.add_argument('-r_out', '--out_root', help='Converted root file path', | ||
default='', type=str) | ||
parser.add_argument('-g', '--out_gltf', help='Converted gltf file path', | ||
default='', type=str) | ||
parser.add_argument('-d', '--depth', help='Level of layers in detector to consider in the conversion', | ||
default=10, type=int) | ||
parser.add_argument('-c', '--color', help='Default colours for detector (choose ild or leave blank)', | ||
default='', type=str) | ||
parser.add_argument('-hide', '--hidden_children', help='Parts of the detector to be hidden', | ||
default=['thereisnodetectorparthere'], type=str, nargs='+') | ||
args = parser.parse_args() | ||
|
||
## Loop for multiple compact files (currently not working) | ||
##for cfile in args.compact_files: | ||
## For if both a root and config file are given | ||
if args.in_root and args.config_file_in: | ||
config_file, root_path = args.config_file_in, args.in_root | ||
|
||
## For if only a root file is given | ||
elif args.in_root and not args.config_file_in: | ||
config_file = automatic_config(args.config_file_out, args.compact_files, args.depth, args.color, args.hidden_children) | ||
root_path = args.in_root | ||
|
||
## For if only a config file is given | ||
elif not args.in_root and args.config_file_in: | ||
root_path = root_convert(args.compact_files, args.out_root, args.depth) | ||
config_file = args.config_file_in | ||
|
||
## For if neither file is given | ||
else: | ||
root_path = root_convert(args.compact_files, args.out_root, args.depth) | ||
config_file = automatic_config(args.config_file_out, args.compact_files, args.depth, args.color, args.hidden_children) | ||
|
||
gltf_convert(config_file, args.out_gltf, root_path) | ||
|
||
def root_convert(cfile, out_path, visibility): | ||
## Converts an xml file to root file | ||
print('INFO: Converting following compact file(s):') | ||
print(' ' + cfile) | ||
|
||
ROOT.gSystem.Load('libDDCore') | ||
description = ROOT.dd4hep.Detector.getInstance() | ||
description.fromXML(cfile) | ||
|
||
## Sets the number of layers visible in the root file | ||
ROOT.gGeoManager.SetVisLevel(visibility) | ||
ROOT.gGeoManager.SetVisOption(0) | ||
## Sets an automatic root path if one isn't given | ||
root_path = determine_outpath(out_path, cfile, 'root') | ||
ROOT.gGeoManager.Export(root_path) | ||
|
||
return root_path | ||
|
||
def automatic_config(config_out, cfile, depth, color, hide): | ||
## Creates an automatic configuaration file if one isn't given using the 'configfile_generator.py' | ||
## Determines automatic outpath of config file | ||
config_file = determine_outpath(config_out, cfile, "json") | ||
subprocess.run(["python", "configfile_generator.py", "--compact", f'{cfile}', '--max_depth', f'{depth}', '--config_path', f'{config_file}', '--hide_list', ', '.join(hide), '--coloring', f'{color}']) | ||
|
||
## Asks the user if they would like to exit the run to edit the automatic config file | ||
config_edit = input(f'Would you like to exit and edit the automatic cofiguration file {config_file}? [y/n]') | ||
program_questions(config_file, config_edit, "c") | ||
|
||
return config_file | ||
|
||
|
||
def gltf_convert(config, gltf, root): | ||
## Converts the root file into a gltf file | ||
## Determines the outpath of the gltf file if one isn't given | ||
gltf_path = determine_outpath(gltf, root, "gltf") | ||
subprocess.run(["node", ".", "-c", f'{config}', "-o", f'{gltf_path}', f'{root}']) | ||
|
||
## Asks the user if they would like to remove the root file | ||
rmv_file = input(f'Would you like to remove the {root} file? [y/n]') | ||
program_questions(root, rmv_file, 'r') | ||
|
||
def determine_outpath(out_path, file, ending): | ||
## Generates the automatic out_paths for the files if one isn't provided | ||
if out_path == '': | ||
counter = 0 | ||
slash_list = [] | ||
for i in file: | ||
counter += 1 | ||
if i == '/': slash_list.append(counter) | ||
if i == '.': dot = counter | ||
|
||
if not slash_list: | ||
path = f'../{ending}_files/{file[:dot-1]}.{ending}' | ||
else: | ||
last_slash = max(slash_list) | ||
if ending == 'json': path = f'../configs/{file[last_slash:dot-1]}.{ending}' | ||
else: path = f'../{ending}_files/{file[last_slash:dot-1]}.{ending}' | ||
else: path = out_path | ||
return path | ||
|
||
def program_questions(file, response, r_c): | ||
## Asks questions to user as described above | ||
while True: | ||
if response == 'y': | ||
if r_c == 'r': | ||
print(f'Removing {file} file') | ||
os.remove(file) | ||
break | ||
elif r_c == 'c': | ||
print('Exiting converter') | ||
exit() | ||
elif response == 'n': | ||
if r_c == 'r': | ||
print(f'{file} file kept') | ||
elif r_c == 'c': | ||
print('Producing gltf file:') | ||
break | ||
else: | ||
print("Incorrect response given (choose y/n)") | ||
response = input() | ||
|
||
if __name__ == '__main__': | ||
main() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.