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

demonstration beam path files from Ron #564

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

RonHildebrandt
Copy link
Contributor

@RonHildebrandt RonHildebrandt commented Feb 28, 2025

What this is

This is a demonstration example, how a beam path description by NXbeam_device could look like

What this is not

A working code, which automatically performs the beam path description for arbitrary files with a standardized output format.

Content

The content are 3 folders, which shows different examples of a Beam Path description via directed graphs. This was done in python, via networkx.

1. example_beam_path_interferometer

The folder contains a python file to create a .nxs file (interferometer_v4.py) called interferometer_v4.nxs. The script calculate_with_transfer_matrix_v4_adjusted_labels.py will use interferometer_v4.nxs as input, to calculate a beam path. See this figure:

output_example_image1

All NXbeam_device elements have a transfermatrix table assigned. Arbitrary values are given to describe parameters such as beam attenuation and beam divergence. The output of these transfermatrix calculations is shown in this figure:

transfer_matrix_table

In this case, a subpath was calculated only. From: beam03 to beam07 to final_beam_detector and from BS1_to_Mirror_1_Beam to beam05 to final_beam_detector. The subpath development was done, as this is most probably only of relevance for real applications (power measured before and after an element. Only this can be compared. The desciption of the whole setup is not useful (error too large)). NXbeam entries, which maybe have to be generated by the program, are added to the NeXus file. A new output is created named interferometer_v4_mod.nxs.

2. example_contraction_of_nodes:

The folder shows an example, how the interferometer can be contracted, by using a the group field from NXbeam_device. In this way, a simplified version of the setup can b

output_example_image
e displayed. This is shown in this figure:

This will be useful, for setup with several hundets of elements, as some components are just a frequency doubling of an input laser. This eases the visualization. In this example, the interferometer components (mirros and beamsplitters) are summed up as a single element.

3. example_beam_path_raman_setup:

** THIS EXAMPLE WAS MOVED TO pynxtools-raman see here: FAIRmat-NFDI/pynxtools-raman#32

The algorithm:

Note: There is a lot of hardcoding involved, and various things are not generalized. Most probably, many functions from pynxtools could be used (i.e. to filter out all NXbeam_device entries in the NeXus file)

  1. Draw the graph network
  • Read the NeXus file
  • Create a directed networkx graph (nx.DiGraph())
  • Identify the NXbeam_devices in the NeXus file with nodes of the networkx graph
  • Determine the edges from the nodes of the networkx. This is done via the previous_devices field in NXbeam_device.
  • Determine the spatial positions of the beam devices from NXtransformations in NXbeam_device.
  • Determine the spatial positons of the beams (graph edges), by averaging the positions of the two optical elements (graph nodes).
  • If the directed network graph exisists, the start and end point (roots and leaves) can be determined easily. This is related to the beam direction.
    Note, that the beam direction is revered, as only the previous element of an optical beam is described.
  • To be able to work with the directed graph, ALL beams between ALL optical elements have to be present.
    Beams, which are not defined in the NeXus file (as the user only knows properties of the beam incident to the sample),
    have to be created. These are named: NXS_Beam_1.
  • The created beams (edges) are added to the graph (see: add_beam_names_to_edges(G, all_edges, opt_beams_at_path, NeXus_File_Name, instr))
  • The graph can be drawn now. As here only 2D information is used, a simple standard matplotlib plot is used.
  1. Calculate the beam properties by transfer matrix tables (TMT)
  • Search the file for optical elements, which have TMT defined.
  • Extract the transfermatrix table elements to a structure (dictionary)
  • Determine all avaialble beam paths. For the interferometer, there are in total 4 different beam paths (see: all_paths.extend(paths)).
  • For the example, the beam path calculation is limited to graphs from the node n2 to n6 and n7 (see: all_paths = list(nx.all_simple_paths(G, source=source_node_list[0], target=target_node_list[0]))).
  • Then, iterate over all pathes, with a given starting beam state, and multiply the transfer matrix tables.
    Iterate along the graph edges (beam states), and use the nodes (transfer matricies) to calculate the next edge (beam state).
  1. Create new NeXus file with added beam elements
  • Create copy of the input nexus file
  • Add the beam entries to the NeXus file
  • Possibly define the number of the beam entries, by the order of the edges.

Note for testing the scripts:
This was developed via Spyder on Windows 10. On my Linux system, the interactive graphs did now show up, as I did not invest any time to solve this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant