1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
from mcstasscript.instrument_diagram.connections import ConnectionList
from mcstasscript.instrument_diagram.arrow import Arrow
def generate_Union_arrows(components, component_box_dict, box_names, component_categories, color=None):
"""
Generate Arrow objects related to use of Union components
Currently supports processes, materials, geometries and master. Can be
expanded to also support loggers, abs_loggers and conditionals.
"""
connections = ConnectionList()
process_names = []
material_names = []
geometry_names = []
simulated_geometry_names = []
abs_loggers = []
loggers = []
conditionals = []
master_names = []
geometry_activation_counters = {}
for component in components:
category = component_categories[component.component_name]
if category == "union" or True:
if "_process" in component.component_name:
# Process component
process_names.append(component.name)
elif component.component_name == "Union_make_material":
# Make material component
material_names.append(component.name)
process_string = component.process_string
if not isinstance(process_string, str):
continue
processes = process_string.strip('"').split(",")
for process in processes:
if process not in process_names:
print("Didn't find process of name '" + process + "'")
print(process_names)
else:
origin = component_box_dict[process]
connections.add(origin, component_box_dict[component.name])
elif "material_string" in component.parameter_names:
# Geometry
geometry_names.append(component.name)
if component.number_of_activations is not None:
try:
# If a number is given, it can be used directly
number_of_activations = int(component.number_of_activations)
except:
# If a variable or parameter is used, it can't be known ahead of time, assume 1
number_of_activations = 1
else:
number_of_activations = component.parameter_defaults["number_of_activations"]
geometry_activation_counters[component.name] = number_of_activations
if component.material_string is not None:
simulated_geometry_names.append(component.name)
if isinstance(component.material_string, str):
material = component.material_string.strip('"')
if material not in material_names:
if material not in ["Vacuum", "vacuum", "Exit", "exit"]:
print("Didn't find material of name '" + material + "'")
print(material_names)
else:
origin = component_box_dict[material]
connections.add(origin, component_box_dict[component.name])
if isinstance(component.mask_string, str):
masks = component.mask_string.strip('"').split(",")
for mask in masks:
if mask not in geometry_names:
print("Didn't find geometry target of name '" + mask + "'")
print(geometry_names)
else:
target = component_box_dict[mask]
connections.add(component_box_dict[component.name], target)
elif "_logger" in component.component_name:
if "_abs_logger" in component.component_name:
# Absoption logger
abs_loggers.append(component.name)
abs_logger = True
else:
# Scattering logger
loggers.append(component.name)
abs_logger = False
target_geometry = component.target_geometry
if isinstance(target_geometry, str):
geometries = target_geometry.strip('"').split(",")
for geometry in geometries:
if geometry not in simulated_geometry_names:
print(component.name)
print("Didn't find geometry of name '" + geometry + "'")
print(simulated_geometry_names)
else:
origin = component_box_dict[geometry]
connections.add(origin, component_box_dict[component.name])
if abs_logger:
# Abs loggers do not have target_process, as they target absorption
continue
target_process = component.target_process
if isinstance(target_process, str):
processes = target_process.strip('"').split(",")
for process in processes:
if process not in process_names:
print(component.name)
print("Didn't find process of name '" + process + "'")
print(process_names)
else:
origin = component_box_dict[process]
connections.add(origin, component_box_dict[component.name])
elif "target_loggers" in component.parameter_names:
# Conditional
conditionals.append(component.name)
target_loggers = component.target_loggers
if isinstance(target_loggers, str):
loggers = target_loggers.strip('"').split(",")
for logger in loggers:
if logger not in loggers + abs_loggers:
print(component.name)
print("Didn't find logger with name '" + logger + "'")
print(loggers, abs_loggers)
else:
target = component_box_dict[logger]
connections.add(component_box_dict[component.name], target)
elif component.component_name == "Union_master":
# Master
master_names.append(component.name)
for geometry in simulated_geometry_names:
if geometry_activation_counters[geometry] > 0: # May need to account for floating point precision
# Only include if activation counter for this geometry is still positive
geometry_activation_counters[geometry] -= 1
origin = component_box_dict[geometry]
connections.add(origin, component_box_dict[component.name])
connections.distribute_lane_numbers(box_names=box_names)
arrows = []
for connection in connections.get_connections():
origin = connection.origin
target = connection.target
lane = connection.lane_number
arrow = Arrow(origin, target, lane=lane, kind="Union")
arrow.set_sub_lane(2)
if color is None:
arrow.color = "green"
else:
arrow.color = color
if target.name in master_names:
arrow.set_linestyle("--")
arrows.append(arrow)
return arrows
|