Author Topic: Undo does not fully restore the values of the properties of an image  (Read 4709 times)

Offline Andres.Pozo

  • PTeam Member
  • PixInsight Padawan
  • ****
  • Posts: 927
If a script sets the value of a new property using setPropertyValue inside a View.beginProcess/endProcess block, when doing an undo it doesn't restore the original state of the properties: the new property is still defined in the image after the undo. This doesn't happen with the keywords: the undo removes the new properties created in the step which being undone.

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Don't define properties inside a beginProcess()...endProcess() construct, but *after* that construct. View properties don't depend on the normal undo/redo mechanism. Properties are stored in view states and preserved across undo/redo operations automatically, as a function of property attributes.

To define a property that cannot be stored in view states, and hence cannot be restored by a redo operation, set the PropertyAttribute_Volatile attribute when you create the property (or by calling setPropertyAttributes()).

To define a property that cannot be stored in projects, set the PropertyAttribute_NotSerializable attribute.

To define a property that will be stored in image files, sert PropertyAttribute_Storable (I think that in your scripts you must *always* set this flag).

To define a property that is "transparent" to image changes, that is, a property that will persist even if the pixel data are modified, set PropertyAttribute_Permanent.

See the pjsr/PropertyAttribute.jsh standard header for more information (given as comments to the PropertyAttribute_xxx constant definitions).
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Andres.Pozo

  • PTeam Member
  • PixInsight Padawan
  • ****
  • Posts: 927
The flag PropertyAttribute_Volatile is not really a good solution to my problem. My scripts store part of the information as FITS keywords and part as a property. I need that the properties have a behaviour similar to the keywords: the properties should be stored in the processing history so the undo/redo works like the keywords. If I have understood the meaning of the attributes, with the "Volatile" attribute the redo is different between keywords and properties. With the "Permanent" attribute is the undo which is different.

Also it would be easier for me if I could to define the properties inside a beginProcess()...endProcess(). If could not do this, I will have to set the keywords inside the begin/end and the properties outside. This will make harder and uglier to write the coordinates of an image.

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
I realize that I didn't explain this correctly in my previous post, sorry.

You don't need to use, and in fact should not use, the PropertyAttribute_Volatile and PropertyAttribute_Permanent attributes in your scripts. You must use the PropertyAttribute_Storable attribute to make sure that the properties that you define are stored in FITS and XISF files.

Just call View.setPropertyValue() with the PropertyAttribute_Storable attribute, outside a beginProcess() ... endProcess() block. Don't do anything else and the properties will work automatically, including undo/redo operations. It's just that simple.

Let me see a relevant part of your script if you need more help with this.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Andres.Pozo

  • PTeam Member
  • PixInsight Padawan
  • ****
  • Posts: 927
Hi Juan,

I have put the call to setPropertyValue outside the begin/end block and the undo still doesn't work. This is the relevant part of the code:
Code: [Select]
   this.SaveKeywords = function(imageWindow)
   {
      console.writeln("Save keywords");
      imageWindow.mainView.beginProcess(UndoFlag_Keywords);
      var keywords = imageWindow.keywords;

      this.UpdateBasicKeywords(keywords);
      this.UpdateWCSKeywords(keywords);
      this.UpdateReferKeywords(keywords);

      imageWindow.keywords = keywords;
      imageWindow.mainView.endProcess();
   };

   this.SaveProperties = function(imageWindow)
   {
      console.writeln("Save properties");
      if(this.controlPoints && (this.ref_I_G instanceof ReferSpline))
         this.SaveControlPoints(imageWindow);
      else
         imageWindow.mainView.deleteProperty("Transformation_ImageToProjection");
   };

   this.SaveControlPoints = function(imageWindow){
      console.writeln("Save controlpoints");
      var lines=["VERSION:1","TYPE:SurfaceSpline"];
      lines.push(format("ORDER:%d", this.ref_I_G.order));
      lines.push(format("SMOOTHING:%f", this.ref_I_G.smoothing));
      lines.push("CONTROLPOINTS:[");
      for(var i=0; i<this.controlPoints.pI.length; i++)
         if(this.controlPoints.pI[i] && this.controlPoints.pG[i]){
            if(this.controlPoints.weights)
               lines.push(format("%.16f;%.16f;%.16f;%.16f;%.16f",
                  this.controlPoints.pI[i].x,this.controlPoints.pI[i].y,
                  this.controlPoints.pG[i].x,this.controlPoints.pG[i].y,
                  this.controlPoints.weights[i]));
            else
               lines.push(format("%.16f;%.16f;%.16f;%.16f",
                  this.controlPoints.pI[i].x,this.controlPoints.pI[i].y,
                  this.controlPoints.pG[i].x,this.controlPoints.pG[i].y));
         }
      lines.push("]");

      var byteArray = new ByteArray(lines.join('\n'));
      imageWindow.mainView.setPropertyValue("Transformation_ImageToProjection", byteArray, PropertyType_ByteArray, PropertyAttribute_Storable);
   };

I call first the method SaveKeywords and then SaveProperties.
If I run this script on an image which doesn't have any properties a new property "Transformation_ImageToProjection" is created. If I execute an undo, I expect that the image doesn't have any properties again. However, after the undo the property "Transformation_ImageToProjection" is still defined in the image. This behaviour breaks the synchronization between the data stored in the keywords and properties.

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Now I understand the problem. This happens because your script does not generate a swap file. You call:

      imageWindow.mainView.beginProcess(UndoFlag_Keywords);

which stores the existing keywords in the view, but doesn't generate swap file data. Since properties are not directly controlled by process histories, they are not synchronized with in-memory swap data. If you force generation of a swap file:

      imageWindow.mainView.beginProcess();

The properties will be stored in the swap file and hence they will be undoable.

I'll fix this problem in the next version (by forcing synchronization of view properties with all history records). In the meanwhile, you can either force a swap file, or continue doing what you're doing and just ignore the potential synchronization problem. Once we have a new version your script will work correctly without changes.

Sorry for the trouble.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Andres.Pozo

  • PTeam Member
  • PixInsight Padawan
  • ****
  • Posts: 927
Thanks Juan,

this seems to do the trick.

I still don't fully understand the behavior of beginProcess, setPropertyValue and its flags, but the script seems to be working now.