Skip to content

Commit

Permalink
Merge pull request #188 from tangkong/mnt_malformed_device_handling
Browse files Browse the repository at this point in the history
MNT: skip processing device if branches are not specified
  • Loading branch information
tangkong authored Apr 10, 2024
2 parents 22ec6aa + d8823b9 commit bbb1f63
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
188 mnt_malformed_device_handling
#################################

API Changes
-----------
- N/A

Features
--------
- N/A

Bugfixes
--------
- N/A

Maintenance
-----------
- Remove hard failure when a lightpath-active device is malformed. Instead of throwing an
exception, simply omit it from the facility graph
- Trim beam paths before BeamPath objects are created, when device names are gathered into paths

Contributors
------------
- tangkong
71 changes: 42 additions & 29 deletions lightpath/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,11 @@ def load_facility(self):
for branch_set in (res.metadata.get('input_branches', []),
res.metadata.get('output_branches', [])):
if branch_set is None:
raise ValueError(
f'device {res.item.name} has no branch information, '
logger.warning(
f'device ({res.item.name}) missing branch information, '
'check to make sure your happi database is '
'correctly implementing its container.')
break
for branch in branch_set:
branch_dict.setdefault(branch, set()).add(res)

Expand All @@ -146,7 +147,7 @@ def load_beamline(self, endstation: str):
consider part of the path.
Loads valid beampaths into the LightController.beamlines
attribute for latedr access.
attribute for later access.
Parameters
----------
Expand All @@ -165,18 +166,46 @@ def load_beamline(self, endstation: str):
# Find the paths from each source to the desired line
for src in self.sources:
try:
if nx.has_path(self.graph, src, branch):
found_paths = nx.all_simple_paths(self.graph,
source=src,
target=branch)
paths.extend(found_paths)
else:
logger.debug(f'No path between {src} and {branch}')
path_exists: bool = nx.has_path(self.graph, src, branch)
except NodeNotFound:
logger.debug(f'Either source {src} or target {branch} '
'not found.')
path_exists = False

if path_exists:
found_paths = nx.all_simple_paths(self.graph,
source=src,
target=branch)

# Trim beamline based on z-positions
if isinstance(end_branches, dict):
new_paths = list()
for found_path in found_paths:
end_z = end_branches[branch]
if end_z is not None:
# Only filter internal devices
truncated_path = [
name for name in found_path[1:-1]
if self.graph.nodes[name]['md'].res['z'] < end_z
]
truncated_path.append(found_path[-1])
truncated_path.insert(0, found_path[0])
new_paths.append(truncated_path)
else:
new_paths.append(found_path)

paths.extend(new_paths)
elif isinstance(end_branches, list):
paths.extend(found_paths)
else:
raise TypeError('config is incorrectly formatted '
f'(found mapping from {endstation} to '
f'{type(end_branches)}).')

self.beamlines[endstation] = paths
else:
logger.debug(f'No path between {src} and {branch}')

self.beamlines[endstation] = paths

def get_paths(self, endstation: str) -> list[BeamPath]:
"""
Expand All @@ -200,7 +229,7 @@ def get_paths(self, endstation: str) -> list[BeamPath]:
return paths

# create the BeamPaths if they have not been already
end_branches = self.beamline_config[endstation]
# end_branches = self.beamline_config[endstation]
filled_paths = []
for path in paths:
subgraph = self.graph.subgraph(path)
Expand All @@ -213,23 +242,7 @@ def get_paths(self, endstation: str) -> list[BeamPath]:
minimum_transmission=self.min_trans
)

if isinstance(end_branches, dict):
# access the last z for this branch
# if end_branches is Dict[BranchName, end_z], grab last
# allowable z with the branch name (last node in path)
last_z = end_branches[path[-1]]
if last_z:
# append path with all devices before last z
filled_paths.append(bp.split(last_z)[0])
else:
filled_paths.append(bp)
elif isinstance(end_branches, list):
# end_branches is a simple list, no splitting needed
filled_paths.append(bp)
else:
raise TypeError('config is incorrectly formatted '
f'(found mapping from {endstation} to '
f'{type(end_branches)}).')
filled_paths.append(bp)

self.beamlines[endstation] = filled_paths
return filled_paths
Expand Down

0 comments on commit bbb1f63

Please # to comment.