Isolate source rays contributing to paths

The intention of this KB article is to demonstrate a programmatic solution to the problem illustrated below, where we wish to isolate the ray distribution at the source plane which ultimately spawns a particular raytrace path(s) of interest.  In other words, if you were to trace the rays for the path(s) of interest back to their origination points in the source plane, what would their spatial or angular distribution look like in object space?

To facilitate the discussion of this analysis, the model shown below has been contrived so that rays can sneak around a baffle through a mechanical opening and illuminate the detector plane.  An embedded script will be used to determine (a) which rays in the source plane spawned the path(s) of interest during the raytrace, and (b) isolate the source rays of interest in their initial state prior to the raytrace.  At the conclusion of the script execution, analyses may be performed on the source rays of interest.

You may be asking why FRED cannot perform this type of analysis without the application of an embedded script.  Although FRED can keep track of a ray's history, and the path that each ray takes through the system, it does NOT keep track of every single parameter associated with the rays at the time of each intersection event.  For example, although FRED knows the ray's (x,y,z) intersection position for each event during the raytrace, FRED does not track the ray's (a,b,c) direction vector or its flux at each intersection event.  Since the goal of this particular analysis is to determine the spatial and directional power distributions of a specific ray subset in the source plane, which requires the ray direction vector and flux information, an embedded script is used to extract the necessary information.

A Comment on Ray Buffers

Before describing the embedded script implementation specifically, we should clarify an important concept used in the script called "ray buffers".  When working in FRED's GUI, the ray data is stored in the "main ray buffer".  Any raytracing or analyses operations are performed on the ray data that is stored in the main ray buffer.  However, through the scripting language (and only the scripting language), it is possible to add additional ray buffers, move ray data between buffers, designate specific buffers to become the "main ray buffer", etc.  In the context of our current application, we will make a copy of the starting source rayset (prior to raytracing) and place these duplicate rays into their own ray buffer.  In this way, we will be able to access all of the starting ray parameters for every ray in the source definition.

Embedded Script Overview

With the goal of recovering the subset of the starting source rays that give rise to the path(s) of interest in the system, the embedded script will take the following steps:

  1. Generate the starting source rays and make a copy of them.  Place the copied rays into their own temporary ray buffer for later use.
  2. Perform an Advanced Raytrace, keeping track of raytrace paths through the system.
  3. From the raytrace path data, identify the starting source ray ID #s that ultimately generate the raypaths of interest.
  4. Activate the temporary ray buffer from step 1 and isolate the source rays identified in step 3

At the conclusion of the script execution, the only rays that are active are the subset of the starting source rays that ultimately generated the raytrace paths of interest.  The user can then perform any desired analyses or data extraction on this rayset using the GUI.

Embedded Script Details

The script begins with the following code.  In the Document Preparation section, a custom user-defined function named DeleteExtraBuffers() is called that simply loops over any extra ray buffers and deletes them before proceeding with the rest of the script.  In general, when working with ray buffers in the script language, making sure to "clean up" extra ray buffers at the start of your script is good practice.  Next, the script creates the rayset for all active sources and immediately dimensions an array of Booleans, srcIds, which is the same size as the total ray count in the source.  The srcIds array will be applied later on in the script to track which source ray ID numbers are ultimately of interest, where the array index value will map to a corresponding ray ID # and the array value (True or False) will indicate whether the ray is of interest or not. 

Sub Main

    'Document preparation

    'Generate the source rays but don't trace them
    Dim srcIds() As Boolean
    ReDim srcIds(GetRayCount()-1) 'We'll use this later on, but BASIC initializes Booleans to False

The next block of code calls a custom function, CopyAllRaysToBuffer(), that makes a duplicate of the starting rayset and stores them in their own temporary ray buffer.  The ray buffer index where these rays are stored is returned by the function call and stored in the variable, srcBuf.  Having a reference to this ray buffer index value allows us to make this the active ray buffer later on in the script when we want to access the source ray data.

    'Lets make a copy of the source rays and put them away in their
    'own buffer for later use
    Dim srcBuf As Long
    srcBuf = CopyAllRaysToBuffer()

After saving a copy of the starting source rays into their own separate buffer, we proceed with an Advanced Raytrace using the main ray buffer.  Note that we are keeping track of raytrace paths by setting the rayPaths member variable to True and we are tracing the existing rays in the buffer by setting the traceActiveSources member to False (i.e. do NOT re-generate starting source rayset, just use the rays that already exist).

   'Now lets go ahead and trace the rays with paths
    InitAdvancedRaytrace( tAdv )
    tAdv.draw               = False
    tAdv.traceActiveSources = False 'use our existing rays
    tAdv.rayPaths           = True
    tAdv.rayHistory         = True
    AdvancedRaytrace( tAdv )

Now, at this point, all of the rays have been traced through the system and followed whatever paths are supported by the geometry and surface properties.  Of all the paths in the system, we are only interested in the raytrace paths which (a) ended on the detector surface and (b) interacted with a particular surface of interest in the model.  Once all paths meeting this requirement have been identified, we can identify each individual ray on these paths and, from each ray, identify which starting source ray ID # spawned the ray during the raytrace.  The code that performs this source ray ID extraction based on path data is contained in the custom function, GetSourceRayIDs, which takes three input arguments.  The first argument, det, is the node number of the detector surface, the second argument, soi, is the node number of the surface of interest that the path must have interacted with during the raytrace, and the third argument, srcIds(), will be populated with True/False values indicating whether a source ray ID # spawned any of the identified paths of interest.

    'For rays that followed paths interacting with a surface of interest
    'and ending on the detector, lets get their associated starting source ray IDs
    Dim det As Long, soi As Long, success As Boolean
    det = FindFullName( "Geometry.Detector.Surface" )
    soi = FindFullName( "Geometry.Housing.Aperture.Notch.Surface" )
    success = GetSourceRayIDs( det, soi, srcIds() )
    If Not(success) Then
        Print "Did not find any paths of interest.  Stopping script."
    End If

The final step in the Main subroutine is to set active the ray buffer that contains the copy of the starting source rays.  With this buffer active, a ray loop is started that sets each ray active or inactive based on the True/False value of the srcIds array.

    'Now that we know what source rays we're interested in, lets switch to our other
    'ray buffer and isolate the source rays of interest
    Dim curidx As Long
    SetActiveRayBufferIndex( srcBuf )
    For curidx = 0 To UBound( srcIds )
        SetRayActive( curidx, srcIds(curidx) ) 'srcIds(curidx) is either True or False
    'Thats it.  The source rays that generated the paths of interest are active at the source
    'plane location. Proceed with analyses!
    Print ""
    Print "Isolated source rays for path(s) of interest."

End Sub


Consider the image of the system at the start of this article, where the rays that propagate along the path(s) of interest appear to leave from the lower portion of the source plane traveling in the +y,+z direction, where they reflect off the housing and pass through the mechanical gap between the baffle and the housing and proceed out to the detector.

Right mouse click on the embedded script and select, "Run an embedded script", and you should see some information printed to the output window regarding the paths that were identified as being of interest.  The path numbers reported will vary from run to run and will be different for your analysis.  In this case, paths 14 and 43 were identified as having passed through the mechanical gap and arriving at the detector and the source rays resulting in those paths were isolated.

Now, using the GUI, we call Analyses > Irradiance Spread Function and use the "Source Plane" analysis surface in order to recover the spatial power distribution in the source plane contributing to the paths of interest.  Is indicated in the image of the 3D model view, the rays contributing to the paths in question originate from the lower portion of the source aperture.

Next, we call Analyses > Intensity on Polar Grid and use the "Source Plane Intensity" directional analysis entity to view the directional power distribution.  The intensity plot below shows that the source rays contributing to the paths of interest propagate into a relatively small angle range that is inclined at about +27 degrees along the Y axis (the +Z axis is 0 degrees polar).


This article has demonstrated a script functionality that allows the recovery of ray data at times/locations when FRED doesn't keep track of it natively.  The script demonstrates many techniques used in a variety of custom analyses, including ray buffer loops, extraction of ray attributes, ray buffer manipulations, and path event searching.

Example FRED File: FindSourceRaysSpawningRaypath.frd

Still need help? Contact Us Contact Us