Skip to main content

Dear support team,



it seems that a 'Print' statement  in ZPL is suppressed during the script is running. Then at the end of the script all print statements are executed at once.


I guess, this is a kind of optimisation? However, I am running large scripts and I would like to see the progress in the command window . So I would like the print statement to react directly when it is called. Is this possible?



   Thank you,


      Christof.

Hi Christof,



Thanks for your post here on the MyZemax forum!



I tried to reproduce this behavior with a couple of simple macros. I found that if you do the printing from a child macro as suggested in the Help to speed up the macro execution, then all the pritnts will appear in the Text Window at once after the script is finished. This seems to be intentional so that Text Window doesn't need to be updated every time when a string is added to it. You may read more about this solution in the Help system at:


The Programming Tab > About the ZPL > KEYWORDS (about the zpl) > PRINT



On the other hand, if you do the printing from the macro itself, without using a child macro, it seems that in most of the cases the Text Window is updated after every added line.



With my simple testing example, I found that sometimes if you run the macro for the first time by Programming...Edit/Run...Execute, it outputs the text once at the end, but this is a short and simple example without any long computations:





However, this never happened when I ran the macro for a second time by updating the Text Window as suggested by Allie in this forum thread:


Efficiency Tips & Tricks for OpticStudio · MyZemax



When re-running the macro by updating the Text Window, it the prints always appeared in the Text Window line by line.



Please find my test macros attached.



If you are not using a child macro for the printing, you might want to try to run the macro by updating the Text Window. Maybe even you can try to run it by Programming...Edit/Run...Execute, Terminate it once the Text Window is generated and re-run it by updating the Text Window for the long simulation.



If these don't help solving your issue, would you mind sharing your system together with the macro so that we can take a look at it? If you don't want to share the design here in the forums, please feel free to open a support case with us.



Thanks,



Csilla


Thank you Csilla for your reply.


Yes, my print statements are in the child macro. Each time a child has finished I am printing a short message from this child, like 'I am finished'. This is to get information on the progress of the flow. But it does not print until the complete (parent) flow has finished, and all messages are printed togehter at the end.



I am a bit confused to hear that the behaviour depends on how I start the script and weather it is started for the first time or for the second time by 'update'. Normally I run it once.



Assume you run a script that takes some days to finish and you would like to receive information on the progress. Is there a way that the script reports from time to time what it is doing?



Thank you and best regards,


Christof.


Hi Christof,



Thanks for your feedback and confirming that you are using child macros and trying to do the printing from the child functions.



I believe printing from the child macros causes your problem. Are you using the child macros just in order to speed up the printing as advised in the Help or are you running other computations from the childs as well? If you are using the childs for other computations too, then I think moving only the PRINT commands to the parent instead of having them in the childs would solve your problem. In this case you can still use the childs to perform the other tasks, so that the parent function isn't too long and remains readable, but if you call the PRINT commands directly from the parent after the lines which run the childs then the text outputs will appear in the Text Window right away, and not all at once when the parent is finished as in case of having the PRINT commands in the childs instead. Does this sound like a reasonable solution to you?



Regarding my testing, it might be the case that I observed this strange behavior because my test macros are quite short and don't contain any long computations, so the update time is comparable to the run time of the whole script. I apologize for this and the confusion it caused, these might not be the best test examples. I did not observe this strange behavior with any longer macros that contain more complex computations. In all those cases the Text Window was updated continuously during the macro run regardless of how I started the macro or whether it was the first, second or nth time.



Thanks and best regards,



Csilla


This is an interesting use case that I don't think we ever considered when first building and testing this feature. Here's some pseudo-code that should help identify the problem





PRINT 'Current time' #use the TIMER & ETIM()

PRINT 'Calling the Child...'

#In child macro

PRINT 'Printout from Child'

PAUSE 5 seconds

PRINT 'Printout 5 seconds later'

RETURN

PRINT 'Child has returned;

PRINT time again


This should establish if the printing from the child macro is instantaneous or delayed until the child returns.



The user's expectation is for instantaneous printing, and so if you don't get instantaneous, I think the devs should look to see why. There may be some perfectly good reason for this, in which case Christoph needs to move his monitoring to the parent macro (and we should document that PRINTs are held over until the child returns), but it may equally be that we just never thought of this case and maybe we should support it if possible.



 


I use the childs similar to subroutines. They are called several times with different input parametrs. Putting the print statemts to the parent is not a nice programming style, because it has to be repeated each time the child is called, together with a string that must be given back. However, it is possible. But I think I will first check (tomorrow, I am in Germany 😉 what happens if I print this status report to a file.


Thanks again, cheers, Christof.


Hi Christof,



I did some extra testing on printing to the screen and I found some workaround which might be useful to you. If you call the child macro in a loop and you do some printing from the child and from the parent too in the same loop where you call the child, the text vindow will be updated every time once you return to the parent and print from there. All the print statements from the child run will be updated once together with the print statement from the parent. This means that it will still not update from inside the child and you cannot monitor the progress inside the child, but at least you can print out the updates in every cycle. In this way, you can print out the results from the child, so you don't have to give them back to the parent, which I see is not a desired solution, and you can just print something like 'in parent' from the parent loop to trigger the updates. This is a bit odd behavior that if you print from the parent too it updates the text output every cycle, while if you only print from the child the output is only updated once the parent is finished. Please see my test macros attached. I will check this with our developers to see if this the intended behaviour.



Best regards,



Csilla


Hi Christof,

I just realized I did not follow-up on this thread earlier, apologies for that.
Please allow me to share the feedback from the developers now.

The PRINT macro keyword always writes to a file, regardless of the output mode used, i.e. even you use OUTPUT SCREEN. Then, when CALLMACRO is called for a child, a new temporary file is created that receives all output from the child, which is then concatenated into the main file output at the very end.  So, this means that unfortunately there is currently no way to immediately print everything from the child macro as it occurs.
That said, you do not need to worry about any buffer filling up during this process, unless your disk is almost full.

I see how this affects your workflow, thank you for bringing this to our attention. I have gone ahead and submitted this internally as a feature request, so it might be added later in the future.
Please keep in mind that feature requests are weighed based on impact, difficulty to implement, and the number of users who request them. A request is not a guarantee that the feature will be added to a future release.
However, these feature requests are very important to us and shape the future of OpticStudio, so we appreciate your input regarding desired functionality.

Best,
Csilla


I know I’m late to the party, but this was a fun little problem to try to solve.  OpticStudio & the ZPL doesn’t have anything native that can display the output of a PRINT command from a child macro instantaneously (as Csilla mentioned, this is because the child’s PRINT is concatenated with parent’s output at the end of the parent’s execution).  However, the ZPL has the COMMAND keyword which enables us to get really creative.  

The COMMAND keyword can run anything “callable” from the cmd Command Window, so this includes EXE, BAT or even a variable stored on the PATH environment variable.  For this task, we can use a simple batch file to report the status of the child macro.  The logic for the batch file is as follows:

  • create a temporary file (file) in the parent macro that will be passed to the child macro for OUTPUT and PRINT
  • create a secondary temp file (old) which stores the last saved status of the output file
  • run a BAT file which monitors the file attributes of the file and if the attributes change (i.e., the Date Modified which includes HH:MM:SS)
  • if the attributes change, print the difference between file and old (this will simply be everything saved using the PRINT command in the latest child macro)

The Parent macro is:

# get a temporary file to pass to the child macro
tmp$ = $TEMPFILENAME()
CALLSETSTR 1, tmp$

# get a second temporary file to pass to the batch script
tmp2$ = $TEMPFILENAME()

# launch the monitor.bat with both file arguments
bat$ = "C:\temp\monitor.bat"
arg$ = tmp$ + " " + tmp2$
COMMAND bat$, arg$

FOR i = 1, 10, 1
CALLSETDBL 1, i
CALLMACRO CHILD.ZPL
PAUSE TIME, 1000
NEXT

The Child macro is:

# get the temporary file
tmp$ = $CALLSTR(1)

FORMAT 2.0
OUTPUT tmp$, APPEND
PRINT "Child macro : " , CALD(1)
PRINT "end of child macro"
OUTPUT SCREEN

And the monitor.bat file is:

@echo off

:: get CLI arguments for the 2 temp files
set file=%1
set old=%2

:: copy original file so we can find the diff when the attrib changes
copy %file% %old% >nul

:: start the "watch" loop looking for the file attribute to change
:loop
:: pause loop for "1" second (prevents runaway memory)
timeout -t 1 >nul

:: check if the attrib tags have changed for the file
for %%i in (%file%) do echo %%~ai|find "a">nul || goto :loop

:: count the number of lines in the old file
:: we will start printing FROM this linecount
set /a numLines=0
for /f %%a in ('type "%old%"^|find "" /v /c') do set /a numLines=%%a

:: print only the additional lines
more /e +%numLines% %file%

:: save a copy of the file for comparison
copy %file% %old% >nul

:: save latest attributes
attrib -a %file%
goto :loop

 

 


Reread some of the previous posts a little more closely and wanted to share an updated child.zpl which shows how to print out updates in the middle of a child macro’s execution (namely, you need to call OUTPUT SCREEN to save & close the printed file and then OUTPUT tmp$, APPEND to reopen and add more text):

# get the temporary file
tmp$ = $CALLSTR(1)

FORMAT 2.0
OUTPUT tmp$, APPEND
PRINT "Child macro : " , CALD(1)
OUTPUT SCREEN

PAUSE TIME, 2000

OUTPUT tmp$, APPEND
PRINT "Second calculation for : ", CALD(1)
OUTPUT SCREEN

PAUSE TIME, 2000

 


Reply