Skip to main content
Solved

When running batch ray trace inside a loop in C#, ReadNextResultFull fails after first iteration


alexander_dumont

Hello fellow Zemax ZOS-API users!

 

I’m getting my hands dirty with the ZOS-API, and I’m currently running a C# code to allow me to use batch ray trace. This reproduces my  input object onto my output image plane very nicely. However, I then tried to put this into a for loop over the range of thicknesses I want to conisder for one eleemnt in my system. I’m using directpol, and the addrays and readnextresults and ReadNextResultFull, and the method runs perfectly fine on the first lop iteration, but then fails for the concurrent lops. I tried to run the program by putting the loop inside the C# code and by calling it from an external program (MATLAB using system command) but in both cases, the success line fails after the first iteration, even though in MATLAB I am asking for a brand new instance of the C# code. to run. So I am stuck running it one parameter at a time, which is not what I want to do. Anyone else facing this problem?

 

Here is a copy of the relevant part of my C# file:

var z_offset_mm = new double[] { 1 };

            foreach (var z in z_offset_mm)
            {
                // Create the initial connection class
                ZOSAPI_Connection TheConnection = new ZOSAPI_Connection();

                // Attempt to create a Standalone connection
                IZOSAPI_Application TheApplication = TheConnection.CreateNewApplication();
                if (TheApplication == null)
                {
                    HandleError("An unknown connection error occurred!");
                    return;
                }

                // Check the connection status
                if (!TheApplication.IsValidLicenseForAPI)
                {
                    HandleError("Failed to connect to OpticStudio: " + TheApplication.LicenseStatus);
                    return;
                }
                if (TheApplication.Mode != ZOSAPI_Mode.Server)
                {
                    HandleError("User plugin was started in the wrong mode: expected Server, found " + TheApplication.Mode.ToString());
                    return;
                }

                //open the system
                IOpticalSystem TheSystem = TheApplication.PrimarySystem;
                TheSystem.LoadFile(model, false);

                ILensDataEditor TheLDE = TheSystem.LDE;

                //first surface is dummy that we can alter thickness
                TheLDE.GetSurfaceAt(1).Thickness = z;

                //move to center wavelength and delete all other wavelengths if any 
                ZOSAPI.SystemData.IWavelengths sysWave = TheSystem.SystemData.Wavelengths;
                var nW = sysWave.NumberOfWavelengths;
                for (int i = 1; i <= nW; i++)
                {
                    try
                    {
                        sysWave.RemoveWavelength(i);
                    }
                    catch
                    {
                        Console.WriteLine("no more wavelengths");
                    }
                }
                var w = 0.405;
                sysWave.GetWavelength(1).Wavelength = w;

                // apply filter coating to these surfaces
                int index_wavelength = centerWavelength.FindIndex(a => a == w);
                for (int i = 10; i <= 14; i++)
                {
                    TheSystem.LDE.GetSurfaceAt(i).Coating = filters[index_wavelength];
                }

                // set up batch ray to ressemble what we have physically for the reference target 
                //load image thats the right size, so that each pixel represents a 0 for dark pixel, or a 1 for light pixel
                var l = 11;//mm for the image height and width
                var n = 3036/10; //number of pixels for image, take it down to a tenth the pixels otherwise this is going to take forever

                var xl = linspace(-l / 2, l / 2, n);
                var yl = linspace(-l / 2, l / 2, n);

                //read mask csv 
                var path = "C:\\Users\\AlexanderDumont\\OneDrive - Cytoveris Inc\\Documents\\R&D\\Reference Checks Analysis\\mask.csv";
                var listPixelsMask = new List<List<int>>();
                string[] lines = System.IO.File.ReadAllLines(path);
                foreach (string line in lines)
                {
                    string[] columns = line.Split(',');
                    var colInt = Array.ConvertAll(columns,int.Parse);
                    listPixelsMask.Add(colInt.ToList());
                }

                // Set up Batch Ray Trace
                ZOSAPI.Tools.RayTrace.IBatchRayTrace raytrace = TheSystem.Tools.OpenBatchRayTrace();
                int nsur = TheSystem.LDE.NumberOfSurfaces;
                var dir_x = linspace(-.1f, .1f, 10);
                var dir_y = linspace(-.1f, .1f, 10);
                int max_rays = n * n * dir_x.Length * dir_y.Length;
                //count up all positions and  angles to lauch from
                var c = 0;
                for (int i = 0; i < xl.Length; i++)
                {
                    for (int j = 0; j < yl.Length; j++)
                    {
                        if (listPixelsMask[i][j] > 0)
                        {
                            //then we have surface to launch from so proceed
                            for (int dx = 0; dx < dir_x.Length; dx++)
                            {
                                for (int dy = 0; dy < dir_y.Length; dy++)
                                {
                                    c++;
                                }
                            }
                        }
                    }
                }
                Console.WriteLine("# of rays simulated in batch trace: " + c);

                var directPolData = raytrace.CreateDirectPol(c, ZOSAPI.Tools.RayTrace.RaysType.Real, 1, 0, 0, 0, 0, nsur-1);

                List<double[]> inputParameters = new List<double[]>();

                for (int i = 0; i < xl.Length; i++)
                {
                    for(int j = 0;j < yl.Length; j++)
                    {
                        if (listPixelsMask[i][j] > 0)
                        {
                            //then we have surface to launch from so proceed
                            for (int dx = 0; dx < dir_x.Length; dx++)
                            {
                                for (int dy = 0; dy < dir_y.Length; dy++)
                                {
                                    //does ray hit lens, if not then dont consider it 
                                    var x = xl[i];
                                    var y = yl[j];
                                    //we have an angle relative to the vertical position
                                    var vector_direction = new double[] { dir_x[dx], dir_y[dy] , 1 };
                                    vector_direction = vector_direction.Select(item => item*item).ToArray();
                                    var vector_sum = vector_direction.Sum();
                                    vector_direction = vector_direction.Select(item=>item / vector_sum).ToArray();
                                    //collect input data
                                    inputParameters.Add(new double[] { xl[i], yl[j], 0, vector_direction[0], vector_direction[1], vector_direction[2] });
                                    //add to batch ray trace 
                                    directPolData.AddRay(0, xl[i], yl[j], 0, vector_direction[0], vector_direction[1], vector_direction[2]);
                                }
                            }
                        }
                    }
                }
                //save input parameters to file 
                var inputFile = @"C:\\Users\\AlexanderDumont\\OneDrive - Cytoveris Inc\\Documents\\R&D\\Reference Checks Analysis\\input.txt";
                using (var writer = new StreamWriter(inputFile))
                {
                    foreach(var item in inputParameters)
                    {
                        foreach(var col in item)
                        {
                            writer.Write(col + ",");
                        }
                        writer.WriteLine();
                    }
                }
                raytrace.RunAndWaitForCompletion();
                // Read batch raytrace and save results
                directPolData.StartReadingResults();
                int rayNumber, ErrorCode, vignetteCode;
                double xo, yo, zo, lo, mo, no, exr, exi, eyr, eyi, ezr, ezi, intensity;
                bool success;

                success = directPolData.ReadNextResultFull(out  rayNumber, out  ErrorCode, out  vignetteCode, out  xo, out  yo, out  zo, out  lo, out  mo, out  no, out  exr, out  exi, out  eyr, out  eyi, out  ezr, out  ezi, out  intensity);
                    ///save output to file as well 
                List<double[]> outputParameters = new List<double[]>();
                outputParameters.Add(new double[] {rayNumber, xo,yo,zo,lo,mo,no,exr,exi,eyr,eyi,ezr,ezi,intensity });
                while (success)
                {
                    success = directPolData.ReadNextResultFull(out rayNumber, out ErrorCode, out vignetteCode, out xo, out yo, out zo, out lo, out mo, out no, out exr, out exi, out eyr, out eyi, out ezr, out ezi, out intensity);
                    outputParameters.Add(new double[] { rayNumber, xo, yo, zo, lo, mo, no, exr, exi, eyr, eyi, ezr, ezi, intensity });
                }
                var outputFile = @"C:\\Users\\AlexanderDumont\\OneDrive - Cytoveris Inc\\Documents\\R&D\\Reference Checks Analysis\\output_" + z + ".txt";
                using (var writer = new StreamWriter(outputFile))
                {
                    foreach (var item in outputParameters)
                    {
                        foreach (var col in item)
                        {
                            writer.Write(col + ",");
                        }
                        writer.WriteLine();
                    }
                }
                //TheSystem.Save();
                FinishStandaloneApplication(TheApplication);
            }

 

 

Best answer by David.Nguyen

Hi Alexander,

 

I haven’t looked at the code in detail, but I might be able to give you a lead. You are calling the method TheSystem.Tools.OpenBatchRayTrace(); multiple times troughout your loop. However, you are not closing the tool in every iteration. This is a problem because OpticStudio can only have a single tool open at any one time. You should either open the batch ray trace outside the loop, or close it at the end of each iteration. Does that make sense? I hope this helps.

 

Take care,


David

View original
Did this topic help you find an answer to your question?

7 replies

David.Nguyen
Luminary
Forum|alt.badge.img+2
  • Luminary
  • 1085 replies
  • Answer
  • March 21, 2023

Hi Alexander,

 

I haven’t looked at the code in detail, but I might be able to give you a lead. You are calling the method TheSystem.Tools.OpenBatchRayTrace(); multiple times troughout your loop. However, you are not closing the tool in every iteration. This is a problem because OpticStudio can only have a single tool open at any one time. You should either open the batch ray trace outside the loop, or close it at the end of each iteration. Does that make sense? I hope this helps.

 

Take care,


David


alexander_dumont

Ahhh I knew it must be something simple like this thank you sir!


David.Nguyen
Luminary
Forum|alt.badge.img+2

Well, I’m not hundred percent sure, so you should try it before. But if it helps you then I’m happy :)

Take care,

 

David


alexander_dumont

Hi Dave 

 

Just a quick update, but that did not solve my problem. I’m still looking back at the code, though, as I think you are correct, there is something I am not closing that remains open and blocks up the ray trace the second time around. 


MichaelH
Ansys Staff
Forum|alt.badge.img+2
  • Ansys Staff
  • 342 replies
  • March 22, 2023

Hey Alexander,

Can you try to pull your connection outside your for loop?  I believe you are trying to connect to OpticStudio, run a simulation, (not close your current connection) and then reconnect on the same class.  This is probably throwing the error:

// Create the initial connection class
ZOSAPI_Connection TheConnection = new ZOSAPI_Connection();

// Attempt to create a Standalone connection
IZOSAPI_Application TheApplication = TheConnection.CreateNewApplication();
if (TheApplication == null)
{
	HandleError("An unknown connection error occurred!");
	return;
}

// Check the connection status
if (!TheApplication.IsValidLicenseForAPI)
{
	HandleError("Failed to connect to OpticStudio: " + TheApplication.LicenseStatus);
	return;
}
if (TheApplication.Mode != ZOSAPI_Mode.Server)
{
	HandleError("User plugin was started in the wrong mode: expected Server, found " + TheApplication.Mode.ToString());
	return;
}

Try looking at Samples 22 & 23 for batch ray tracing examples inside a loop with C#.


alexander_dumont

I took the initialization and destruction functions out of the loop, so the only thing I have inside the loop is the batch ray trace initialization and reading, but it gives me this error now even though I clear the data before going through this process. This happens on the second loop and the first loop behaves just as expected. 

I initialize batch rayu trace and clear data as folllows:

            foreach (var z in z_offset_mm)
            {

                // Set up Batch Ray Trace
                IBatchRayTrace raytrace = TheSystem.Tools.OpenBatchRayTrace();

                // set up direct polarized batch ray trace 
                var directPolData = raytrace.CreateDirectPol(count_rays_launched, RaysType.Real, 1, 0, 0, 0, 0, nsur - 1);

                Console.WriteLine("# of rays simulated in batch trace: " + c);

                //first surface is dummy that we can alter thickness so alter thickness 
                TheLDE.GetSurfaceAt(1).Thickness = z;

                //clear data in ray trace and fil it back up 
                directPolData.ClearData();

So I’m gessing that somehow, even though I clear the data, it’s still in the memory and just oiverloads my memory. Not sure how to proceed with this problem. I’ve attached my entire C# script if anyone wants to take a look at it. 

Alex


alexander_dumont

Okay, that error is acutally due to just asking the ray batch trace to store too much rays in its memory, overflowing the program. When I reduce the number of rays, the problem goes away. Houff. Thank you everyone for your helpful answers. 

 

Alex


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings