Solved

ZRD ray database processing in MATLAB, why does the output power changes magnitude?

  • 15 February 2023
  • 7 replies
  • 199 views

Hi all!

I am processing ZRD ray databases in Matlab using batch processing improved method. However, the intensity reading appears to be incorrect, as I expected to see the total intensity in microns based on the trends in the original files. Is there anything done to convert the values, or is there something I am missing at some point in the processing? Note that I used the sample Matlab file provided in the tutorial with some changes to support my own data.

Here is the output power calculated!

icon

Best answer by MichaelH 21 February 2023, 17:58

View original

7 replies

Userlevel 7
Badge +2

Hi Priscilla,

 

Can you post the link to the method you are refering to? Also, do you have a sample file with instructions to reproduce the issue? That would be really helpful for troubleshooting.

Take care,


David

Hi David,

 

Thank you for responding. Yes the files are referring are found here:

https://support.zemax.com/hc/en-us/articles/1500005576882-Batch-Processing-of-Ray-Trace-Data-using-ZOS-API-in-MATLAB-or-Python

 

And here is the sample zrd file I am processing using the code provided in the link above. I have uploaded the txt version since ZRD file is too big to be uploaded.

 

Userlevel 7
Badge +2

Hi Priscilla,

 

It’ll be hard to troubleshoot like this, at least for me. I have no idea what your code is like, and your file seems quite complex. Are you refering to this particular example: MATLAB_ZRDLoaderFull.m or PythonNET_ZRDLoaderFull.py?

How can you judge the trend in the file? If you trace millions of ray, each with a power in uW, and they all add up on the detector, then you get Watts.

Any chance you can make a simple file that demonstrate the issue and also includes your code?

Take care,


David

Hi David,

 

Thank you for clarifying. I apologize for not attaching the codes to read the file, as I stated earlier I was unable to attach the zos file unless I copy and paste here. I agree that we can convert uW to Watts, but in my case, the transmitted power is 1W, and we should not expect to receive more than this while the computed power is about 7.6169, which made me doubt the process. Unfortunately, I was unable to debug my code.

 

Here are the MATLAB codes used:

function [ r ] = MATLABRayDatabaseExample_improved_4( args )

if ~exist('args', 'var')
args = [];
end

% Initialize the OpticStudio connection
TheApplication = InitConnection();
if isempty(TheApplication)
% failed to initialize a connection
r = [];
else
try
r = BeginApplication(TheApplication, args);
CleanupConnection(TheApplication);
catch err
CleanupConnection(TheApplication);
rethrow(err);
end
end
end

function [r] = BeginApplication(TheApplication, args)

import ZOSAPI.*;

TheSystem = TheApplication.PrimarySystem;

% Add your custom code here...


for k = 1:20
fname = sprintf('Clear_weather_Simulation_zmx_%d',k);

samplesDir = TheApplication.SamplesDir;
fileDir = System.IO.Path.Combine(samplesDir, 'Non-sequential', 'Simulations');
lensFile = System.IO.Path.Combine(fileDir, [fname,'.zmx']);
zrdFile = System.IO.Path.Combine(fileDir, [fname,'.zrd']);

ReadZRDFile(TheSystem, lensFile, zrdFile);

r = [];

end
end


function [] = ReadZRDFile(sys, lensFile, zrdFile)

sys.LoadFile(lensFile, false);

if ~isempty(sys.Tools.CurrentTool)
sys.Tools.CurrentTool.Close();
end

zrdReader = sys.Tools.OpenRayDatabaseReader();
zrdReader.ZRDFile = zrdFile;
zrdReader.Filter = '';

% start processing
zrdReader.RunAndWaitForCompletion();
res = zrdReader.GetResults();

if ~isempty(res)
ProcessZRD1(res, 1000000);
end

zrdReader.Close();

end

function [] = ProcessZRD1(res, maxRays)
% Directly use the ZRD Reader API without the .NET helper DLL
import ZOSAPI.Tools.RayTrace.*;

% This method assumes the helper dll is in the .m file directory.
p = mfilename('fullpath');
[path] = fileparts(p);
p = strcat(path, '\', 'ZRDLoaderFull.dll');
NET.addAssembly(p);
import ZRDLoaderFull.*

tic();

% Attach the helper class to the ray database reader
dataReader = ReadZRDData(res);
% Configure the maximum number of segments to read at one time.
% Note that this is a tradeoff between speed and memory usage
maxSeg = 1000000;
zrdData = dataReader.InitializeOutput(maxSeg);

isFinished = false;
totalSegRead = 0;
totalRaysRead = 0;
pow = 0.0;
global powArray
powArray = [];
global PL
PL = [];
while ~isFinished
% fill the next block of data
readSegments = dataReader.ReadNextBlock(zrdData);
if readSegments == 0
isFinished = true;
else
totalSegRead = totalSegRead + readSegments;
% Note - MATLAB arrays 1-base, however .NET arrays are 0-based, so we have to be careful...
totalRaysRead = int32(zrdData.RayNumber(readSegments-1));

% retrieve whatever data is needed
intensityData = zrdData.Intensity.double;
%xData = zrdData.X.double;

pow = pow + sum(intensityData(1:readSegments));

powArray = [powArray pow];

pathLoss = 10*log10(pow);
PL = [PL pathLoss];

end

if totalRaysRead >= maxRays
isFinished = true;
end
end
toc();

%disp(['Rays read: ', num2str(totalRaysRead)]);
%disp(['Segments read: ', num2str(totalSegRead)]);
disp('The power array formed is:');
disp(powArray);
disp(['Total power: ', num2str(pow)]);
disp('The power array in DB is:');
disp(PL);

end

function app = InitConnection()

import System.Reflection.*;

% Find the installed version of OpticStudio.
zemaxData = winqueryreg('HKEY_CURRENT_USER', 'Software\Zemax', 'ZemaxRoot');
NetHelper = strcat(zemaxData, '\ZOS-API\Libraries\ZOSAPI_NetHelper.dll');
% Note -- uncomment the following line to use a custom NetHelper path
% NetHelper = 'C:\Users\michael.humphreys\Documents\Zemax\ZOS-API\Libraries\ZOSAPI_NetHelper.dll';
% This is the path to OpticStudio
NET.addAssembly(NetHelper);

success = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize();
% Note -- uncomment the following line to use a custom initialization path
% success = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize('C:\Program Files\Zemax OpticStudio\');
if success == 1
LogMessage(strcat('Found OpticStudio at: ', char(ZOSAPI_NetHelper.ZOSAPI_Initializer.GetZemaxDirectory())));
else
app = [];
return;
end

% Now load the ZOS-API assemblies
NET.addAssembly(AssemblyName('ZOSAPI_Interfaces'));
NET.addAssembly(AssemblyName('ZOSAPI'));

% Create the initial connection class
TheConnection = ZOSAPI.ZOSAPI_Connection();

% Attempt to create a Standalone connection

app = TheConnection.CreateNewApplication();
if isempty(app)
HandleError('An unknown connection error occurred!');
end
if ~app.IsValidLicenseForAPI
HandleError('License check failed!');
app = [];
end

end

function LogMessage(msg)
disp(msg);
end

function HandleError(error)
ME = MXException(error);
throw(ME);
end

function CleanupConnection(TheApplication)
% Note - this will close down the connection.

% If you want to keep the application open, you should skip this step
% and store the instance somewhere instead.
TheApplication.CloseApplication();
end

 

 

 

Thank you in advance for your time.

Priscilla.

Userlevel 7
Badge +2

Hi Priscilla,

 

If you want to attach your file, please create an archive (File..Create Archive) and embed it into a *.zip before uploading it.

Before I spend some time looking at your code, what does the Analyze..Detector Viewer say about the total power? Also, are your detectors material set to ABSORB? If the detector material is not ABSORB, it could be that a ray goes through the detector (its energy is recorded) then gets reflected elsewhere and comes back to the detector and is detected a second (or more) times.

Take care,

 

David

Hi David,

Thank you for your response,

Yes my detector is set to ABSORB rays. And the detector viewer shows the total power 1.2817e-3 Watts as shown in figure below.

 

Userlevel 6
Badge +2

Hi Priscilla,

I think the DLL is working fine and as-intended but you’re not applying the proper Filter String to only look at the intensity hitting your detector.  Each segment of a NSC ray has intensity and you’re summing all the individual segment’s intensity.  On line 58, you have a blank Filter with zrdReader.Filter = ''; and on line 111, you are getting all the intensity values for all the segments with intensityData = zrdData.Intensity.double;.  The zrdData.Intensity is the same array of data as looking at Intensity Column in the Ray Database Viewer (highlighted in yellow below for the Double Gauss 28 degree field.zmx converted to non-sequential mode):

You can see that for the on-axis chief ray, the total intensity for all the segments is 11.618W but the intensity for the last segment hitting Detector 20 (H20 filter string) is only 0.934W.  The same is true for the on-axis marginal ray with a total intensity for all the segments of 11.354W but the intensity for the last segment is only 0.887W.

If you either apply a filter for the HitObj array passing back from the ZRDLoaderFull.dll or using a Filter String when originally creating the ZRD file, then you should get the intensity you’re looking for.

Reply