ZRD ray database processing in MATLAB, why does the output power changes magnitude?
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!
Page 1 / 1
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:
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.
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 n 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 nr] = 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);
% start processing zrdReader.RunAndWaitForCompletion(); res = zrdReader.GetResults();
if ~isempty(res) ProcessZRD1(res, 1000000); end
zrdReader.Close();
end
function n] = 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(p'Rays read: ', num2str(totalRaysRead)]); %disp(p'Segments read: ', num2str(totalSegRead)]); disp('The power array formed is:'); disp(powArray); disp(p'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.
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.
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.