importpyotbimg_pth="/vsicurl/https://gitlab.orfeo-toolbox.org/orfeotoolbox/" \"otb/-/raw/develop/Data/Input/SP67_FR_subset_1.tif?inline=false"bm=pyotb.BandMath({"il":[img_pth],"exp":"im1b1"})bm.write("/tmp/toto.tif")# Comment this line --> Worksprint(bm.shape)
Output
itk::ERROR: BandMath(0x12d7870): Call Execute() or ExecuteAndWriteOutput() before trying to reach output image information
The problem is that after pipeline execution, OTB considers that the Execute() method has to be called again, prior to access the output image parameters?
By Rémi Cresson on 2023-01-06T09:17:55 (imported from GitLab)
I need to check again but it may be due to PropagateConnectMode... but I believe this is not called when we simply init an Input then directly write the result. So UpdateParameters is the main suspect here
By Vincent Delbar on 2023-01-06T09:44:48 (imported from GitLab)
Still this should not happen with our try except at the end of write():
try:self.app.WriteOutput()exceptRuntimeError:logger.debug('%s: failed to simply write output, executing once again then writing',self.name)self.app.ExecuteAndWriteOutput()
By Vincent Delbar on 2023-01-06T09:50:04 (imported from GitLab)
Propagate no, UpdateParameters yes when we set the output param value (well not us but it is done internally by otb), but then we call ExecuteAndWriteOutput again if needed
By Vincent Delbar on 2023-01-06T09:53:17 (imported from GitLab)
Yes. I fear this is the same kind of problem than the previous big one we had : I mean this is occurs when we Execute several times, or Execute then ExecuteAndWriteOutput again.
But the following is working (when we write output immediately at init) :
The following is working, so I really think now that the problem comes from pyotb :/
importotbApplicationimg_pth="/vsicurl/https://gitlab.orfeo-toolbox.org/orfeotoolbox/otb/-/raw/develop/Data/Input/SP67_FR_subset_1.tif?inline=false"app=otbApplication.Registry.CreateApplication("BandMath")app.SetParameterStringList("il",[img_pth])app.SetParameterString("out","/tmp/toto.tif")app.SetParameterString("exp","im1b1")app.ExecuteAndWriteOutput()# Can be as well Execute(). If commented, the right exception is thrownprint(app.GetImageSize("out"))
By Rémi Cresson on 2023-01-06T16:18:41 (imported from GitLab)
I don't think this is a bug in pyotb but a normal behaviour of OTB.
The snippet works if I re-run Execute() after WriteOutput() in write().
I guess this is not possible to re-use the app once it has been written, without re-executing it.
And it seems right, if the image is flushed to disk, it is not in memory anymore, so attributes like GetImageNbBands doesn't work anymore, if we don't execute once again.
I do believe what you want to do in code like test_pipeline isn't compatible with how otb works in memory. Generating a pipeline, writing the result to disk, then using it again in another pipeline as if it was still in memory... May be if the result has been written and is called again, we should point to the file on disk, instead of executing the app once more..?
By Vincent Delbar on 2023-01-06T14:14:43 (imported from GitLab)
Yes you're right, something must be wrong in write(), but the only diff I can see is that you're using ExecuteAndWriteOutput whereas we do Execute during app init then WriteOutput OR ExecuteAndWriteOutput...
By Vincent Delbar on 2023-01-06T14:26:14 (imported from GitLab)
I think that I understood the problem. Setting the "out" parameter triggers the UpdateParameters, so resets the state of the OTB application execution (m_ExecuteDone, etc)
By Rémi Cresson on 2023-01-06T14:49:00 (imported from GitLab)
OTB considers that any parameter modification implies that the application has not been executed. Even if it actually has.
Sometimes, this behavior could make sense (e.g. changing some application parameters that change output image informations, like image size) but sometimes it doesn't (e.g. changing the output file name).
By Rémi Cresson on 2023-01-06T14:53:53 (imported from GitLab)
I don't see what the has_changed would do if the problem is upstream in OTB code .?
I don't know if this could be changed in OTB, regarding the architecture of the OTB application engine. I doubt that the OTB application engine is able to detect which parameters are modified during DoUpdateParameters(), which is implemented in the OTB applications. I think it would be a lot easier to do that on the python side.
By Rémi Cresson on 2023-01-06T15:06:21 (imported from GitLab)
It's working with has_changed and if we check this flag or call Execute in shape, to_array etc.
But this will be easier in my new branch because we need to init this flag, and right now otbObject doesn't have an __init__.
This is what I plan to change, by moving almost all the App code to OTBObject, to avoid having classes like Slicer that init an App object, while they also directly inherit from OTBObject.
By Vincent Delbar on 2023-01-06T15:23:51 (imported from GitLab)
All right. I see this IsExecuteDone function, may be we need to check this everytime or call execute ( I mean in properties like shape, dtype, and in write...)
By Vincent Delbar on 2023-01-06T09:43:28 (imported from GitLab)