On Tuesday, July 23, 2019 at 7:08:01 AM UTC+2, kfj wrote:
 

> I did the changes I mentioned above here and made a new patch - not sure 
> if the removal of the excutable flag shows in the diff, if not, just do 
> chmod a-x on offending files.
>

Sorry, one of my local changes leaked into the previous patch. here's the 
proper one. And yes, the mode changes did make it into the patch. 

>
> with regards
> Kay
>  
>  
>

-- 
A list of frequently asked questions is available at: 
http://wiki.panotools.org/Hugin_FAQ
--- 
You received this message because you are subscribed to the Google Groups 
"hugin and other free panoramic software" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/hugin-ptx/25ae73a0-6171-4fdb-a4a5-d2f8c3d35fb7%40googlegroups.com.
diff --git a/src/hugin_script_interface/plugins-dev/dual_use.py b/src/hugin_script_interface/plugins-dev/dual_use.py
--- a/src/hugin_script_interface/plugins-dev/dual_use.py
+++ b/src/hugin_script_interface/plugins-dev/dual_use.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 gpl = r"""
@@ -23,8 +21,6 @@
 
 # @category Examples
 # @name     Dual Use Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # dual_use will function as a hugin plugin and as a standalone
 # Python script.
diff --git a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
--- a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
+++ b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 # plugin_skeleton.py - a skeleton for a hugin plugin
 # Copyright (C) 2011  Kay F. Jahnke
 
@@ -18,8 +16,6 @@
 
 # @category Examples
 # @name     Skeleton Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # we use modern type python print statements:
 
diff --git a/src/hugin_script_interface/plugins/crop_cp.py b/src/hugin_script_interface/plugins/crop_cp.py
deleted file mode 100755
--- a/src/hugin_script_interface/plugins/crop_cp.py
+++ /dev/null
@@ -1,337 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-gpl = r"""
-    crop_cp.py - remove CPs from parts of the panorama
-    
-    Copyright (C) 2011  Kay F. Jahnke
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-# @category Control Points
-# @name     Crop Control Points
-# @api-min  2011.1
-# @api-max  2015.1
-
-# crop_cps will function as a hugin plugin and as a standalone
-# Python script. It can also serve as a template for a slightly
-# more involved plugin than the ones in the Examples section.
-
-# Please note that this script tries to use wxPython. This should
-# work on Linux systems that have wxPython istalled, but as far as
-# I know currently it won't work on Windows, and certainly not on
-# Mac OS, where there is currently no hsi/hpi suport. If you want
-# to switch off the use of wxPython, set the default parameter in
-# the entry function to a value different from None, i.e. change
-# def entry ( pano , inside = None ) :
-# to
-# def entry ( pano , inside = False ) :
-
-import os
-import sys
-import hsi
-import math
-
-# we make an exception for run time errors in this script:
-
-class CropCpError ( Exception ) :
-
-    def __init__ ( self , text ) :
-        self.text = text
-
-    def __str__ ( self ) :
-        return self.text
-    
-# some global variables to reduce overhead - we just reuse the same
-# FDiff2D objects every time we call the transforms
-
-transform_in = hsi.FDiff2D(0,0)
-transform_out = hsi.FDiff2D(0,0)
-
-# transform point coordinates using panotools transforms
-# and the global variables for source and target
-
-class to_pano :
-
-    def __init__ ( self , pano , image ) :
-
-        pano_options = pano.getOptions()
-        img = pano.getImage ( image )
-        w = img.getWidth()
-        h = img.getHeight()
-        self.wh = w / 2.0
-        self.hh = h / 2.0
-
-        # image to pano
-
-        self.tf = hsi.Transform()
-        self.tf.createInvTransform ( img , pano_options )
-
-    def transform ( self , p ) :
-
-        # pixel coordinates come in, but have to use center-origin
-        
-        transform_in.x = p[0] - self.wh
-        transform_in.y = p[1] - self.hh
-
-        if self.tf.transform ( transform_out , transform_in ) :
-            return ( transform_out.x , transform_out.y )
-
-        # KFJ 2011-06-19 I've noticed the transform failing
-        # with images that have X, Y or Z values different from 0.
-        # I'm not sure if this is a bug in the transform.
-        
-        print ( 'transform failed for %s' % str ( p ) )
-        return None
-
-# the crop_cps routine is the workhorse of this script. It does the
-# actual work of looking at the CPs and removing the unwanted ones.
-
-def crop_cps ( pano , inside ) :
-
-    pano_options = pano.getOptions()
-
-    size = pano_options.getSize()
-
-    # we need these offsets because pano coordinates are center-origin
-    
-    wh = size.width() / 2.0
-    hh = size.height() / 2.0
-    
-    # that's the ROI of the panorama, in corner-origin
-    
-    roi = pano_options.getROI()
-
-    # out limits, now in center-origin
-    
-    left = roi.left() - wh
-    right = roi.right() - wh
-    top = roi.top() - hh
-    bottom = roi.bottom() - hh
-
-    ni = pano.getNrOfImages()
-    tflist = []
-
-    # we get a list of CPs in pano coordinates. Note that the pano
-    # coordinates are taken from the coordinates in the left image only.
-    
-    for img in range ( ni ) :
-        tflist.append ( to_pano ( pano , img ) )
-
-    # we take the CPVector:
-    
-    cpv = pano.getCtrlPoints()
-    print ( 'found %d CPs' % len ( cpv ) )
-
-    # We want to put the remaining CPs into this CPVector:
-    
-    ncpv = hsi.CPVector()
-
-    for cp in cpv :
-        p = ( cp.x1 , cp.y1 )
-        img = cp.image1Nr
-        tfp = tflist[img].transform ( p )
-        # KFJ 2011-06-17 If the transform fails, keep the CP
-        # - best to be defensive.
-        if tfp is None :
-            ncpv.append ( cp )
-        elif inside : # remove CPs inside ROI (or, keep those outside)
-            if not ( ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) ) :
-                ncpv.append ( cp )
-        else :
-            if ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) :
-                ncpv.append ( cp )
-
-    pano.setCtrlPoints ( ncpv )
-    print ( 'removed %d CPs' % ( len ( cpv ) - len ( ncpv ) ) )
-
-    return 0
-
-# the remainder of the script is administration and deals with running
-# it either as a plugin from hugin or as a standalone CLI program.
-
-# first is the entry routine which is called when this script is used
-# as a plugin from hugin. If the inside parameter is not passed
-# (or passed as 'None') - a dialog will ask whether to remove CPs
-# inside or outside of the ROI. If inside is passed as True, CPs
-# inside the ROI are removed, otherwise those outside.
-# Note that the 'GUI' is primitive - it offers no help or about info,
-# no tool tips etc. - the help could be made from the docstrings of
-# the CLI version below.
-
-def entry ( pano , inside = None ) :
-
-    if inside is None:
-
-    # if we've been called as a plugin (we're not main) and inside is
-    # None, the default, we assume that we're supposed to ask the user
-    # whether to remove the CPs from inside or outside the ROI. If
-    # inside is passed as True or False, we execute without further ado.
-
-        import wx
-
-        # we need a simple dialog box for this purpose which displays
-        # a radio button for the inside/outside choice, plus Okay and Cancel.
-        
-        class crop_cp_dialog ( wx.Dialog ) :
-
-            # excuse my clumsy wxPython ;-)
-            
-            def __init__(self, parent, title):
-
-                wx.Dialog.__init__(self, parent, -1, title, size = ( 200 , 150 ) )
-                choices = [ 'outside ROI' , 'inside ROI' ]
-                # default choice is to remove CPs outdide ROI
-                self.choice = 0
-
-                # we create and position the UI elements                
-                sizer = wx.BoxSizer ( wx.VERTICAL )
-                rb = wx.RadioBox(
-                        self, -1, "", wx.DefaultPosition, wx.DefaultSize,
-                        choices, 2, wx.RA_SPECIFY_COLS
-                        )
-                self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, rb)
-                sizer.Add(rb, 0, wx.ALL, 20)
-                btnsizer = wx.StdDialogButtonSizer()
-                btn = wx.Button(self, wx.ID_OK)
-                btn.SetDefault()
-                btnsizer.AddButton(btn)
-                btn = wx.Button(self, wx.ID_CANCEL)
-                btnsizer.AddButton(btn)
-                btnsizer.Realize()
-                sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
-                self.SetSizer(sizer)
-
-            # what to do when the radio button is operated:
-            def EvtRadioBox(self, event):
-                self.choice = event.GetInt()
-        
-        # make the dialog and show it modally:
-        ccd = crop_cp_dialog ( None , 'Crop CPs' )
-        retval = ccd.ShowModal()
-        # only if Okay was clicked the state of the radio button is used
-        if retval == wx.ID_OK :
-            if ccd.choice == 0 :
-                inside = False
-            else :
-                inside = True
-        # otherwise we cancel the operation and return.
-        else :
-            return 0
-
-    # now the preliminaries are sorted, we can call the workhorse routine.
-    
-    return crop_cps ( pano , inside )
-    
-# the main routine is what's called if this script has been called from
-# the command line. In this case we do the CLI thing, so we parse the
-# argument vector and act accordingly.
-
-def main() :
-
-    # when called from the command line, we import the argparse module.
-    # This may not be part of the standard library on your system.
-    
-    import argparse
-
-    # and create an argument parser.
-    
-    parser = argparse.ArgumentParser (
-        formatter_class=argparse.RawDescriptionHelpFormatter ,
-        description = gpl + '''
-    crop_cp will remove all CPs which are either outside the panorama's ROI
-    or inside it's ROI if the inside flag is set
-    ''' )
-
-    parser.add_argument('-o', '--output',
-                        metavar='<output file>',
-                        default = None,
-                        type=str,
-                        help='write output to a different file')
-
-    parser.add_argument('-i', '--inside',
-                        action='store_true',
-                        default = False,
-                        help='remove CPs inside ROI')
-
-    parser.add_argument('input' ,
-                        metavar = '<pto file>' ,
-                        type = str ,
-                        help = 'pto file to be processed' )
-
-    if len ( sys.argv ) < 2 :
-        parser.print_help()
-        return
-
-    # we parse the arguments into a global variable so we can access
-    # them from everywhere without having to pass them around
-    
-    global args
-    
-    args = parser.parse_args()
-
-    if args.output :
-        print ( 'output: ' , args.output )
-    print ( 'ptofile:' , args.input )
-
-    # first we see if we can open the input file
-
-    ifs = hsi.ifstream ( args.input )
-    if not ifs.good() :
-        raise CropCpError ( 'cannot open input file %s' % args.input )
-
-    pano = hsi.Panorama()
-    success = pano.readData ( ifs )
-    del ifs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'input file %s contains invalid data' % args.input )
-
-    # if a separate output file was chosen, we open it now to avoid
-    # later disappointments
-    
-    if args.output:
-        ofs = hsi.ofstream ( args.output )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open output file %s' % args.output )
-
-    # we've checked the args, now we call crop_cps()
-    
-    crop_cps ( pano , args.inside )
-
-    # if no different output file was specified, overwrite the input
-    
-    if not args.output :
-        ofs = hsi.ofstream ( args.input )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open file %s for output' % args.input )
-
-    success = pano.writeData ( ofs )
-    del ofs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'error writing pano to %s' % args.input )
-    
-    # done.
-    
-    return 0
-
-# are we main? This means we've been called from the command line
-# as a standalone program, so we have to go through the main() function.
-
-if __name__ == "__main__":
-    try:
-        main()
-    except CropCpError as e :
-        print ( 'Run Time Error: %s' % e )
diff --git a/src/hugin_script_interface/plugins/shooting_pattern.py b/src/hugin_script_interface/plugins/shooting_pattern.py
--- a/src/hugin_script_interface/plugins/shooting_pattern.py
+++ b/src/hugin_script_interface/plugins/shooting_pattern.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 #    shooting_pattern.py - apply a 6-1-1 shooting pattern to a panorama
@@ -41,8 +39,6 @@
 # @name     6-1-1 Shooting Pattern
 # @description apply a shooting pattern (6 around, 1 up 1 down)
 # @sys win nix mac
-# @api-max 2016.1
-# @api-min 2011.1
 
 # the position routine will apply yaw, pitch to an image
 
diff --git a/src/hugin_script_interface/plugins/top_five.py b/src/hugin_script_interface/plugins/top_five.py
--- a/src/hugin_script_interface/plugins/top_five.py
+++ b/src/hugin_script_interface/plugins/top_five.py
@@ -1,11 +1,7 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 # @category Control Points
 # @name     keep 5 CPs per image pair
-# @api-min  2011.1
-# @api-max  2016.1
 
 #    top_five.py - keep the five best CPs for each image pair
 
@@ -66,7 +62,10 @@
 
     # finally we attach the new CP vector to the panorama
     
-    print ( 'keeping %d control points' % len ( cpv ) )
+    print ( 'keeping %d control points:' % len ( cpv ) )
+    for cp in cpv:
+        print ( "%d %d %d %d" % ( cp.x1 , cp.y1 , cp.x2 , cp.y2 ) )
+
     pano.setCtrlPoints ( cpv )
     
     return 0
diff --git a/src/hugin_script_interface/plugins/woa.py b/src/hugin_script_interface/plugins/woa.py
--- a/src/hugin_script_interface/plugins/woa.py
+++ b/src/hugin_script_interface/plugins/woa.py
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from __future__ import print_function
@@ -24,8 +23,6 @@
 """
 # @category Control Points
 # @name     Warped Overlap Analysis
-# @api-min  2014.0
-# @api-max  2016.3
 
 # note that if you want to read the script, it's written bottom-up, so the
 # higher-level routines are towards the end.
diff --git a/src/hugin_base/panodata/PanoramaOptions.h b/src/hugin_base/panodata/PanoramaOptions.h
--- a/src/hugin_base/panodata/PanoramaOptions.h
+++ b/src/hugin_base/panodata/PanoramaOptions.h
@@ -240,7 +240,7 @@
             panoProjectionFeaturesQuery(m_projectionFormat, &m_projFeatures);
             resetProjectionParameters();
 
-            outputStacksMinOverlap = 0.7;
+            outputStacksMinOverlap = 0.85;
             outputLayersExposureDiff = 0.5;
         }
 
diff --git a/src/hugin_script_interface/hpi.py b/src/hugin_script_interface/hpi.py
old mode 100755
new mode 100644
diff --git a/src/hugin_script_interface/plugins-dev/dual_use.py b/src/hugin_script_interface/plugins-dev/dual_use.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins-dev/dual_use.py
+++ b/src/hugin_script_interface/plugins-dev/dual_use.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 gpl = r"""
@@ -23,8 +21,6 @@
 
 # @category Examples
 # @name     Dual Use Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # dual_use will function as a hugin plugin and as a standalone
 # Python script.
diff --git a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
+++ b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 # plugin_skeleton.py - a skeleton for a hugin plugin
 # Copyright (C) 2011  Kay F. Jahnke
 
@@ -18,8 +16,6 @@
 
 # @category Examples
 # @name     Skeleton Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # we use modern type python print statements:
 
diff --git a/src/hugin_script_interface/plugins/crop_cp.py b/src/hugin_script_interface/plugins/crop_cp.py
deleted file mode 100755
--- a/src/hugin_script_interface/plugins/crop_cp.py
+++ /dev/null
@@ -1,337 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-gpl = r"""
-    crop_cp.py - remove CPs from parts of the panorama
-    
-    Copyright (C) 2011  Kay F. Jahnke
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-# @category Control Points
-# @name     Crop Control Points
-# @api-min  2011.1
-# @api-max  2015.1
-
-# crop_cps will function as a hugin plugin and as a standalone
-# Python script. It can also serve as a template for a slightly
-# more involved plugin than the ones in the Examples section.
-
-# Please note that this script tries to use wxPython. This should
-# work on Linux systems that have wxPython istalled, but as far as
-# I know currently it won't work on Windows, and certainly not on
-# Mac OS, where there is currently no hsi/hpi suport. If you want
-# to switch off the use of wxPython, set the default parameter in
-# the entry function to a value different from None, i.e. change
-# def entry ( pano , inside = None ) :
-# to
-# def entry ( pano , inside = False ) :
-
-import os
-import sys
-import hsi
-import math
-
-# we make an exception for run time errors in this script:
-
-class CropCpError ( Exception ) :
-
-    def __init__ ( self , text ) :
-        self.text = text
-
-    def __str__ ( self ) :
-        return self.text
-    
-# some global variables to reduce overhead - we just reuse the same
-# FDiff2D objects every time we call the transforms
-
-transform_in = hsi.FDiff2D(0,0)
-transform_out = hsi.FDiff2D(0,0)
-
-# transform point coordinates using panotools transforms
-# and the global variables for source and target
-
-class to_pano :
-
-    def __init__ ( self , pano , image ) :
-
-        pano_options = pano.getOptions()
-        img = pano.getImage ( image )
-        w = img.getWidth()
-        h = img.getHeight()
-        self.wh = w / 2.0
-        self.hh = h / 2.0
-
-        # image to pano
-
-        self.tf = hsi.Transform()
-        self.tf.createInvTransform ( img , pano_options )
-
-    def transform ( self , p ) :
-
-        # pixel coordinates come in, but have to use center-origin
-        
-        transform_in.x = p[0] - self.wh
-        transform_in.y = p[1] - self.hh
-
-        if self.tf.transform ( transform_out , transform_in ) :
-            return ( transform_out.x , transform_out.y )
-
-        # KFJ 2011-06-19 I've noticed the transform failing
-        # with images that have X, Y or Z values different from 0.
-        # I'm not sure if this is a bug in the transform.
-        
-        print ( 'transform failed for %s' % str ( p ) )
-        return None
-
-# the crop_cps routine is the workhorse of this script. It does the
-# actual work of looking at the CPs and removing the unwanted ones.
-
-def crop_cps ( pano , inside ) :
-
-    pano_options = pano.getOptions()
-
-    size = pano_options.getSize()
-
-    # we need these offsets because pano coordinates are center-origin
-    
-    wh = size.width() / 2.0
-    hh = size.height() / 2.0
-    
-    # that's the ROI of the panorama, in corner-origin
-    
-    roi = pano_options.getROI()
-
-    # out limits, now in center-origin
-    
-    left = roi.left() - wh
-    right = roi.right() - wh
-    top = roi.top() - hh
-    bottom = roi.bottom() - hh
-
-    ni = pano.getNrOfImages()
-    tflist = []
-
-    # we get a list of CPs in pano coordinates. Note that the pano
-    # coordinates are taken from the coordinates in the left image only.
-    
-    for img in range ( ni ) :
-        tflist.append ( to_pano ( pano , img ) )
-
-    # we take the CPVector:
-    
-    cpv = pano.getCtrlPoints()
-    print ( 'found %d CPs' % len ( cpv ) )
-
-    # We want to put the remaining CPs into this CPVector:
-    
-    ncpv = hsi.CPVector()
-
-    for cp in cpv :
-        p = ( cp.x1 , cp.y1 )
-        img = cp.image1Nr
-        tfp = tflist[img].transform ( p )
-        # KFJ 2011-06-17 If the transform fails, keep the CP
-        # - best to be defensive.
-        if tfp is None :
-            ncpv.append ( cp )
-        elif inside : # remove CPs inside ROI (or, keep those outside)
-            if not ( ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) ) :
-                ncpv.append ( cp )
-        else :
-            if ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) :
-                ncpv.append ( cp )
-
-    pano.setCtrlPoints ( ncpv )
-    print ( 'removed %d CPs' % ( len ( cpv ) - len ( ncpv ) ) )
-
-    return 0
-
-# the remainder of the script is administration and deals with running
-# it either as a plugin from hugin or as a standalone CLI program.
-
-# first is the entry routine which is called when this script is used
-# as a plugin from hugin. If the inside parameter is not passed
-# (or passed as 'None') - a dialog will ask whether to remove CPs
-# inside or outside of the ROI. If inside is passed as True, CPs
-# inside the ROI are removed, otherwise those outside.
-# Note that the 'GUI' is primitive - it offers no help or about info,
-# no tool tips etc. - the help could be made from the docstrings of
-# the CLI version below.
-
-def entry ( pano , inside = None ) :
-
-    if inside is None:
-
-    # if we've been called as a plugin (we're not main) and inside is
-    # None, the default, we assume that we're supposed to ask the user
-    # whether to remove the CPs from inside or outside the ROI. If
-    # inside is passed as True or False, we execute without further ado.
-
-        import wx
-
-        # we need a simple dialog box for this purpose which displays
-        # a radio button for the inside/outside choice, plus Okay and Cancel.
-        
-        class crop_cp_dialog ( wx.Dialog ) :
-
-            # excuse my clumsy wxPython ;-)
-            
-            def __init__(self, parent, title):
-
-                wx.Dialog.__init__(self, parent, -1, title, size = ( 200 , 150 ) )
-                choices = [ 'outside ROI' , 'inside ROI' ]
-                # default choice is to remove CPs outdide ROI
-                self.choice = 0
-
-                # we create and position the UI elements                
-                sizer = wx.BoxSizer ( wx.VERTICAL )
-                rb = wx.RadioBox(
-                        self, -1, "", wx.DefaultPosition, wx.DefaultSize,
-                        choices, 2, wx.RA_SPECIFY_COLS
-                        )
-                self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, rb)
-                sizer.Add(rb, 0, wx.ALL, 20)
-                btnsizer = wx.StdDialogButtonSizer()
-                btn = wx.Button(self, wx.ID_OK)
-                btn.SetDefault()
-                btnsizer.AddButton(btn)
-                btn = wx.Button(self, wx.ID_CANCEL)
-                btnsizer.AddButton(btn)
-                btnsizer.Realize()
-                sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
-                self.SetSizer(sizer)
-
-            # what to do when the radio button is operated:
-            def EvtRadioBox(self, event):
-                self.choice = event.GetInt()
-        
-        # make the dialog and show it modally:
-        ccd = crop_cp_dialog ( None , 'Crop CPs' )
-        retval = ccd.ShowModal()
-        # only if Okay was clicked the state of the radio button is used
-        if retval == wx.ID_OK :
-            if ccd.choice == 0 :
-                inside = False
-            else :
-                inside = True
-        # otherwise we cancel the operation and return.
-        else :
-            return 0
-
-    # now the preliminaries are sorted, we can call the workhorse routine.
-    
-    return crop_cps ( pano , inside )
-    
-# the main routine is what's called if this script has been called from
-# the command line. In this case we do the CLI thing, so we parse the
-# argument vector and act accordingly.
-
-def main() :
-
-    # when called from the command line, we import the argparse module.
-    # This may not be part of the standard library on your system.
-    
-    import argparse
-
-    # and create an argument parser.
-    
-    parser = argparse.ArgumentParser (
-        formatter_class=argparse.RawDescriptionHelpFormatter ,
-        description = gpl + '''
-    crop_cp will remove all CPs which are either outside the panorama's ROI
-    or inside it's ROI if the inside flag is set
-    ''' )
-
-    parser.add_argument('-o', '--output',
-                        metavar='<output file>',
-                        default = None,
-                        type=str,
-                        help='write output to a different file')
-
-    parser.add_argument('-i', '--inside',
-                        action='store_true',
-                        default = False,
-                        help='remove CPs inside ROI')
-
-    parser.add_argument('input' ,
-                        metavar = '<pto file>' ,
-                        type = str ,
-                        help = 'pto file to be processed' )
-
-    if len ( sys.argv ) < 2 :
-        parser.print_help()
-        return
-
-    # we parse the arguments into a global variable so we can access
-    # them from everywhere without having to pass them around
-    
-    global args
-    
-    args = parser.parse_args()
-
-    if args.output :
-        print ( 'output: ' , args.output )
-    print ( 'ptofile:' , args.input )
-
-    # first we see if we can open the input file
-
-    ifs = hsi.ifstream ( args.input )
-    if not ifs.good() :
-        raise CropCpError ( 'cannot open input file %s' % args.input )
-
-    pano = hsi.Panorama()
-    success = pano.readData ( ifs )
-    del ifs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'input file %s contains invalid data' % args.input )
-
-    # if a separate output file was chosen, we open it now to avoid
-    # later disappointments
-    
-    if args.output:
-        ofs = hsi.ofstream ( args.output )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open output file %s' % args.output )
-
-    # we've checked the args, now we call crop_cps()
-    
-    crop_cps ( pano , args.inside )
-
-    # if no different output file was specified, overwrite the input
-    
-    if not args.output :
-        ofs = hsi.ofstream ( args.input )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open file %s for output' % args.input )
-
-    success = pano.writeData ( ofs )
-    del ofs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'error writing pano to %s' % args.input )
-    
-    # done.
-    
-    return 0
-
-# are we main? This means we've been called from the command line
-# as a standalone program, so we have to go through the main() function.
-
-if __name__ == "__main__":
-    try:
-        main()
-    except CropCpError as e :
-        print ( 'Run Time Error: %s' % e )
diff --git a/src/hugin_script_interface/plugins/shooting_pattern.py b/src/hugin_script_interface/plugins/shooting_pattern.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/shooting_pattern.py
+++ b/src/hugin_script_interface/plugins/shooting_pattern.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 #    shooting_pattern.py - apply a 6-1-1 shooting pattern to a panorama
@@ -41,8 +39,6 @@
 # @name     6-1-1 Shooting Pattern
 # @description apply a shooting pattern (6 around, 1 up 1 down)
 # @sys win nix mac
-# @api-max 2016.1
-# @api-min 2011.1
 
 # the position routine will apply yaw, pitch to an image
 
diff --git a/src/hugin_script_interface/plugins/top_five.py b/src/hugin_script_interface/plugins/top_five.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/top_five.py
+++ b/src/hugin_script_interface/plugins/top_five.py
@@ -1,11 +1,7 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 # @category Control Points
 # @name     keep 5 CPs per image pair
-# @api-min  2011.1
-# @api-max  2016.1
 
 #    top_five.py - keep the five best CPs for each image pair
 
@@ -66,7 +62,10 @@
 
     # finally we attach the new CP vector to the panorama
     
-    print ( 'keeping %d control points' % len ( cpv ) )
+    print ( 'keeping %d control points:' % len ( cpv ) )
+    for cp in cpv:
+        print ( "%d %d %d %d" % ( cp.x1 , cp.y1 , cp.x2 , cp.y2 ) )
+
     pano.setCtrlPoints ( cpv )
     
     return 0
diff --git a/src/hugin_script_interface/plugins/woa.py b/src/hugin_script_interface/plugins/woa.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/woa.py
+++ b/src/hugin_script_interface/plugins/woa.py
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from __future__ import print_function
@@ -24,8 +23,6 @@
 """
 # @category Control Points
 # @name     Warped Overlap Analysis
-# @api-min  2014.0
-# @api-max  2016.3
 
 # note that if you want to read the script, it's written bottom-up, so the
 # higher-level routines are towards the end.
diff --git a/src/hugin_base/panodata/PanoramaOptions.h b/src/hugin_base/panodata/PanoramaOptions.h
--- a/src/hugin_base/panodata/PanoramaOptions.h
+++ b/src/hugin_base/panodata/PanoramaOptions.h
@@ -240,7 +240,7 @@
             panoProjectionFeaturesQuery(m_projectionFormat, &m_projFeatures);
             resetProjectionParameters();
 
-            outputStacksMinOverlap = 0.7;
+            outputStacksMinOverlap = 0.85;
             outputLayersExposureDiff = 0.5;
         }
 
diff --git a/src/hugin_script_interface/hpi.py b/src/hugin_script_interface/hpi.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/hpi.py
+++ b/src/hugin_script_interface/hpi.py
@@ -1,5 +1,3 @@
-#! /usr/bin/env python
-
 from __future__ import print_function
 
 # hpi.py - dispatcher for hugin plugins
diff --git a/src/hugin_script_interface/plugins-dev/dual_use.py b/src/hugin_script_interface/plugins-dev/dual_use.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins-dev/dual_use.py
+++ b/src/hugin_script_interface/plugins-dev/dual_use.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 gpl = r"""
@@ -23,8 +21,6 @@
 
 # @category Examples
 # @name     Dual Use Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # dual_use will function as a hugin plugin and as a standalone
 # Python script.
diff --git a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
+++ b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 # plugin_skeleton.py - a skeleton for a hugin plugin
 # Copyright (C) 2011  Kay F. Jahnke
 
@@ -18,8 +16,6 @@
 
 # @category Examples
 # @name     Skeleton Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # we use modern type python print statements:
 
diff --git a/src/hugin_script_interface/plugins/crop_cp.py b/src/hugin_script_interface/plugins/crop_cp.py
deleted file mode 100755
--- a/src/hugin_script_interface/plugins/crop_cp.py
+++ /dev/null
@@ -1,337 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-gpl = r"""
-    crop_cp.py - remove CPs from parts of the panorama
-    
-    Copyright (C) 2011  Kay F. Jahnke
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-# @category Control Points
-# @name     Crop Control Points
-# @api-min  2011.1
-# @api-max  2015.1
-
-# crop_cps will function as a hugin plugin and as a standalone
-# Python script. It can also serve as a template for a slightly
-# more involved plugin than the ones in the Examples section.
-
-# Please note that this script tries to use wxPython. This should
-# work on Linux systems that have wxPython istalled, but as far as
-# I know currently it won't work on Windows, and certainly not on
-# Mac OS, where there is currently no hsi/hpi suport. If you want
-# to switch off the use of wxPython, set the default parameter in
-# the entry function to a value different from None, i.e. change
-# def entry ( pano , inside = None ) :
-# to
-# def entry ( pano , inside = False ) :
-
-import os
-import sys
-import hsi
-import math
-
-# we make an exception for run time errors in this script:
-
-class CropCpError ( Exception ) :
-
-    def __init__ ( self , text ) :
-        self.text = text
-
-    def __str__ ( self ) :
-        return self.text
-    
-# some global variables to reduce overhead - we just reuse the same
-# FDiff2D objects every time we call the transforms
-
-transform_in = hsi.FDiff2D(0,0)
-transform_out = hsi.FDiff2D(0,0)
-
-# transform point coordinates using panotools transforms
-# and the global variables for source and target
-
-class to_pano :
-
-    def __init__ ( self , pano , image ) :
-
-        pano_options = pano.getOptions()
-        img = pano.getImage ( image )
-        w = img.getWidth()
-        h = img.getHeight()
-        self.wh = w / 2.0
-        self.hh = h / 2.0
-
-        # image to pano
-
-        self.tf = hsi.Transform()
-        self.tf.createInvTransform ( img , pano_options )
-
-    def transform ( self , p ) :
-
-        # pixel coordinates come in, but have to use center-origin
-        
-        transform_in.x = p[0] - self.wh
-        transform_in.y = p[1] - self.hh
-
-        if self.tf.transform ( transform_out , transform_in ) :
-            return ( transform_out.x , transform_out.y )
-
-        # KFJ 2011-06-19 I've noticed the transform failing
-        # with images that have X, Y or Z values different from 0.
-        # I'm not sure if this is a bug in the transform.
-        
-        print ( 'transform failed for %s' % str ( p ) )
-        return None
-
-# the crop_cps routine is the workhorse of this script. It does the
-# actual work of looking at the CPs and removing the unwanted ones.
-
-def crop_cps ( pano , inside ) :
-
-    pano_options = pano.getOptions()
-
-    size = pano_options.getSize()
-
-    # we need these offsets because pano coordinates are center-origin
-    
-    wh = size.width() / 2.0
-    hh = size.height() / 2.0
-    
-    # that's the ROI of the panorama, in corner-origin
-    
-    roi = pano_options.getROI()
-
-    # out limits, now in center-origin
-    
-    left = roi.left() - wh
-    right = roi.right() - wh
-    top = roi.top() - hh
-    bottom = roi.bottom() - hh
-
-    ni = pano.getNrOfImages()
-    tflist = []
-
-    # we get a list of CPs in pano coordinates. Note that the pano
-    # coordinates are taken from the coordinates in the left image only.
-    
-    for img in range ( ni ) :
-        tflist.append ( to_pano ( pano , img ) )
-
-    # we take the CPVector:
-    
-    cpv = pano.getCtrlPoints()
-    print ( 'found %d CPs' % len ( cpv ) )
-
-    # We want to put the remaining CPs into this CPVector:
-    
-    ncpv = hsi.CPVector()
-
-    for cp in cpv :
-        p = ( cp.x1 , cp.y1 )
-        img = cp.image1Nr
-        tfp = tflist[img].transform ( p )
-        # KFJ 2011-06-17 If the transform fails, keep the CP
-        # - best to be defensive.
-        if tfp is None :
-            ncpv.append ( cp )
-        elif inside : # remove CPs inside ROI (or, keep those outside)
-            if not ( ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) ) :
-                ncpv.append ( cp )
-        else :
-            if ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) :
-                ncpv.append ( cp )
-
-    pano.setCtrlPoints ( ncpv )
-    print ( 'removed %d CPs' % ( len ( cpv ) - len ( ncpv ) ) )
-
-    return 0
-
-# the remainder of the script is administration and deals with running
-# it either as a plugin from hugin or as a standalone CLI program.
-
-# first is the entry routine which is called when this script is used
-# as a plugin from hugin. If the inside parameter is not passed
-# (or passed as 'None') - a dialog will ask whether to remove CPs
-# inside or outside of the ROI. If inside is passed as True, CPs
-# inside the ROI are removed, otherwise those outside.
-# Note that the 'GUI' is primitive - it offers no help or about info,
-# no tool tips etc. - the help could be made from the docstrings of
-# the CLI version below.
-
-def entry ( pano , inside = None ) :
-
-    if inside is None:
-
-    # if we've been called as a plugin (we're not main) and inside is
-    # None, the default, we assume that we're supposed to ask the user
-    # whether to remove the CPs from inside or outside the ROI. If
-    # inside is passed as True or False, we execute without further ado.
-
-        import wx
-
-        # we need a simple dialog box for this purpose which displays
-        # a radio button for the inside/outside choice, plus Okay and Cancel.
-        
-        class crop_cp_dialog ( wx.Dialog ) :
-
-            # excuse my clumsy wxPython ;-)
-            
-            def __init__(self, parent, title):
-
-                wx.Dialog.__init__(self, parent, -1, title, size = ( 200 , 150 ) )
-                choices = [ 'outside ROI' , 'inside ROI' ]
-                # default choice is to remove CPs outdide ROI
-                self.choice = 0
-
-                # we create and position the UI elements                
-                sizer = wx.BoxSizer ( wx.VERTICAL )
-                rb = wx.RadioBox(
-                        self, -1, "", wx.DefaultPosition, wx.DefaultSize,
-                        choices, 2, wx.RA_SPECIFY_COLS
-                        )
-                self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, rb)
-                sizer.Add(rb, 0, wx.ALL, 20)
-                btnsizer = wx.StdDialogButtonSizer()
-                btn = wx.Button(self, wx.ID_OK)
-                btn.SetDefault()
-                btnsizer.AddButton(btn)
-                btn = wx.Button(self, wx.ID_CANCEL)
-                btnsizer.AddButton(btn)
-                btnsizer.Realize()
-                sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
-                self.SetSizer(sizer)
-
-            # what to do when the radio button is operated:
-            def EvtRadioBox(self, event):
-                self.choice = event.GetInt()
-        
-        # make the dialog and show it modally:
-        ccd = crop_cp_dialog ( None , 'Crop CPs' )
-        retval = ccd.ShowModal()
-        # only if Okay was clicked the state of the radio button is used
-        if retval == wx.ID_OK :
-            if ccd.choice == 0 :
-                inside = False
-            else :
-                inside = True
-        # otherwise we cancel the operation and return.
-        else :
-            return 0
-
-    # now the preliminaries are sorted, we can call the workhorse routine.
-    
-    return crop_cps ( pano , inside )
-    
-# the main routine is what's called if this script has been called from
-# the command line. In this case we do the CLI thing, so we parse the
-# argument vector and act accordingly.
-
-def main() :
-
-    # when called from the command line, we import the argparse module.
-    # This may not be part of the standard library on your system.
-    
-    import argparse
-
-    # and create an argument parser.
-    
-    parser = argparse.ArgumentParser (
-        formatter_class=argparse.RawDescriptionHelpFormatter ,
-        description = gpl + '''
-    crop_cp will remove all CPs which are either outside the panorama's ROI
-    or inside it's ROI if the inside flag is set
-    ''' )
-
-    parser.add_argument('-o', '--output',
-                        metavar='<output file>',
-                        default = None,
-                        type=str,
-                        help='write output to a different file')
-
-    parser.add_argument('-i', '--inside',
-                        action='store_true',
-                        default = False,
-                        help='remove CPs inside ROI')
-
-    parser.add_argument('input' ,
-                        metavar = '<pto file>' ,
-                        type = str ,
-                        help = 'pto file to be processed' )
-
-    if len ( sys.argv ) < 2 :
-        parser.print_help()
-        return
-
-    # we parse the arguments into a global variable so we can access
-    # them from everywhere without having to pass them around
-    
-    global args
-    
-    args = parser.parse_args()
-
-    if args.output :
-        print ( 'output: ' , args.output )
-    print ( 'ptofile:' , args.input )
-
-    # first we see if we can open the input file
-
-    ifs = hsi.ifstream ( args.input )
-    if not ifs.good() :
-        raise CropCpError ( 'cannot open input file %s' % args.input )
-
-    pano = hsi.Panorama()
-    success = pano.readData ( ifs )
-    del ifs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'input file %s contains invalid data' % args.input )
-
-    # if a separate output file was chosen, we open it now to avoid
-    # later disappointments
-    
-    if args.output:
-        ofs = hsi.ofstream ( args.output )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open output file %s' % args.output )
-
-    # we've checked the args, now we call crop_cps()
-    
-    crop_cps ( pano , args.inside )
-
-    # if no different output file was specified, overwrite the input
-    
-    if not args.output :
-        ofs = hsi.ofstream ( args.input )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open file %s for output' % args.input )
-
-    success = pano.writeData ( ofs )
-    del ofs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'error writing pano to %s' % args.input )
-    
-    # done.
-    
-    return 0
-
-# are we main? This means we've been called from the command line
-# as a standalone program, so we have to go through the main() function.
-
-if __name__ == "__main__":
-    try:
-        main()
-    except CropCpError as e :
-        print ( 'Run Time Error: %s' % e )
diff --git a/src/hugin_script_interface/plugins/shooting_pattern.py b/src/hugin_script_interface/plugins/shooting_pattern.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/shooting_pattern.py
+++ b/src/hugin_script_interface/plugins/shooting_pattern.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 #    shooting_pattern.py - apply a 6-1-1 shooting pattern to a panorama
@@ -41,8 +39,6 @@
 # @name     6-1-1 Shooting Pattern
 # @description apply a shooting pattern (6 around, 1 up 1 down)
 # @sys win nix mac
-# @api-max 2016.1
-# @api-min 2011.1
 
 # the position routine will apply yaw, pitch to an image
 
diff --git a/src/hugin_script_interface/plugins/top_five.py b/src/hugin_script_interface/plugins/top_five.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/top_five.py
+++ b/src/hugin_script_interface/plugins/top_five.py
@@ -1,11 +1,7 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 # @category Control Points
 # @name     keep 5 CPs per image pair
-# @api-min  2011.1
-# @api-max  2016.1
 
 #    top_five.py - keep the five best CPs for each image pair
 
@@ -66,7 +62,10 @@
 
     # finally we attach the new CP vector to the panorama
     
-    print ( 'keeping %d control points' % len ( cpv ) )
+    print ( 'keeping %d control points:' % len ( cpv ) )
+    for cp in cpv:
+        print ( "%d %d %d %d" % ( cp.x1 , cp.y1 , cp.x2 , cp.y2 ) )
+
     pano.setCtrlPoints ( cpv )
     
     return 0
diff --git a/src/hugin_script_interface/plugins/woa.py b/src/hugin_script_interface/plugins/woa.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/woa.py
+++ b/src/hugin_script_interface/plugins/woa.py
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from __future__ import print_function
@@ -24,8 +23,6 @@
 """
 # @category Control Points
 # @name     Warped Overlap Analysis
-# @api-min  2014.0
-# @api-max  2016.3
 
 # note that if you want to read the script, it's written bottom-up, so the
 # higher-level routines are towards the end.
diff --git a/src/hugin_script_interface/hpi.py b/src/hugin_script_interface/hpi.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/hpi.py
+++ b/src/hugin_script_interface/hpi.py
@@ -1,5 +1,3 @@
-#! /usr/bin/env python
-
 from __future__ import print_function
 
 # hpi.py - dispatcher for hugin plugins
diff --git a/src/hugin_script_interface/plugins-dev/dual_use.py b/src/hugin_script_interface/plugins-dev/dual_use.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins-dev/dual_use.py
+++ b/src/hugin_script_interface/plugins-dev/dual_use.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 gpl = r"""
@@ -23,8 +21,6 @@
 
 # @category Examples
 # @name     Dual Use Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # dual_use will function as a hugin plugin and as a standalone
 # Python script.
diff --git a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
+++ b/src/hugin_script_interface/plugins-dev/plugin_skeleton.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 # plugin_skeleton.py - a skeleton for a hugin plugin
 # Copyright (C) 2011  Kay F. Jahnke
 
@@ -18,8 +16,6 @@
 
 # @category Examples
 # @name     Skeleton Plugin
-# @api-min  2011.1
-# @api-max  2012.0
 
 # we use modern type python print statements:
 
diff --git a/src/hugin_script_interface/plugins/crop_cp.py b/src/hugin_script_interface/plugins/crop_cp.py
deleted file mode 100755
--- a/src/hugin_script_interface/plugins/crop_cp.py
+++ /dev/null
@@ -1,337 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-gpl = r"""
-    crop_cp.py - remove CPs from parts of the panorama
-    
-    Copyright (C) 2011  Kay F. Jahnke
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-# @category Control Points
-# @name     Crop Control Points
-# @api-min  2011.1
-# @api-max  2015.1
-
-# crop_cps will function as a hugin plugin and as a standalone
-# Python script. It can also serve as a template for a slightly
-# more involved plugin than the ones in the Examples section.
-
-# Please note that this script tries to use wxPython. This should
-# work on Linux systems that have wxPython istalled, but as far as
-# I know currently it won't work on Windows, and certainly not on
-# Mac OS, where there is currently no hsi/hpi suport. If you want
-# to switch off the use of wxPython, set the default parameter in
-# the entry function to a value different from None, i.e. change
-# def entry ( pano , inside = None ) :
-# to
-# def entry ( pano , inside = False ) :
-
-import os
-import sys
-import hsi
-import math
-
-# we make an exception for run time errors in this script:
-
-class CropCpError ( Exception ) :
-
-    def __init__ ( self , text ) :
-        self.text = text
-
-    def __str__ ( self ) :
-        return self.text
-    
-# some global variables to reduce overhead - we just reuse the same
-# FDiff2D objects every time we call the transforms
-
-transform_in = hsi.FDiff2D(0,0)
-transform_out = hsi.FDiff2D(0,0)
-
-# transform point coordinates using panotools transforms
-# and the global variables for source and target
-
-class to_pano :
-
-    def __init__ ( self , pano , image ) :
-
-        pano_options = pano.getOptions()
-        img = pano.getImage ( image )
-        w = img.getWidth()
-        h = img.getHeight()
-        self.wh = w / 2.0
-        self.hh = h / 2.0
-
-        # image to pano
-
-        self.tf = hsi.Transform()
-        self.tf.createInvTransform ( img , pano_options )
-
-    def transform ( self , p ) :
-
-        # pixel coordinates come in, but have to use center-origin
-        
-        transform_in.x = p[0] - self.wh
-        transform_in.y = p[1] - self.hh
-
-        if self.tf.transform ( transform_out , transform_in ) :
-            return ( transform_out.x , transform_out.y )
-
-        # KFJ 2011-06-19 I've noticed the transform failing
-        # with images that have X, Y or Z values different from 0.
-        # I'm not sure if this is a bug in the transform.
-        
-        print ( 'transform failed for %s' % str ( p ) )
-        return None
-
-# the crop_cps routine is the workhorse of this script. It does the
-# actual work of looking at the CPs and removing the unwanted ones.
-
-def crop_cps ( pano , inside ) :
-
-    pano_options = pano.getOptions()
-
-    size = pano_options.getSize()
-
-    # we need these offsets because pano coordinates are center-origin
-    
-    wh = size.width() / 2.0
-    hh = size.height() / 2.0
-    
-    # that's the ROI of the panorama, in corner-origin
-    
-    roi = pano_options.getROI()
-
-    # out limits, now in center-origin
-    
-    left = roi.left() - wh
-    right = roi.right() - wh
-    top = roi.top() - hh
-    bottom = roi.bottom() - hh
-
-    ni = pano.getNrOfImages()
-    tflist = []
-
-    # we get a list of CPs in pano coordinates. Note that the pano
-    # coordinates are taken from the coordinates in the left image only.
-    
-    for img in range ( ni ) :
-        tflist.append ( to_pano ( pano , img ) )
-
-    # we take the CPVector:
-    
-    cpv = pano.getCtrlPoints()
-    print ( 'found %d CPs' % len ( cpv ) )
-
-    # We want to put the remaining CPs into this CPVector:
-    
-    ncpv = hsi.CPVector()
-
-    for cp in cpv :
-        p = ( cp.x1 , cp.y1 )
-        img = cp.image1Nr
-        tfp = tflist[img].transform ( p )
-        # KFJ 2011-06-17 If the transform fails, keep the CP
-        # - best to be defensive.
-        if tfp is None :
-            ncpv.append ( cp )
-        elif inside : # remove CPs inside ROI (or, keep those outside)
-            if not ( ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) ) :
-                ncpv.append ( cp )
-        else :
-            if ( left <= tfp[0] <= right ) and ( top <= tfp[1] <= bottom ) :
-                ncpv.append ( cp )
-
-    pano.setCtrlPoints ( ncpv )
-    print ( 'removed %d CPs' % ( len ( cpv ) - len ( ncpv ) ) )
-
-    return 0
-
-# the remainder of the script is administration and deals with running
-# it either as a plugin from hugin or as a standalone CLI program.
-
-# first is the entry routine which is called when this script is used
-# as a plugin from hugin. If the inside parameter is not passed
-# (or passed as 'None') - a dialog will ask whether to remove CPs
-# inside or outside of the ROI. If inside is passed as True, CPs
-# inside the ROI are removed, otherwise those outside.
-# Note that the 'GUI' is primitive - it offers no help or about info,
-# no tool tips etc. - the help could be made from the docstrings of
-# the CLI version below.
-
-def entry ( pano , inside = None ) :
-
-    if inside is None:
-
-    # if we've been called as a plugin (we're not main) and inside is
-    # None, the default, we assume that we're supposed to ask the user
-    # whether to remove the CPs from inside or outside the ROI. If
-    # inside is passed as True or False, we execute without further ado.
-
-        import wx
-
-        # we need a simple dialog box for this purpose which displays
-        # a radio button for the inside/outside choice, plus Okay and Cancel.
-        
-        class crop_cp_dialog ( wx.Dialog ) :
-
-            # excuse my clumsy wxPython ;-)
-            
-            def __init__(self, parent, title):
-
-                wx.Dialog.__init__(self, parent, -1, title, size = ( 200 , 150 ) )
-                choices = [ 'outside ROI' , 'inside ROI' ]
-                # default choice is to remove CPs outdide ROI
-                self.choice = 0
-
-                # we create and position the UI elements                
-                sizer = wx.BoxSizer ( wx.VERTICAL )
-                rb = wx.RadioBox(
-                        self, -1, "", wx.DefaultPosition, wx.DefaultSize,
-                        choices, 2, wx.RA_SPECIFY_COLS
-                        )
-                self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, rb)
-                sizer.Add(rb, 0, wx.ALL, 20)
-                btnsizer = wx.StdDialogButtonSizer()
-                btn = wx.Button(self, wx.ID_OK)
-                btn.SetDefault()
-                btnsizer.AddButton(btn)
-                btn = wx.Button(self, wx.ID_CANCEL)
-                btnsizer.AddButton(btn)
-                btnsizer.Realize()
-                sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
-                self.SetSizer(sizer)
-
-            # what to do when the radio button is operated:
-            def EvtRadioBox(self, event):
-                self.choice = event.GetInt()
-        
-        # make the dialog and show it modally:
-        ccd = crop_cp_dialog ( None , 'Crop CPs' )
-        retval = ccd.ShowModal()
-        # only if Okay was clicked the state of the radio button is used
-        if retval == wx.ID_OK :
-            if ccd.choice == 0 :
-                inside = False
-            else :
-                inside = True
-        # otherwise we cancel the operation and return.
-        else :
-            return 0
-
-    # now the preliminaries are sorted, we can call the workhorse routine.
-    
-    return crop_cps ( pano , inside )
-    
-# the main routine is what's called if this script has been called from
-# the command line. In this case we do the CLI thing, so we parse the
-# argument vector and act accordingly.
-
-def main() :
-
-    # when called from the command line, we import the argparse module.
-    # This may not be part of the standard library on your system.
-    
-    import argparse
-
-    # and create an argument parser.
-    
-    parser = argparse.ArgumentParser (
-        formatter_class=argparse.RawDescriptionHelpFormatter ,
-        description = gpl + '''
-    crop_cp will remove all CPs which are either outside the panorama's ROI
-    or inside it's ROI if the inside flag is set
-    ''' )
-
-    parser.add_argument('-o', '--output',
-                        metavar='<output file>',
-                        default = None,
-                        type=str,
-                        help='write output to a different file')
-
-    parser.add_argument('-i', '--inside',
-                        action='store_true',
-                        default = False,
-                        help='remove CPs inside ROI')
-
-    parser.add_argument('input' ,
-                        metavar = '<pto file>' ,
-                        type = str ,
-                        help = 'pto file to be processed' )
-
-    if len ( sys.argv ) < 2 :
-        parser.print_help()
-        return
-
-    # we parse the arguments into a global variable so we can access
-    # them from everywhere without having to pass them around
-    
-    global args
-    
-    args = parser.parse_args()
-
-    if args.output :
-        print ( 'output: ' , args.output )
-    print ( 'ptofile:' , args.input )
-
-    # first we see if we can open the input file
-
-    ifs = hsi.ifstream ( args.input )
-    if not ifs.good() :
-        raise CropCpError ( 'cannot open input file %s' % args.input )
-
-    pano = hsi.Panorama()
-    success = pano.readData ( ifs )
-    del ifs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'input file %s contains invalid data' % args.input )
-
-    # if a separate output file was chosen, we open it now to avoid
-    # later disappointments
-    
-    if args.output:
-        ofs = hsi.ofstream ( args.output )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open output file %s' % args.output )
-
-    # we've checked the args, now we call crop_cps()
-    
-    crop_cps ( pano , args.inside )
-
-    # if no different output file was specified, overwrite the input
-    
-    if not args.output :
-        ofs = hsi.ofstream ( args.input )
-        if not ofs.good() :
-            raise CropCpError ( 'cannot open file %s for output' % args.input )
-
-    success = pano.writeData ( ofs )
-    del ofs
-    if success != hsi.DocumentData.SUCCESSFUL :
-        raise CropCpError ( 'error writing pano to %s' % args.input )
-    
-    # done.
-    
-    return 0
-
-# are we main? This means we've been called from the command line
-# as a standalone program, so we have to go through the main() function.
-
-if __name__ == "__main__":
-    try:
-        main()
-    except CropCpError as e :
-        print ( 'Run Time Error: %s' % e )
diff --git a/src/hugin_script_interface/plugins/shooting_pattern.py b/src/hugin_script_interface/plugins/shooting_pattern.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/shooting_pattern.py
+++ b/src/hugin_script_interface/plugins/shooting_pattern.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 #    shooting_pattern.py - apply a 6-1-1 shooting pattern to a panorama
@@ -41,8 +39,6 @@
 # @name     6-1-1 Shooting Pattern
 # @description apply a shooting pattern (6 around, 1 up 1 down)
 # @sys win nix mac
-# @api-max 2016.1
-# @api-min 2011.1
 
 # the position routine will apply yaw, pitch to an image
 
diff --git a/src/hugin_script_interface/plugins/top_five.py b/src/hugin_script_interface/plugins/top_five.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/top_five.py
+++ b/src/hugin_script_interface/plugins/top_five.py
@@ -1,11 +1,7 @@
-#!/usr/bin/env python
-
 from __future__ import print_function
 
 # @category Control Points
 # @name     keep 5 CPs per image pair
-# @api-min  2011.1
-# @api-max  2016.1
 
 #    top_five.py - keep the five best CPs for each image pair
 
@@ -66,7 +62,10 @@
 
     # finally we attach the new CP vector to the panorama
     
-    print ( 'keeping %d control points' % len ( cpv ) )
+    print ( 'keeping %d control points:' % len ( cpv ) )
+    for cp in cpv:
+        print ( "%d %d %d %d" % ( cp.x1 , cp.y1 , cp.x2 , cp.y2 ) )
+
     pano.setCtrlPoints ( cpv )
     
     return 0
diff --git a/src/hugin_script_interface/plugins/woa.py b/src/hugin_script_interface/plugins/woa.py
old mode 100755
new mode 100644
--- a/src/hugin_script_interface/plugins/woa.py
+++ b/src/hugin_script_interface/plugins/woa.py
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from __future__ import print_function
@@ -24,8 +23,6 @@
 """
 # @category Control Points
 # @name     Warped Overlap Analysis
-# @api-min  2014.0
-# @api-max  2016.3
 
 # note that if you want to read the script, it's written bottom-up, so the
 # higher-level routines are towards the end.

Reply via email to