# -*- coding: UTF-8 -*-
# ==============================================================================

# ------------------------------------------------------------------------------
# Project: pysiril ( Python SiriL )
#
# This is a library to interface python to Siril.
# ------------------------------------------------------------------------------
#    Author:  M27trognondepomme <pebe92 (at) gmail.com>
#
# This program is provided without any guarantee.
#
# The license is  LGPL-v3
# For details, see GNU General Public License, version 3 or later.
#                        "https://www.gnu.org/licenses/gpl.html"
# ------------------------------------------------------------------------------
from __future__ import absolute_import
__all__=["Wrapper"]
import sys
import os
import re
import re
import time

# ------------------------------------------------------------------------------
class Wrapper:
    def __init__(self, sirilpipe ):

        self.siril       = sirilpipe
        self.tr          = self.siril.tr
        self.param       = 'XXX'

    # --------------------------------------------------------------------------
    def Execute(self, commandes, bEndTest = True):
        return self.siril.Execute(commandes+self.param,bEndTest)

    def GetData(self):
        return self.siril.GetData()

    def InitParam(self):
        self.param  = ''

    def AddParam(self,value,name='',path=False):
        if value != None and path==True : value=value.replace(os.sep,'/')
        if name == None or len(name) <= 1 :
            if value != None :
                self.param+= " " + str(value)
                return True
            return False
        if name[0]=='-' and name[-1]=='=' :
            if value != None :
               self.param+= " " + name + str(value)
               return True
            return False
        if name[0]=='-' :
           if value  :
               self.param+= " " + name
               return True
           return False
        return False

    # --------------------------------------------------------------------------

    def filt_log(self, resultat_cmd):
        log=[]
        for ligne in resultat_cmd :
            if ligne[0:4] == 'log:' :
                log.append(ligne[5:])
        return log

    def filt_status(self, resultat_cmd):
        status=[]
        for ligne in resultat_cmd :
            if ligne[0:7] == 'status:' :
                status.append(ligne)
        return status


    def pourcent_or_value(self, name_filt, filt_value ):
        if filt_value == None :
            return "";
        if type(filt_value) == str :
            return "-" + name_filt + "=" + filt_value + " "
        else:
            return "-" + name_filt + "=" + str(filt_value) + " "

    def AddFiltering(self, filter_fwhm, filter_wfwhm, filter_round, filter_bkg,
                          filter_nbstars,filter_quality,filter_included):
        self.AddParam(filter_fwhm     ,"-filter-fwhm="   )
        self.AddParam(filter_wfwhm    ,"-filter-wfwhm="  )
        self.AddParam(filter_round    ,"-filter-round="  )
        self.AddParam(filter_bkg      ,"-filter-bkg="    )
        self.AddParam(filter_nbstars  ,"-filter-nbstars=")
        self.AddParam(filter_quality  ,"-filter-quality=")
        self.AddParam(filter_included ,"-filter-included")

    def get_level(self,status=True):
        if status is False : return (False,)
        log = self.filt_log(self.GetData())
        resultat=[ ]
        for line in log :
            if not re.match("^.*#",line) :
                continue
            res = re.sub( r"^.*#",'#', line )
            res=res.split(':')
            label=res[0][:-1].lower().replace('layer','').replace(')','')
            rr = res[1].split('(')
            resultat.append( [ label.lower(), eval(rr[0].strip()), eval(rr[1][:-1].strip())] )
        return (status, resultat )

    def setBool(self,value,strFalse,strTrue):
        if value is not None:
            if type(value) is bool or type(value) is int :
                value = strTrue if value else strFalse
        return value
    # ------------------------------------------------------------------------------
    def clean_char(self,chaine):
        chaine=chaine.replace('\\xe0','Ã ')
        chaine=chaine.replace('\\u2212','-')
        chaine=chaine.replace('&lt;',"<")
        chaine=chaine.replace('<a href=',"")
        chaine=chaine.replace('</a>',"")
        chaine=chaine.replace('<i>',"'")
        chaine=chaine.replace('</i>',"'")
        chaine=chaine.replace('<b>','"')
        chaine=chaine.replace('</b>','"')
        chaine=chaine.replace('\\n','\n')
        chaine=chaine.replace('\\"','\"')
        chaine=chaine.replace('""','"')
        return  chaine
    # ------------------------------------------------------------------------------
    def fmt_paragraphe(self,chaine,width=72):
        chaine=self.clean_char(chaine)
        prec=0
        cnt=0
        sortie=''
        memo=''
        for ii in range(len(chaine)) :
            if chaine[ii] == ' ' : prec=cnt
            if chaine[ii] == '\n' :
                sortie+=memo[0:ii] + "\n"
                memo=''
                cnt=0
                prec=0
                continue
            memo+=chaine[ii]
            cnt+=1
            if cnt == width :
                sortie+=memo[0:prec] + "\n"
                memo=memo[prec+1:]
                cnt=len(memo)
                prec=0
        if len(memo) != 0 : sortie+=memo
        return sortie
    # --------------------------------------------------------------------------
    # wrapper des commandes

    def asinh(self,stretch,human=False,offset=None):
        """ Stretches the image using an hyperbolic arcsin transformation

        Syntax     : status=cmd.asinh(stretch, [human=True],[offset])
        Parameters :
            - stretch = strength of the stretch (1..1000)
            - human   = enables using human eye luminous efficiency weights
            - offset  = the normalized pixel value of [0..1]
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted

        Example    :
            status=cmd.asinh(10)
            status=cmd.asinh(100,offset=0.65,human=True)
            status=cmd.asinh(100,offset=0.35)
        """
        self.InitParam()
        self.AddParam(human,'-human')
        self.AddParam(stretch)
        self.AddParam(offset)
        return (self.Execute("asinh"),)


    def autoghs(self,shadowsclip,stretchamount,linked=False,b=None,hp=None,lp=None):
        """ Application of the generalized hyperbolic stretch with a symmetry point

        Syntax     : status=cmd.autoghs(shadowsclip stretchamount, [linked=True],[-b=],[-hp=],[-lp=])
        Parameters :
            - shadowsclip   : shadows clipping point
            - stretchamount : stretch amount
            - linked        : linked channels
            - b             : brightness range (default=13)
            - hp            : HP range (default=0.7)
            - lp            : LP range (default=0)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted

        Example    :
            status=cmd.asinh(10)
            status=cmd.asinh(100,offset=0.65,human=True)
            status=cmd.asinh(100,offset=0.35)

        """
        self.InitParam()
        self.AddParam(linked,'-linked')
        self.AddParam(stretchamount)
        self.AddParam(shadowsclip)
        self.AddParam(b,'-b=')
        self.AddParam(hp,'-hp=')
        self.AddParam(lp,'-lp=')
        return (self.Execute("autoghs"),)

    def autostretch(self,linked=False,shadowsclip=None,targetbg=None):
        """ Auto-stretches the currently loaded image

        Syntax     : status=cmd.autostretch([linked=True], [shadowsclip, [targetbg]])
        Parameters :
            - linked     = True/False => linked channels
            - shadowclip = shadows clipping point (default is -2.8)
            - targetbg   = target background value (range [0, 1], default is 0.25)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted

        Example    :
            status=cmd.autostretch(linked=True)
            status=cmd.autostretch(shadowsclip=-2.8)

        """
        self.InitParam()
        self.AddParam(linked,'-linked')
        if self.AddParam(shadowsclip) :
            self.AddParam(targetbg)
        return (self.Execute("autostretch"),)

    def bg(self):
        """ Returns the background level of the image loaded in memory.

        Syntax     : status=cmd.bg()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = background level per layer
        """
        self.InitParam()
        return self.get_level(self.Execute("bg" , bEndTest = True ))

    def bgnoise(self):
        """ Returns the background noise level.

        Syntax     : status=cmd.bgnoise()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = background noise level
        """
        self.InitParam()
        return self.get_level(self.Execute("bgnoise", bEndTest = True  ))

    def binxy(self,coefficient,sum=False):
        """ Computes the numerical binning of the current image.

        Syntax     :
                    status=cmd.binxy(coefficient,[sum=True])
        Parameters :
            - coefficient = 2 (2x2), 3 (3x3) ...
            - sum         = enable sum of pixels is computed else it is the average
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted

        Example    :
            status=cmd.binxy(2)
            status=cmd.binxy(3,sum=True)

        """
        self.InitParam()
        self.AddParam(coefficient)
        self.AddParam(sum,'-sum')
        return (self.Execute("binxy"),)

    def boxselect(self,x=None,y=None, width=None, height=None,clear=False):
        """ Select an area in the currently loaded image with the arguments
        or get the current selection without argument

        Syntax     :
                    status=cmd.boxselect([clear=True] [x y width height])
                    status=cmd.boxselect()
        Parameters :
            - x,y    = coordinates of the image area
            - width  = width of the image area
            - height = height of the image area
            - clear  = deletes any selection area.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = ( x, y, width,height) if no parameter and a
                          selection is active else ()

        Example    :
            status=cmd.boxselect(2,3,56,35)
            status=cmd.boxselect()
            status=cmd.boxselect(clear=True)
        """
        self.InitParam()
        if  self.AddParam(clear,'-clear') :
            status = (self.Execute("boxselect"))
        else:
            if (x==None) or (y==None) or (width==None) or (height==None) :
                status = self.Execute("boxselect" )
                status1=()
                log = self.filt_log(self.GetData())
                for line in log :
                    if not '[x, y, w, h]' in line : continue
                    rr = re.sub( r"^.*: ",'', line )
                    if rr != None :
                        res=rr.split(' ')
                        status1=(int(res[0]),int(res[1]),int(res[2]),int(res[3]))
                return ( status,status1)
            else:
                self.AddParam(x)
                self.AddParam(y)
                self.AddParam(width)
                self.AddParam(height)
                status = (self.Execute("boxselect "))
        return (status,)

    def calibrate(self,sequencename, bias=None, dark=None,flat=None,
                   cc=None,siglo=None,sighi=None,bpmfile=None,
                   cfa=False,debayer=False, fix_xtrans=False, equalize_cfa=False,
                   opt=False, all=False, prefix=None, fitseq=False ):
        return self.preprocess(sequencename, bias, dark, flat, cc,
                               siglo, sighi, bpmfile, cfa, debayer,
                               fix_xtrans, equalize_cfa, opt, all, prefix,
                               fitseq)

    def calibrate_single(self,imagename, bias=None, dark=None,flat=None,
                   cc=None,siglo=None,sighi=None,bpmfile=None,
                   cfa=False,debayer=False, fix_xtrans=False, equalize_cfa=False,
                   opt=False, prefix=None, fitseq=False ):
        return self.preprocess_single(imagename, bias, dark, flat, cc,
                                      siglo, sighi, bpmfile, cfa, debayer,
                                      fix_xtrans, equalize_cfa, opt, prefix,
                                      fitseq)

    def capabilities(self):
        """ Returns Lists Siril capabilities, based on compilation and runtime.

        Syntax     : status=cmd.capabilities()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = capabilities
        """
        self.InitParam()
        status = self.Execute("capabilities"  )
        if status is False : return (False,)
        return (status, self.filt_log(self.GetData())[1:] )

    def catsearch(self,star_name):
        """ Request SIMBAD server for particular photometric magnitude (BVRIJ), the
            argument is a star name

        Syntax     : status=cmd.catsearch(star_name)
        Parameters : star_name
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = log
        """
        self.InitParam()
        self.AddParam(star_name)
        status = self.Execute("catsearch" )
        if status is False : return (False,)
        return (status, self.filt_log(self.GetData())[1:] )

    def cd(self,dirname):
        """ Sets the new current working directory.

        Syntax     : status=cmd.cd(directory)
        Parameters : directory
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Examples   :
           cmd.cd('~/M42')
           cmd.cd('../OIII 2x2/')
        """
        self.InitParam()
        os.chdir(dirname)
        return (self.Execute("cd '" + dirname.replace(os.sep,'/') + "'"),)

    def cdg(self):
        """ Return the coordinates of the center of gravity of the image

        Syntax     : status=cmd.cdg()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = (x,y)
        """
        self.InitParam()
        status = self.Execute("cdg", bEndTest = True  )
        if status is False : return (False,)
        log = self.filt_log(self.GetData())
        res = log[1].replace( ' ', '').split('(')[1].split(',')
        return (status,(eval(res[0]), eval(res[1][:-1])) )

    def clahe(self, cliplimit, tileSize):
        """ Equalizes the histogram of an image using Contrast Limited Adaptive
        Histogram Equalization.

        Syntax     : status=cmd.clahe(cliplimit, tileSize)
        Parameters :
            - cliplimit= sets the threshold for contrast limiting.
            - tilesize = sets the size of grid for histogram equalization.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted

        Example    :
            status=cmd.clahe(0.8,8)
        """
        self.InitParam()
        self.AddParam(cliplimit)
        self.AddParam(tileSize)
        return (self.Execute("clahe"),)

    def close(self):
        """ Properly closes the opened image and the opened sequence, if any

        Syntax     : status=cmd.close()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("close"),)

    def convert(self,basename, debayer=False, fitseq=False, ser=False, start=None, out=None):
        """ Convert all images in a known format into Siril's FITS images.

        Syntax     : status=cmd.convert(basename,[debayer=True],[fitseq=True],[ser=True],[start=index],[out=filename])
        Parameters :
            - basename = new sequence basename
            - debayer  = set to True to debayerise
            - fitseq   = set to True to save as multi-image fit file
            - ser      = set to True to save as ser file
            - start    = starting index of new sequence
            - out      = output folder
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(basename)
        self.AddParam(debayer,'-debayer')
        self.AddParam(fitseq ,'-fitseq' )
        self.AddParam(ser    ,'-ser'    )
        self.AddParam(start  ,'-start=' )
        self.AddParam(out    ,'-out='   ,path=True)
        return (self.Execute("convert"),)

    def convertraw(self,basename, debayer=False, fitseq=False, ser=False, start=None, out=None):
        """ Convert DSLR RAW files into Siril's FITS images or a FITS sequence (single image)

        Syntax     : status=cmd.convertraw(basename,[debayer=True],[fitseq=True],[ser=True],[start=index],[out=filename])
        Parameters :
            - basename = new sequence basename
            - debayer  = set to True to debayerise
            - fitseq   = set to True to save as multi-image fit file
            - ser      = set to True to save as ser file
            - start    = starting index of new sequence
            - out      = output folder
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(basename)
        self.AddParam(debayer,'-debayer')
        self.AddParam(fitseq ,'-fitseq' )
        self.AddParam(ser    ,'-ser'    )
        self.AddParam(start  ,'-start=' )
        self.AddParam(out    ,'-out='   ,path=True)
        return (self.Execute("convertraw"),)

    def cosme(self,filename):
        """ cosmetic correction

        Syntax     : status=cmd.cosme(filename)
        Parameters : filename = list of point  (*.lst)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        if filename : filename=filename.replace(os.sep,'/')
        self.InitParam()
        self.AddParam(filename)
        return (self.Execute("cosme"),)

    def cosme_cfa(self,filename):
        """ cosmetic correction on CFA image

        Syntax     : status=cmd.cosme_cfa(filename)
        Parameters : filename = list of cosmetic points  (*.lst)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("cosme_cfa"),)

    def crop(self,x=None,y=None, width=None, height=None):
        """ Crops to a selected area of the loaded image
        if no argument then use the current selection (BOXSELECT command)

        Syntax     : status=cmd.crop([x, y, width, height])
        Parameters :
            - x,y   = coordinates of the image area
            - width = width of the image area
            - height= height of the image area
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        if (x!=None) and (y!=None) and (width!=None) and (height!=None) :
            self.AddParam(x)
            self.AddParam(y)
            self.AddParam(width)
            self.AddParam(height)
        return (self.Execute("crop"),)

    def denoise(self,nocosmetic=False,mod=None, vst=False, da3d=False, sos=None, rho=None,indep=False):
        """ Denoises the image using the non-local Bayesian algorithm

        Syntax     : status=cmd.denoise([-nocosmetic],[-mod=m],[ -vst | -da3d | -sos=n [-rho=r]],[-indep] )
        Parameters :
            - nocosmetic = disable cosmetic correction
            - mod        =  modulation value
            - vst        = apply the generalised Anscombe variance stabilising transform prior to NL-Bayes
            - da3d       = enable Data-Adaptive Dual Domain Denoising
            - sos        = number of iterations of Strengthen-Operate-Subtract (SOS) denoise boosting
            - rho        = optional used by the SOS booster
            - indep      = used to prevent this by denoising each channel separately.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(nocosmetic,'-nocosmetic')
        self.AddParam(mod       ,'-mod='      )
        self.AddParam(vst       ,'-vst'       )
        self.AddParam(da3d      ,'-da3d'      )
        if self.AddParam(sos    ,'-sos='      ):
            self.AddParam(rho   ,'-rho='      )
        self.AddParam(indep     ,'-indep')
        return (self.Execute("denoise"),)

    def dumpheader(self):
        """ Returns Dumps the FITS header.

        Syntax     : status=cmd.dumpheader()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = Dumps the FITS header of the current image
        """
        self.InitParam()
        status = self.Execute("dumpheader"  )
        if status is False : return (False)
        return (status, self.filt_log(self.GetData())[1:] )

    def entropy(self):
        """ Computes the entropy of the opened image

        Syntax     : status=cmd.entropy()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = entropy value
        """
        self.InitParam()
        status = self.Execute("entropy", bEndTest = True  )
        if status is False : return (False)
        log = self.filt_log(self.GetData())[1].split(':')
        return (status, float(log[-1]) )

    def exit(self):
        """ Quits the application.

        Syntax     : status=cmd.exit()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        return (self.Execute("exit"))

    def extract(self,NbPlane):
        """ Extracts NbPlane Planes of Wavelet domain.

        Syntax     : status=cmd.extract(NbPlane)
        Parameters :
            - NbPlane = plane number
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(NbPlane)
        return (self.Execute("extract"),)

    def extract_Green(self):
        """ Extracts green signal from the currently loaded CFA image.

        Syntax     : status=cmd.extract_Green()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("extract_Green"),)


    def extract_Ha(self):
        """Extracts H-alpha signal from the currently loaded CFA image.

        Syntax     : status=cmd.extract_Ha()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("extract_Ha"),)

    def extract_HaOIII(self,resample=None):
        """ Extracts Ha and OIII signals from a CFA image.

        Syntax     : status=cmd.extract_HaOIII([-resample={ha|oiii}])
        Parameters : "resample={'ha'|'oiii'}" sets whether to upsample
                     the Ha image or downsample the OIII image.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(resample,'-resample=')
        return (self.Execute("extract_HaOIII"),)

    def fdiv(self,filename, scalar):
        """ Divides the image in memory by the image given in argument.

        Syntax     : status=cmd.fdiv(filename, scalar)
        Parameters :
            - filename = image file
            - scalar   = multiplier factor
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        self.AddParam(scalar)
        return (self.Execute("fdiv"),)

    def ffill(self,value,x=None,y=None, width=None, height=None):
        """ Same command than FILL but this is a symmetric fill of a region
        defined by the mouse. Used to process an image in the Fourier (FFT) domain.

        Syntax     : status=cmd.ffill(value,[x y width height])
        Parameters :
            - value  = pixels having the "value" intensity expressed in ADU
            - x,y    = coordinates of the image area
            - width  = width of the image area
            - height = height of the image area
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(value)
        if (x!=None) and (y!=None) and (width!=None) and (height!=None) :
            self.AddParam(x)
            self.AddParam(y)
            self.AddParam(width)
            self.AddParam(height)
        return (self.Execute("ffill"),)

    def fftd(self,modulus, phase):
        """ Applies a Fast Fourier Transform to the image loaded in memory.

        Syntax     : status=cmd.fftd(modulus, phase)
        Parameters :
            - modulus = modulus filename
            - phase   = phase filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(modulus)
        self.AddParam(phase)
        return (self.Execute("fftd"))

    def ffti(self,modulus, phase):
        """ Fast Fourier transformation inverse: The modulus and phase used are the files given
        in argument.

        Syntax     : status=cmd.ffti(modulus, phase)
        Parameters :
            - modulus= modulus filename
            - phase  = phase filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(modulus)
        self.AddParam(phase)
        return (self.Execute("ffti"),)

    def fill(self,value,x=None,y=None, width=None, height=None):
        """ Fills the whole current image (or selection) with pixels having the
        value intensity.

        Syntax     : status=cmd.fill(value, [x y width height])
        Parameters :
            - value  = pixels having the "value" intensity expressed in ADU
            - x,y    = coordinates of the image area
            - width  = width of the image area
            - height = height of the image area
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(value)
        if (x!=None) and (y!=None) and (width!=None) and (height!=None) :
            self.AddParam(x)
            self.AddParam(y)
            self.AddParam(width)
            self.AddParam(height)
        return (self.Execute("fill"),)

    def find_cosme(self,cold_sigma, hot_sigma):
        """ This command applies an automatic detection of cold and hot pixels
        following the threshold written in arguments.

        Syntax     : status=cmd.find_cosme(cold_sigma, hot_sigma)
        Parameters :
            - cold_sigma = threshold of cold pixels
            - hot_sigma  = threshold of hot pixels
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(cold_sigma)
        self.AddParam(hot_sigma)
        return (self.Execute("find_cosme"),)

    def find_cosme_cfa(self,cold_sigma, hot_sigma):
        """ Same command than FIND_COSME but for monochromatic CFA images.

        Syntax     : status=cmd.find_cosme_cfa(cold_sigma, hot_sigma)
        Parameters :
            - cold_sigma = threshold of cold pixels
            - hot_sigma  = threshold of hot pixels
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(cold_sigma)
        self.AddParam(hot_sigma)
        return (self.Execute("find_cosme_cfa"),)

    def find_hot(self, filename, cold_sigma, hot_sigma):
        """ The command provides a list file (format text) in the
        working directory which contains the coordinates of the pixels which
        have an intensity "hot_sigma" times higher and "cold_sigma" lower than
        standard deviation. We generally use this command on a master-dark file.

        Syntax     : status=cmd.find_hot(filename,cold_sigma, hot_sigma)
        Parameters :
            - filename   = filename containing a  list of cold and hot pixels
            - cold_sigma = threshold of cold pixels
            - hot_sigma  = threshold of hot pixels
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        self.AddParam(cold_sigma)
        self.AddParam(hot_sigma)
        return (self.Execute("find_hot"),)

    def findstar(self,out=None,layer=None,maxstars=None):
        """ Detects stars in the currently loaded image, having a level greater than a threshold computed by Siril.

        Syntax     : status=cmd.findstar( [out=],[layer=],[maxstars=])
        Parameters :
            - out      = save the results to the given path.
            - layer    = specifies the layer onto which the detection is performed (for color images only).
            - maxstars = limit the max number of stars detected
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(out,"-out=",path=True)
        self.AddParam(layer,"-layer=")
        self.AddParam(maxstars,"-maxstars=")
        return (self.Execute("findstar"),)

    def fix_xtrans(self):
        """ Fixes the Fujifilm X-Trans Auto Focus pixels.

        Syntax     : status=cmd.fix_xtrans()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("fix_xtrans"),)

    def fixbanding(self,amount , sigma, vertical=False):
        """ Tries to remove the canon banding.

        Syntax     : status=fixbanding(amount, sigma,[vertical=True])
        Parameters :
            - amount  = defines the amount of correction.
            - sigma   = defines a protection level of the algorithm, higher sigma gives higher protection
            - vertical= enables to perform vertical banding removal
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(amount)
        self.AddParam(sigma)
        self.AddParam(vertical,"-vertical")
        return (self.Execute("fixbanding"),)

    def fmedian(self,ksize, modulation):
        """ Performs a median filter of size ksize x ksize (ksize MUST be odd)
        to the original image with a modulation parameter.

        Syntax     : status=cmd.fmedian(ksize, modulation)
        Parameters :
            - ksize
            - modulation
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(ksize)
        self.AddParam(modulation)
        return (self.Execute("fmedian"),)

    def fmul(self,scalar):
        """ Multiplies the loaded image by the scalar given in argument.

        Syntax     : status=cmd.fmul(scalar)
        Parameters :
            - scalar
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(scalar)
        return (self.Execute("fmul"),)

    def gauss(self,sigma):
        """ Performs a Gaussian filter with the given sigma.

        Syntax     : status=cmd.gauss(sigma)
        Parameters :
            - sigma
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sigma)
        return (self.Execute("gauss"),)

    def get(self,variable=None,a=False,A=False):
        """ Returns Get setting values

        Syntax     : status=cmd.get([variable] | [a=True] | [A=True] )
        Parameters :
            - variable = get the variable value
            - a        = list all variables (name and value list)
            - A        = detailed list all variables
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = values
        Example   :
            status=cmd.get(a=True)
            status=cmd.get(A=True)
            status=cmd.get("core.rgb_aladin")
        """
        self.InitParam()
        if not self.AddParam(variable) :
            if not self.AddParam(A,"-A") :
                self.AddParam(a,"-a")
        status = self.Execute("get")
        if status is False : return (False,)
        log = self.filt_log(self.GetData())[1:]
        var={}
        delimiter="="
        for line in log:
            nom,*valeurs=line.split(delimiter)
            nom=nom.strip()
            valeur=""
            for vv in valeurs : valeur += delimiter + vv
            valeur=valeur[1:].strip() # delete first delimiter
            var[nom]=valeur
        return (status, var )

    def getref(self,sequencename):
        """ Prints information about the reference image of the sequence given
        in argument. First image has index 0

        Syntax     : status=cmd.getref(sequencename )
        Parameters :
            - sequencename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = values
        """
        self.InitParam()
        self.AddParam(sequencename)
        status = self.Execute("getref")
        if status is False : return (False,)
        log = self.filt_log(self.GetData())[1:]
        var=0
        delimiter=" "
        for line in log:
            var=line.split(delimiter)[-1]
        return (status, var )

    def ght(self, D, B=None, LP=None, SP=None, HP=None,channels=None,human=False,even=False,independent=False):
        """ Generalised hyperbolic stretch based on the work of the ghsastro.co.uk
        team.

        Syntax     : status=cmd.ght(D, [B], [LP], [SP], [HP],[channels], [human=True]|[even=True]|[independent=True])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.ght(1,-1,0.15,0.75,1)
            status=cmd.ght(1,-1,0.15,0.75,1,channels=2,even=True)
            status=cmd.ght(1,-1,0.15,0.75,1,human=True) )
            status=cmd.ght(1,-1,0.15,0.75,1,independent=True)
        """
        self.InitParam()
        self.AddParam(D ,"-D=")
        self.AddParam(B ,"-B=" )
        self.AddParam(LP,"-LP=")
        self.AddParam(SP,"-SP=")
        self.AddParam(HP,"-HP=")
        self.AddParam(channels)
        if not self.AddParam(human,"-human")  :
            if not self.AddParam(even,"-even")  :
                self.AddParam(independent,"-independent")
        return (self.Execute("ght"),)

    def grey_flat(self):
        """ The function equalizes the mean intensity of RGB layers in a CFA images.

        Syntax     : status=cmd.grey_flat()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("grey_flat"),)

    def help(self, name=None):
        """ help on SiriL commands.

        Syntax     : status=cmd.help( name )
                     status=cmd.help(  )
        Parameters :
            - name = command name
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(name)
        status = self.Execute("help")
        if not status : return ( False,)

        log = self.filt_log(self.GetData())[1:]

        resultat=""
        if name is not None: resultat+="="*80+"\n"
        for chaine in log :
            if name is None:
                resultat += chaine + "\n"
            else:
                resultat+=self.fmt_paragraphe(chaine) + "\n\n"

        if name is not None: resultat+="="*80+"\n"
        print(resultat)
        return ( True,  )

    def histo(self,layer=0):
        """ Calculates the histogram of the image layer in memory and produces
        file histo_[layer name].dat in the working directory.

        Syntax     : status=cmd.histo( layer )
        Parameters :
            - layer = 0, 1 or 2 with 0=red, 1=green and 2=blue.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(layer)
        return (self.Execute("histo" ),)

    def iadd(self,filename):
        """ Adds the image in memory to the image designed in argument. Please
        check that the image is in the working directory.

        Syntax     : status=cmd.iadd(filename)
        Parameters :
            - filename = image to add
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("iadd"),)

    def idiv(self,filename):
        """ Divides the image in memory by the image given in argument. Please
        check that the image is in the working directory. See also fdiv.

        Syntax     : status=cmd.idiv(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("idiv"),)

    def imul(self,filename):
        """ Multiplies the image in memory by the image given in argument. Please
        check that the image is in the working directory. See also fdiv.

        Syntax     : status=cmd.imul(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("imul"),)

    def invght(self, D,  B=None, LP=None, SP=None, HP=None,channels=None,human=False,even=False,independent=False ):
        """ Inverse generalised hyperbolic stretch based on the work of the
        ghsastro.co.uk team.

        Syntax     : status=cmd.invght(D,  [B], [LP], [SP], [HP],
                                       [channels], [human=True]|[even=True]|[independent=True])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.invght(1,-1,0.15,0.75,1)
            status=cmd.invght(1,-1,0.15,0.75,1,channels=2,even=True)
            status=cmd.invght(1,-1,0.15,0.75,1,human=True) )
            status=cmd.invght(1,-1,0.15,0.75,1,independent=True)
        """
        self.InitParam()
        self.AddParam(D ,"-D=")
        self.AddParam(B ,"-B=" )
        self.AddParam(LP,"-LP=")
        self.AddParam(SP,"-SP=")
        self.AddParam(HP,"-HP=")
        self.AddParam(channels)
        if not self.AddParam(human,"-human")  :
            if not self.AddParam(even,"-even")  :
                self.AddParam(independent,"-independent")
        return (self.Execute("invght"),)

    def invmodasinh(self, D, LP=None, SP=None, HP=None,channels=None,human=False,even=False,independent=False):
        """ Inverse generalised arcsinh stretch based on the work of the
        ghsastro.co.uk team. This is similar to the simple asinh stretch but
        offers additional parameters for fine tuning.

        Syntax     : status=cmd.invmodasinh( D, LP, SP, HP,[channels], [human=True]|[even=True]|[independent=True])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.invmodasinh(1,0.15,0.75,1)
            status=cmd.invmodasinh(1,0.15,0.75,1,channels=2,even=True)
            status=cmd.invmodasinh(1,0.15,0.75,1,human=True) )
            status=cmd.invmodasinh(1,0.15,0.75,1,independent=True)
        """
        self.InitParam()
        self.AddParam(D , "-D=")
        self.AddParam(LP, "-LP=")
        self.AddParam(SP, "-SP=")
        self.AddParam(HP, "-HP=")
        self.AddParam(channels)
        if not self.AddParam(human,"-human")  :
            if not self.AddParam(even,"-even")  :
                self.AddParam(independent,"-independent")
        return (self.Execute("invmodasinh"),)

    def invmtf(self, low, mid, high, channels=None ):
        """ Inverse of the midtones transfer function.

        Syntax     : status=cmd.invmtf(low, mid, high, [channels])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.invmtf(0.2,0.5,0.8)
            status=cmd.invmtf(0.2,0.5,0.8,channels=1)
        """
        self.InitParam()
        self.AddParam(low)
        self.AddParam(mid)
        self.AddParam(high)
        self.AddParam(channels)
        return (self.Execute("invmtf"),)

    def isub(self,filename):
        """ Substracts the image in memory by the image designed in argument. Please
        check that the image is in the working directory.

        Syntax     : status=cmd.isub(filename)
        Parameters :
            - filename = image to substract
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("isub"),)

    def jsonmetadata(self,FITS_file,stats_from_loaded=False,nostats=False,out=None):
        """ Substracts the image in memory by the image designed in argument. Please
        check that the image is in the working directory.

        Syntax     : status=cmd.jsonmetadata(FITS_file,[stats_from_loaded=True], [nostats=True], [-out=])
        Parameters :
            - filename = image to substract
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(FITS_file,path=True)
        self.AddParam(stats_from_loaded,"-stats_from_loaded")
        self.AddParam(nostats,"-nostats")
        self.AddParam(out,"-out=",path=True)
        return (self.Execute("jsonmetadata"))

    #  TODO light_curve
    '''
    def light_curve(self,sequencename,channel,ninastars=None,at=None,wcs=None,refat=None,refwcs=None):
        """ Analyse several stars in a sequence of images and produce a light curve
        for one, calibrated by the others.

        Syntax     : status=cmd.light_curve(sequencename, channel,
                             { ninastars=file | { at=x,y | wcs=ra,dec }
                             { refat=x,y | refwcs=ra,dec })
        Parameters :
            - sequencename :
            - ...
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        sequencename=sequencename.replace(os.sep,'/')
        if ninastars : ninastars=ninastars.replace(os.sep,'/')
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(channel)
        if not self.AddParam(ninastars,"-ninastars=") :

        parameters= # ne pas entourer de ' '
        parameters+= " " + str(channel)
        if ninastars != None  : parameters+= " -ninastars=" +  out.replace(os.sep,'/')  # ne pas entourer de ' '
        if at != None  : parameters+= " -at=" + at
        if wcs != None  : parameters+= " -wcs=" + wcs
        if refat != None  : parameters+= " -refat=" + refat
        if refwcs != None  : parameters+= " -refwcs=" + refwcs
        return (self.Execute("isub  " + parameters ))
    '''

    def linear_match(self, reference, low, high):
        """ Computes a linear function between a reference image and a target.

        Syntax     : status=cmd.linear_match(reference, low, high)
        Parameters :
            -reference = reference image
            - low      = low threshold
            - high     = high threshold
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.linear_match('r_C0', 0.15,0.85)
        """
        self.InitParam()
        self.AddParam(reference,path=True)
        self.AddParam(low)
        self.AddParam(high)
        return (self.Execute("linear_match"),)

    def link(self,basename, start=None,out=None):
        """ Link all FITS images in the working directory with the basename given
        in argument. If no symbolic link could be created, files are copied.
        It is possible to convert files in another directory with the "out" option.

        Syntax     : status=cmd.link(basename,[start=index],[out=])
        Parameters :
            - basename = output basename
            - start    = index of the first image
            - out      = output directory
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(basename)
        self.AddParam(start,"-start=")
        self.AddParam(out,"-out=",path=True)
        return (self.Execute("link"),)

    def linstretch(self,BP,channels=None):
        """ Stretches the image linearly to a new black point BP.


        Syntax     : status=cmd.linstretch(BP,[channels=])
        Parameters :
            - BP       =  the new black point to stretch to
            - channels = specify the channels to apply the stretch
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.linstretch(0.12,channels='RG')
        """
        self.InitParam()
        self.AddParam(BP)
        self.AddParam(channels,"-channels=")
        return (self.Execute("linstretch"),)

    def livestack(self, filename):
        """ Process the provided image for live stacking. Only possible after START_LS

        Syntax     : status=cmd.livestack(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("livestack"),)

    def load(self,filename):
        """ Loads the image filename;
        Syntax     : status=cmd.load(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("load"),)

    def log(self):
        """ Computes and applies a logarithmic scale to the current image.

        Syntax     : status=cmd.log()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("log"),)

    # TODO makepsf
    #def makepsf(self):
    #    pass

    def merge(self, *list_seq):
        """ Merges several sequences of the same type (FITS images, FITS sequence or SER)

        Syntax     : status=cmd.merge(output_sequence, seq ,... )
        Parameters :
            - list_seq = list of sequences to merge
            - output sequence  is the  last file of the list of sequences
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        seq_to_merge=""
        for seq in list_seq : self.AddParam(seq)
        return (self.Execute("merge"),)

    def merge_cfa(self, file_CFA0,file_CFA1,file_CFA2,file_CFA3,bayerpattern='RGGB'):
        """ Builds a Bayer masked colour image from 4 separate images containing
        the data from Bayer subchannels CFA0, CFA1, CFA2 and CFA3.

        Syntax     : status=cmd.merge_cfa( file_CFA0,file_CFA1,file_CFA2,file_CFA3,bayerpattern )
        Parameters :
            - file_CFA0,
              file_CFA1,
              file_CFA2,
              file_CFA3= Bayer subchannels CFA0, CFA1, CFA2 and CFA3
            - bayerpattern=Bayer matrix pattern
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(file_CFA0,path=True)
        self.AddParam(file_CFA1,path=True)
        self.AddParam(file_CFA2,path=True)
        self.AddParam(file_CFA3,path=True)
        self.AddParam(bayerpattern)
        return ( self.Execute("merge_cfa"), )

    def mirrorx(self,bottomup=False):
        """ Rotates the image around a vertical axis.

        Syntax     : status=cmd.mirrorx( [bottomup=True])
        Parameters :
            - bottomup = flip it if it's not already bottom-up
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(bottomup,"-bottomup")
        return (self.Execute("mirrorx"),)

    def mirrorx_single(self,imagename):
        """Flips the image about the vertical axis, only if needed (if it's not already bottom-up).

        Syntax     : status=cmd.mirrorx_single( imagename )
        Parameters :
            - imagename = imag to flip
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(imagename,path=True)
        return (self.Execute("mirrorx_single"),)

    def mirrory(self):
        """ Rotates the image around a horizontal axis.

        Syntax     : status=cmd.mirrory()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("mirrory"),)

    def modasinh(self, D, LP=None, SP=None, HP=None,channels=None ,human=False,even=False,independent=False):
        """ Modified arcsinh stretch based on the work of the ghsastro.co.uk team.
        This is similar to the simple asinh stretch but offers additional
        parameters for fine tuning.

        Syntax     : status=cmd.modasinh( D, [LP], [SP], [HP],
                                         [channels], [human=True]|[even=True]|[independent=True])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.modasinh(1,0.15,0.75,1)
            status=cmd.modasinh(1,0.15,0.75,1,channels=2,even=True)
            status=cmd.modasinh(1,0.15,0.75,1,human=True) )
            status=cmd.modasinh(1,0.15,0.75,1,independent=True)
        """
        self.InitParam()
        self.AddParam(D,"-D=")
        self.AddParam(LP,"-LP=")
        self.AddParam(SP,"-SP=")
        self.AddParam(HP,"-HP=")
        self.AddParam(channels)
        if not self.AddParam(human,"-human")  :
            if not self.AddParam(even,"-even")  :
                self.AddParam(independent,"-independent")
        return (self.Execute("modasinh"),)

    def mtf(self, low, mid, high,channels=None):
        """ Applies midtones transfer function to the current loaded image.
        Syntax     : status=cmd.mtf( low, midtone , high, [channels])
        Parameters :
            - low
            - midtone
            - high
            - channels
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.mtf(0.2,0.5,0.8)
            status=cmd.mtf(0.2,0.5,0.8,channels='R')
        """
        self.InitParam()
        self.AddParam(low)
        self.AddParam(mid)
        self.AddParam(high)
        self.AddParam(channels)
        return (self.Execute("mtf"),)

    def neg(self):
        """ Shows the negative view of the current image.

        Syntax     : status=cmd.neg()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("neg"),)

    def nozero(self, level):
        """ Replaces null values by level values. Useful before an idiv or fdiv
        operation.

        Syntax     : status=cmd.nozero( level )
        Parameters :
            - level = new value of null pixel
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(level)
        return (self.Execute("nozero"),)

    def offset(self, value):
        """ Adds the constant value to the current image.

        Syntax     : status=cmd.offset( level )
        Parameters :
            - value= offset value
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(value)
        return (self.Execute("offset"),)

    def parse(self, str, r=False):
        """ Parses the string "str" using the information contained in the header
        of the image currently loaded.

        Syntax     : status=cmd.parse( str, [r=True] )
        Parameters :
            - str = the string to parse
            - r   = specifies the string is to be interpreted in read mode.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(str)
        self.AddParam(r,"-r")
        return (self.Execute("parse"),)

    def pcc(self, center_coords=None, noflip=False, platesolve=False,
                  focal=None, pixelsize=None,limitmag=None,catalog=None,
                  downscale=False):
        """ Run the Photometric Color Correction on the loaded image.

        Syntax     : status=cmd.pcc([center_coords],[noflip=True],
                                    [platesolve=True],[focal=],[pixelsize=],
                                    [limitmag=[+-]], [catalog=True],
                                    [downscale=True])
        Parameters :
            - center_coords= approximate image center coordinates
            - noflip       =  disable flip during the plate solving operation.
            - platesolve   = force the plate solving to be remade
            - focal        = focal length if no metadata
            - pixelsize    = pixel size if no metadata
            - limitmag     = limit magnitude of stars
            - catalog      = choice of the star catalog
            - downscale    = downsampling the image
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(center_coords)
        if self.AddParam(platesolve, "-platesolve"):
            self.AddParam(noflip   , "-noflip"    )
            self.AddParam(focal    , "-focal="    )
            self.AddParam(pixelsize, "-pixelsize=")
            self.AddParam(limitmag , "-limitmag=" )
            self.AddParam(catalog  , "-catalog="  )
            self.AddParam(downscale, "-downscale")
        return (self.Execute("pcc"),)

    def platesolve(self, center_coords=None, noflip=False, platesolve=False,
                   focal=None, pixelsize=None,limitmag=None,catalog=None,
                   localasnet=False, downscale=False):
        """ Plate solve the loaded image.

        Syntax     : status=cmd.platesolve([center_coords],[noflip=True],
                                [platesolve=True], [focal=],[pixelsize=],
                                [limitmag=[+-]], [catalog=],
                                [localasnet=True],[-downscale=True])
        Parameters :
            - center_coords= approximate image center coordinates
            - noflip       =  disable flip during the plate solving operation.
            - platesolve   = force the plate solving to be remade
            - focal        = focal length if no metadata
            - pixelsize    = pixel size if no metadata
            - limitmag     = limit magnitude of stars
            - catalog      = choice of the star catalog
            - localasnet   = astrometry.net's local solve-field
            - downscale    = downsampling the image
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(center_coords)
        if self.AddParam(platesolve, "-platesolve"):
            self.AddParam(noflip    , "-noflip"     )
            self.AddParam(focal     , "-focal="     )
            self.AddParam(pixelsize , "-pixelsize=" )
            self.AddParam(limitmag  , "-limitmag="  )
            self.AddParam(catalog   , "-catalog="   )
            self.AddParam(localasnet, "-localasnet")
            self.AddParam(downscale , "-downscale" )
        return (self.Execute("platesolve"),)

    def pm(self, expression=None, rescale=False, low=None, high=None):
        """ This command evaluates the expression given in argument as in PixelMath
        tool.

        Syntax     : status=cmd.pm(expression,[rescale=(low,high)])
        Parameters :
            - expression         = math expression
            - rescale=(low,high) =  enable rescale operation.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.pm("$r_C0$ * 0.5 + $r_C1$ * 0.75 - $r_C2$ * 0.25")
            status=cmd.pm("$r_C0$ * 0.5", rescale=True)
            status=cmd.pm("$r_C0$ * 0.5", rescale=True,low=0.1,high=0.85)
        """
        if expression[0] != '"' : expression= '"' + expression
        if expression[-1] != '"' : expression= expression + '"'
        self.InitParam()
        self.AddParam(expression)
        if self.AddParam(rescale,"-rescale") :
            self.AddParam(low)
            self.AddParam(high)

        return (self.Execute("pm"),)

    def preprocess(self,sequencename, bias=None, dark=None,flat=None,
                   cc=None,siglo=None,sighi=None,bpmfile=None,
                   cfa=False,debayer=False, fix_xtrans=False, equalize_cfa=False,
                   opt=False, all=False, prefix=None, fitseq=False ):
        """ Preprocesses the sequence "sequencename" using bias, dark and flat
        given in argument.

        Syntax     : status=cmd.preprocess(sequencename,
                            [bias=filename], [dark=filename], [flat=filename],
                            [cc=dark [siglo sighi] || cc=bpm bpmfile]
                            [cfa], [debayer=True], [fix_xtrans=True],
                            [equalize_cfa=True], [opt=True], [prefix=xxx],[fitseq=True]
                            )
        Parameters :
            - sequencename = basename of input images
            - bias         = master-bias filename
            - dark         = master-dark filename
            - flat         = master-flat filename
            - cc           = cosmetic correction
            - siglo        = sigma low  if cc=dark
            - sigHi        = sigma high if cc=dark
            - bpmfile      = 'Bad Pixels Map' file if cc=bpm
            - cfa          = the images are CFA type
            - debayer      = debayerised
            - fix_xtrans   = option to  X-Trans files
            - equalize_cfa = option to equalize CFA images
            - opt          = to optimize the dark subtraction
            - all          = force processing of all frame
            - prefix       = set the prefix of output images
            - fitseq       = save in a multi-image FIT file
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(bias,"-bias=",path=True)
        self.AddParam(dark,"-dark=",path=True)
        self.AddParam(flat,"-flat=",path=True)

        if self.AddParam(cc,"-cc=") :
            if cc=="bpm" : self.AddParam(bpmfile,path=True)
            if cc=="dark" :
                self.AddParam(siglo)
                self.AddParam(sighi)
        self.AddParam(cfa,"-cfa")
        self.AddParam(debayer,"-debayer")
        self.AddParam(fix_xtrans,"-fix_xtrans")
        self.AddParam(equalize_cfa,"-equalize_cfa")
        self.AddParam(opt,"-opt")
        self.AddParam(all,"-all")
        self.AddParam(prefix,"-prefix=",path=True)
        self.AddParam(fitseq,"-fitseq")
        return (self.Execute("preprocess"),)

    def preprocess_single(self,imagename, bias=None, dark=None,flat=None,
                   cc=None,siglo=None,sighi=None,bpmfile=None,
                   cfa=False,debayer=False, fix_xtrans=False, equalize_cfa=False,
                   opt=False, prefix=None, fitseq=False ):
        """ Preprocesses the image "imagename" using bias, dark and flat given in
        argument.".

        Syntax     : status=cmd.preprocess_single(imagename,
                            [bias=filename], [dark=filename], [flat=filename],
                            [cc=dark [siglo sighi] || cc=bpm bpmfile]
                            [cfa], [debayer=True], [fix_xtrans=True],
                            [equalize_cfa=True], [opt=True], [prefix=xxx]
                            )
        Parameters :
            - sequencename = basename of input images
            - bias         = master-bias filename
            - dark         = master-dark filename
            - flat         = master-flat filename
            - cc           = cosmetic correction
            - siglo        = sigma low  if cc=dark
            - sigHi        = sigma high if cc=dark
            - bpmfile      = 'Bad Pixels Map' file if cc=bpm
            - cfa          = the images are CFA type
            - debayer      = debayerised
            - fix_xtrans   = option to  X-Trans files
            - equalize_cfa = option to equalize CFA images
            - opt          = to optimize the dark subtraction
            - prefix       = set the prefix of output images
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(bias,"-bias=",path=True)
        self.AddParam(dark,"-dark=",path=True)
        self.AddParam(flat,"-flat=",path=True)

        if self.AddParam(cc,"-cc=") :
            if cc=="bpm" : self.AddParam(bpmfile,path=True)
            if cc=="dark" :
                self.AddParam(siglo)
                self.AddParam(sighi)
        self.AddParam(cfa         ,"-cfa"         )
        self.AddParam(debayer     ,"-debayer"     )
        self.AddParam(fix_xtrans  ,"-fix_xtrans"  )
        self.AddParam(equalize_cfa,"-equalize_cfa")
        self.AddParam(opt         ,"-opt"         )
        self.AddParam(prefix      ,"-prefix="     ,path=True)
        return (self.Execute("preprocess_single"),)

    def psf(self, channel=None):
        """ Performs a PSF (Point Spread Function) on the selected star and display
            the results.

        Syntax     : status=cmd.psf( [channel] )
        Parameters : channel = If provided, the "channel" selects the image channel
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(channel)
        return ( self.Execute("psf "), )

    def register(self,sequencename, pass2=False, noout=False,
                 drizzle=False, prefix=None, minpairs=None, transf=None,
                 layer=None, maxstars=None, nostarlist=False,interp=None,
                 noclamp=False, selected=False):
        """ Finds and optionally performs geometric transforms on images of the
        sequence.

        Syntax     : status=cmd.register(sequence, [pass=True],[noout=True],
                                   [norot=True],[drizzle=True],[prefix=xxx],
                                   [minpairs=],[transf=],[layer=],[maxstars=],
                                   [nostarlist=True],[interp=],[noclamp=True]
                                   [selectedTrue])
        Parameters :
            - sequence = basename of input images
            - pass2    = adds a preliminary pass to the algorithm to find a good reference
            - noout    = not generate the transformed images
            - drizzle  = up-scaling by 2
            - prefix   = set the prefix of output images
            - minpairs = minimum number of star pairs a frame with the reference frame
            - transf   = choose the transformation
            - layer    = detection layer (0,1,2)
            - maxstars = maximum number of star to find within each frame [100..2000]
            -nostarlist= disables saving the star lists to disk
            - interp   = choose the pixel interpolation method
            - noclamp  = disable clamping (bicubic and lanczos4 interpolation)
            - selected = excluded images will not be processed
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(pass2     ,"-2pass"     )
        self.AddParam(noout     ,"-noout"     )
        self.AddParam(drizzle   ,"-drizzle"   )
        self.AddParam(prefix    ,"-prefix="   ,path=True)
        self.AddParam(minpairs  ,"-minpairs=" )
        self.AddParam(transf    ,"-transf="   )
        self.AddParam(layer     ,"-layer="    )
        self.AddParam(maxstars  ,"-maxstars=" )
        self.AddParam(interp    ,"-interp="   )
        self.AddParam(nostarlist,"-nostarlist")
        self.AddParam(noclamp   ,"-noclamp"   )
        self.AddParam(selected  ,"-selected"  )
        return (self.Execute("register"),)

    def requires(self, version_str):
        """ This function returns an error if the version of Siril is older that the one passed in argument.

        Syntax     : status=cmd.requires(version_str)
        Parameters :
            - version_str = format x.y.z ( ie: "0.99.6" )
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(version_str)
        return (self.Execute("requires"),)

    def resample(self, factor=None,width=None,height=None,interp=None,noclamp=False):
        """ Resamples image, either with a factor "factor" or for the target width
        or height provided by either of "-width=" or "-height=".

        Syntax     : status=cmd.resample([factor=],[width=],[height=],[interp=],[noclamp=True])
        Parameters :
            - factor  = rescale factor
            - width   = target width
            - height  = target height
            - interp  = choose the pixel interpolation method
            - noclamp = disable clamping (bicubic and lanczos4 interpolation)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        if self.AddParam(factor ,"-factor=") :
            if self.AddParam(width  ,"-width=" )  :
                self.AddParam(height ,"-height=")
        self.AddParam(interp ,"-interp=")
        self.AddParam(noclamp,"-noclamp")
        return (self.Execute("resample"),)

    def rgbcomp(self, lum=None,rgb_image=None,red=None,green=None,blue=None,out=None):
        """ Create an RGB composition using three independent images, or an LRGB
        composition.

        Syntax     : status=cmd.resample([lum=image [rgb_image]],[red green blue],[out=result_filename])
        Parameters :
            - lum       = luminance image
            - rgb_image = target width
            - red       = red image
            - green     = green image
            - blue      = disable clamping (bicubic and lanczos4 interpolation)
            - out       = specify ouput file
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        if self.AddParam(lum ,"-lum=",path=True):
            self.AddParam(rgb_image,path=True)

        if (red!=None) and (green!=None) and (blue!=None) :
            self.AddParam(red  ,path=True)
            self.AddParam(green,path=True)
            self.AddParam(blue ,path=True)

        self.AddParam(out,"-out=",path=True)

        return (self.Execute("rgbcomp"),)

    def rgradient(self, xc, yc, dR, dalpha):
        """ Creates two images, with a radial shift ("dR" in pixels) and a
        rotational shift ("dalpha" in degrees) with respect to the point (xc,yc).

        Syntax     : status=cmd.rgradient(xc, yc, dR, dalpha)
        Parameters :
            - xc , yc = points
            - dR      = radial shift
            - dalpha  = rotational shift in degrees
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(xc)
        self.AddParam(yc)
        self.AddParam(dR)
        self.AddParam(dalpha)
        return (self.Execute("rgradient"),)

    def rl(self, alpha=None, iters=None, stop=None,gdstep=None,
                 tv=False, fh=False, mul=False):
        """ Restores an image using the Richardson-Lucy method.

        Syntax     : status=cmd.rl([alpha=], [iters=], [stop=], [gdstep=],
                                   [tv=True], [fh=True], [mul=])
        Parameters :
            - alpha = provides the regularization strength (lower value = more
                       regularization, default = 3000)
            - iters = number of iterations (10)
            - stop  = stopping criterion
            - gdstep= gradient descent step
            - tv    = Total Variation
            - fh    = Frobenius norm of the Hessian matrix
            - mul   = multiplicative method
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(aplpha,"-alpha=")
        self.AddParam(iters,"-iters=")
        self.AddParam(stop,"-stop=")
        self.AddParam(gdstep,"-gdstep=")
        self.AddParam(tv,"-tv")
        self.AddParam(fh,"-fh")
        self.AddParam(mul,"-mul")
        return (self.Execute("rl"),)

    def rmgreen(self, nopreserve=False, type=None, amount=None):
        """ rmgreen is a chromatic noise reduction filter.

        Syntax     : status=cmd.rmgreen(type)
        Parameters :
            - nopreserve : Lightness is preserved by default but this can be
                           disabled with the "-nopreserve" switch
            - type : ( default=0)
                o 0 = for Average Neutral Protection
                o 1 = for Maximum Neutral Protection
                o 2 = for maximum mask
                o 3 = for additive mask
            - amount
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(nopreserve,"-nopreserve")
        self.AddParam(type)
        self.AddParam(amount)
        return (self.Execute("rmgreen"),)

    def rotate(self, degree, nocrop=False,interp=None,noclamp=False):
        """ Rotates the image by an angle of "degree" value.

        Syntax     : status=cmd.rotate(degree, [nocrop=True],[interp=],[noclamp=True] )
        Parameters :
            - degree = rotation angle in degree
            - nocrop = option can be added to avoid the cropping
            - interp = "no"[ne], "ne"[arest], "cu"[bic], "la"[nczos4], "li"[near], "ar"[ea]
            - noclamp= disable clamp  of the bicubic and lanczos4 interpolation
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.rotate(15)
            status=cmd.rotate(360-15,nocrop=True)
            status=cmd.rotate(5,interp="la", noclamp=True)
        """
        self.InitParam()
        self.AddParam(degree)
        self.AddParam(nocrop,"-nocrop")
        self.AddParam(interp,"-interp=")
        self.AddParam(noclamp,"-noclamp")
        return (self.Execute("rotate"),)

    def rotatepi(self):
        """ Rotates the image of an angle of 180° around its center. This is
        equivalent to the command "rotate 180" or "rotate -180"

        Syntax     : status=cmd.rotatepi()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("rotatepi"))

    def satu(self, amount, background_factor=None,hue_range_index=None):
        """ Enhances the color saturation of the loaded image. Try iteratively to
        obtain best results.

        Syntax     : status=cmd.satu(coeff,[background_factor=],[hue_range_index=])
        Parameters :
            - amount            = increase or decrease color saturation
            - background_factor = a factor to (median + sigma) used to set a
                                   threshold for which only pixels above it would be modified.
            - hue_range_index   = 0 for pink to orange, 1 for orange to yellow, 2 for yellow to cyan,
                                  3 for cyan, 4 for cyan to magenta, 5 for magenta to pink, 6 for all
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.satu(1.2)
        """
        self.InitParam()
        self.AddParam(amount)
        if self.AddParam(background_factor,"-background_factor=") :
            self.AddParam(hue_range_index,"-hue_range_index=")
        return (self.Execute("satu"),)

    def save(self,filename):
        """ Saves current image to filename.fit. Fits headers MIPS-HI and MIPS-LO
        are added with values corresponding to the current viewing levels.

        Syntax     : status=cmd.save(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("save"),)

    def savebmp(self,filename):
        """ Saves current image under the form of a bitmap file with 8bits per
        channel: filename.bmp (BMP 24 bits).

        Syntax     : status=cmd.savebmp(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("savebmp"),)

    def savejpg(self,filename,quality=100):
        """ Saves current image into a JPG file. You have the possibility to
        adjust the quality of the compression. A value 100 for quality parameter
        offers best fidelity while a low value increases the compression ratio.
        If no value is specified, it holds a value of 100. This command is very
        usefull to share an image in the jpeg format on the forums for example.

        Syntax     : status=cmd.savejpg(filename, [quality=100])
        Parameters :
            - filename
            - quality
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        self.AddParam(quality)
        return (self.Execute("savejpg"),)

    def savepng(self,filename):
        """ Saves current image as a PNG file.

        Syntax     : status=cmd.savepng(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("savepng"),)

    def savepnm(self,filename):
        """ Saves current image under the form of a Netpbm file format with
        16bits per channel. The extension of the output will be filename.ppm for
        RGB image and filename.pgm for gray-level image. More details about the
        Netpbm format at : http://en.wikipedia.org/wiki/Netpbm_format.

        Syntax     : status=cmd.savepnm(filename)
        Parameters :
            - filename
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        return (self.Execute("pnm"),)

    def savetif(self,filename,astro=False):
        """ Saves current image under the form of a uncompressed TIFF file with
        16bits per channel.

        Syntax     : status=cmd.savetif(filename)
        Parameters :
            - filename
            - astro  = save under the form of a uncompressed TIFF file
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        self.AddParam(astro,"-astro")
        return (self.Execute("savetif"),)

    def savetif32(self,filename,astro=False):
        """ Same command than SAVE_TIF but the output file is saved in 32bits
        per channel.

        Syntax     : status=cmd.savetif32(filename,[astro=True])
        Parameters :
            - filename
            - astro  = save under the form of a uncompressed TIFF file
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        self.AddParam(astro,"-astro")
        return (self.Execute("savetif32"),)

    def savetif8(self,filename,astro=False):
        """ Same command than SAVE_TIF but the output file is saved in 8bits
        per channel.

        Syntax     : status=cmd.savetif(filename)
        Parameters :
            - filename
            - astro  = save under the form of a uncompressed TIFF file
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(filename,path=True)
        self.AddParam(astro,"-astro")
        return (self.Execute("savetif8"),)

    def sb(self, alpha=None, iters=None ):
        """ Restores an image using the Split Bregman method.

        Syntax     : status=cmd.sb([alpha=], [iters=])
        Parameters :
            - alpha = regularization strength (lower value = more regularization,
                                               default = 3000)
            - iters = number of iterations (the default is 1).
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(alpha,"-alpha=")
        self.AddParam(iters,"-iters=")
        return (self.Execute("sb"),)

    def select(self, sequencename, _from, _to):
        """ This command allows easy mass selection of images in the sequence

        Syntax     : status=cmd.select(sequencename, _from, _to)
        Parameters :
            - sequencename
            - _from, _to  = range
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(_from )
        self.AddParam(_to )
        return (self.Execute("select"),)

    def seqapplyreg(self,sequencename,drizzle=False,interp=None,noclamp=False,layer=None,
                         framing=None,prefix=None,filter_fwhm=None,filter_wfwhm=None,
                         filter_round=None, filter_bkg=None, filter_nbstars=None,
                         filter_quality=None, filter_included=False,filter_incl=False):
        """ Applies geometric transforms on images of the sequence.

        Syntax     : status=cmd.seqapplyreg(sequencename,[drizzle=True] [interp=], [noclamp=True],
                                            [layer=] [framing=] [prefix=] [filter_fwhm=value[%|k]],
                                            [filter_wfwhm=value[%|k]], [filter_round=value[%|k]],
                                            [filter_bkg=value[%|k]] [filter_nbstars=value[%|k]]
                                            [filter_quality=value[%|k]] [filter_included=True])
        Parameters :
            - sequencename
            - drizzle        = up-scaling by 2 the output images
            - interp         = interpolation method :  "no"[ne], "ne"[arest], "cu"[bic],
                                                    "la"[nczos4], "li"[near], "ar"[ea]
            - noclamp        = disable clamping for the bicubic and lanczos4 interpolation
            - layer          = selection the layer for registering ( 0=R,1:G,2:B default=0)
            - framing        = automatic framing ("current" | "min" | "max" | "cog" )
            - prefix         = change the default output prefix ("r_")
            - filter_fwhm    = fwhm threshold ( absolu value or pourcent with % )
            - filter_wfwhm   = wfwhm threshold ( absolu value or pourcent with % )
            - filter_round   = roudness threshold ( absolu value or pourcent with % )
            - filter_bkg     = background threshold ( absolu value or pourcent with % )
            - filter_nbstars = stars number threshold ( absolu value or pourcent with % )
            - filter_quality = quality threshold ( absolu value or pourcent with % )
            - filter_included=

        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        filter_included = filter_included or filter_incl
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(drizzle,"-drizzle")
        self.AddParam(interp,"-interp=")
        self.AddParam(noclamp,"-noclamp")
        self.AddParam(layer,"-layer=")
        self.AddParam(framing,"-framing=")
        self.AddParam(prefix,"-prefix=",path=True)
        self.AddFiltering(filter_fwhm,filter_wfwhm,filter_round, filter_bkg,
                          filter_nbstars, filter_quality, filter_included)
        return (self.Execute("seqapplyreg"),)

    def seqclean(self, sequencename, reg=False, stat=False, sel=False ):
        """Clears selection, registration and/or statistics data stored in "sequencename.

        Syntax     : status=cmd.seqclean(sequencename,[reg=True], [stat=True], [sel=True])
        Parameters :
            - sequencename
            - reg          = enable the clear of registration
            - stat         = enable the clear of statistics
            - sel          = enable the clear of selection
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(reg ,"-reg")
        self.AddParam(stat,"-stat")
        self.AddParam(sel ,"-sel")
        return (self.Execute("seqclean"),)

    def seqcosme(self, sequencename, filename=None, prefix=None ):
        """Same command as COSME but for the the sequence "sequencename.

        Syntax     : status=cmd.seqcosme(sequencename,[filename], [prefix=])
        Parameters :
            - sequencename
            - filename     = list of cosmetic points  (*.lst)
            - prefix       = change the prefix output (default="cosme_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(filename)
        self.AddParam(prefix,"-prefix=")
        return (self.Execute("seqcosme"),)

    def seqcosme_cfa(self, sequencename, filename=None, prefix=None ):
        """Same command as COSME_CFA but for the the sequence "sequencename".

        Syntax     : status=cmd.seqcosme_cfa(sequencename,[filename], [prefix=])
        Parameters :
            - sequencename
            - filename     = list of cosmetic points  (*.lst)
            - prefix       = change the prefix output (default="cosme_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(filename)
        self.AddParam(prefix,"-prefix=")
        return (self.Execute("seqcosme_cfa"),)

    def seqcrop(self, sequencename, x, y, width, height, prefix=None ):
        """ Crops the loaded sequence.

        Syntax     : status=cmd.seqcrop(sequencename, x, y, width, height, [prefix=])
        Parameters :
            - x, y, width, height = crop area
            - prefix = set the prefix of output images (default="cropped_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(x)
        self.AddParam(y)
        self.AddParam(width)
        self.AddParam(height)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqcrop"),)

    def seqextract_Green(self, sequencename, prefix=None):
        """ Same command than extract_Green but for the sequence "sequencename".

        Syntax     : status=cmd.seqextract_Green(sequencename,prefix)
        Parameters :
            - sequence : basename of input images
            - prefix   : set the prefix of output images (default="Green_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqextract_Green"),)

    def seqextract_Ha (self, sequencename, prefix=None):
        """ Same command than extract_Ha but for the sequence "seqname".

        Syntax     : status=cmd.seqextract_Ha(sequencename,prefix)
        Parameters :
            - sequence = basename of input images
            - prefix   = set the prefix of output images (default="Ha_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqextract_Ha"),)

    def seqextract_HaOIII(self, sequencename, resample=False ):
        """ Same command than EXTRACT_HAOIII but for the sequence "seqname". The
        output sequence name start with the prefix "Ha_" and "OIII_".

        Syntax     : status=cmd.seqextract_HaOIII(seqname,prefix)
        Parameters :
            - sequence = basename of input images
            - resample = "ha"|"oiii" sets whether to upsample the Ha image
                         or downsample the OIII image.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(resample,"-resample")
        return (self.Execute("seqextract_HaOIII"),)

    def seqfind_cosme(self, sequencename, cold_sigma, hot_sigma, prefix=None ):
        """ Same command than FIND_COSME but for the loaded sequence.

        Syntax     : status=cmd.seqfind_cosme(sequencename, cold_sigma, hot_sigma, [prefix=xxx])
        Parameters :
            - sequencename
            - cold_sigma   = cold threshold
            - hot_sigma    = hot threshold
            - prefix       = set the prefix of output images (default="cc_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(cold_sigma)
        self.AddParam(hot_sigma)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqfind_cosme"),)

    def seqfind_cosme_cfa(self, sequencename, cold_sigma, hot_sigma, prefix=None ):
        """ Same command than FIND_COSME_CFA but for the loaded sequence.

        Syntax     : status=cmd.seqfind_cosme_cfa(sequencename,cold_sigma, hot_sigma, [prefix=xxx])
        Parameters :
            - sequencename
            - cold_sigma   = cold threshold
            - hot_sigma    = hot threshold
            - prefix       = set the prefix of output images
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(cold_sigma)
        self.AddParam(hot_sigma)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqfind_cosme_cfa"),)

    def seqfindstar(self,sequencename,layer=None,maxstars=None):
        """ Same command as FINDSTAR but for the sequence "sequencename".

        Syntax     : status=cmd.seqfindstar()
        Parameters :
            - layer
            - maxstars
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(layer,"-layer=")
        self.AddParam(maxstars,"-maxstars=")
        return (self.Execute("seqfindstar"),)

    def seqfixbanding(self,sequencename,amount, sigma,prefix=None,vertical=False):
        """ Same command as FINDSTAR but for the sequence "sequencename".

        Syntax     : status=cmd.seqfindstar()
        Parameters :
            - amount
            - sigma
            - prefix   = set the prefix of output images (default="unband_")
            - vertical = enable to perform vertical banding removal
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(amount)
        self.AddParam(sigma)
        self.AddParam(prefix,"-prefix=",path=True)
        self.AddParam(vertical,"-vertical")
        return (self.Execute("seqfixbanding"),)


    def seqght(self, sequence, D,  B=None, LP=None, SP=None, HP=None,
                     channels=None,human=False,even=False,independent=False):
        """ Generalised hyperbolic stretch based on the work of the ghsastro.co.uk
        team.

        Syntax     : status=cmd.seqght(D, B, LP, SP, HP,[channels], [human=True]|[even=True]|[independent=True])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.seqght(sequence,1,-1,0.15,0.75,1)
            status=cmd.seqght(sequence,1,-1,0.15,0.75,1,channels=2,even=True)
            status=cmd.seqght(sequence,1,-1,0.15,0.75,1,human=True) )
            status=cmd.seqght(sequence,1,-1,0.15,0.75,1,independent=True)
        """
        self.InitParam()
        self.AddParam(sequence)
        self.AddParam(D,"-D")
        self.AddParam(B ,"-B=" )
        self.AddParam(LP,"-LP=")
        self.AddParam(SP,"-SP=")
        self.AddParam(HP,"-HP=")
        self.AddParam(channels)
        if not self.AddParam(human,"-human")  :
            if not self.AddParam(even,"-even")  :
                self.AddParam(independent,"-independent")
        return (self.Execute("seqght"),)

    def seqheader(self, sequencename=None, keyword=None ):
        """ "Prints the FITS header value for the given key for all images in the sequence.

        Syntax     : status=cmd.seqheader(seqname,keyword)
        Parameters :
            - sequencename = basename of input images
            - keyword      = Search value of FITS header
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        if self.AddParam(sequencename) :
            self.AddParam(keyword)
        return (self.Execute("seqheader"),)

    def seqinvght(self, sequence, D,  B=None, LP=None, SP=None, HP=None,channels=None,human=False,even=False,independent=False ):
        """ Inverse generalised hyperbolic stretch based on the work of the
        ghsastro.co.uk team.

        Syntax     : status=cmd.seqinvght(sequence,D,  [B], [LP], [SP], [HP],
                                       [channels], [human=True]|[even=True]|[independent=True])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.seqinvght(sequence,1,-1,0.15,0.75,1)
            status=cmd.seqinvght(sequence,1,-1,0.15,0.75,1,channels=2,even=True)
            status=cmd.seqinvght(sequence,1,-1,0.15,0.75,1,human=True) )
            status=cmd.seqinvght(sequence,1,-1,0.15,0.75,1,independent=True)
        """
        self.InitParam()
        self.AddParam(sequence)
        self.AddParam(D,"-D=")
        self.AddParam(B ,"-B=" )
        self.AddParam(LP,"-LP=")
        self.AddParam(SP,"-SP=")
        self.AddParam(HP,"-HP=")
        self.AddParam(channels)
        if not self.AddParam(human,"-human")  :
            if not self.AddParam(even,"-even")  :
                self.AddParam(independent,"-independent")
        return (self.Execute("seqinvght"),)

    def seqmodasinh(self, sequence, D, LP=None, SP=None, HP=None,channels=None ,human=False,even=False,independent=False):
        """ Modified arcsinh stretch based on the work of the ghsastro.co.uk team.
        This is similar to the simple asinh stretch but offers additional
        parameters for fine tuning.

        Syntax     : status=cmd.seqmodasinh( D, [LP], [SP], [HP],
                                         [channels], [human=True]|[even=True]|[independent=True])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.seqmodasinh(1,0.15,0.75,1)
            status=cmd.seqmodasinh(1,0.15,0.75,1,channels=2,even=True)
            status=cmd.seqmodasinh(1,0.15,0.75,1,human=True) )
            status=cmd.seqmodasinh(1,0.15,0.75,1,independent=True)
        """
        self.InitParam()
        self.AddParam(sequence)
        self.AddParam(D,"-D=")
        self.AddParam(LP,"-LP=")
        self.AddParam(SP,"-SP=")
        self.AddParam(HP,"-HP=")
        self.AddParam(channels)
        if not self.AddParam(human,"-human")  :
            if not self.AddParam(even,"-even")  :
                self.AddParam(independent,"-independent")
        return (self.Execute("seqmodasinh"),)


    def seqlinstretch(self, sequence, BP=None,channels=None):
        """ Stretches the image linearly to a new black point BP.

        Syntax     : status=cmd.seqlinstretch( sequence, BP,[channels=])
        Parameters :
            - BP       =  the new black point to stretch to
            - channels = specify the channels to apply the stretch
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.seqlinstretch( sequence, 0.12,channels='RG')
        """
        self.InitParam()
        self.AddParam(sequence)
        self.AddParam(BP,"-BP=")
        self.AddParam(channels,"-channels=")
        return (self.Execute("seqlinstretch"),)

    def seqmerge_cfa(self,sequencename, bayerpattern, prefixin=None, prefixout=None):
        """ Same command as MERGE_CFA but for the sequence "sequencename".

        Syntax     : status=cmd.seqmerge_cfa( sequencename, bayerpattern, [prefixin=], [prefixout=] )
        Parameters :
            - sequence    = basename of input images
            - bayerpattern= "RGGB", "BGGR", "GBRG" or "GRBG"
            - prefixin    = set the prefix of input images (default="CFA_")
            - prefixout   = set the prefix of output images (default="mCFA_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(bayerpattern)
        self.AddParam(prefixin,"-prefixin=",path=True)
        self.AddParam(prefixout,"-prefixout=",path=True)
        return ( self.Execute("seqmerge_cfa"), )

    def seqmtf(self, sequencename, low, midtone, high, prefix=None ):
        """ Same command than MTF but for the sequence seqname.

        Syntax     : status=cmd.seqmtf(sequencename, low, midtone, high, [prefix=xxx])
        Parameters :
            - sequencename = basename of input images
            - low          =
            - midtone      =
            - high         =
            - prefix       = set the prefix of output images (default="mtf_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(low)
        self.AddParam(midtone)
        self.AddParam(high)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqmtf"),)

    def seqplatesolve(self, sequencename, center_coords=None, noflip=False, platesolve=False,
                   focal=None, pixelsize=None,limitmag=None,catalog=None,
                   localasnet=False, downscale=False):
        """ Plate solve the loaded image.

        Syntax     : status=cmd.seqplatesolve(sequencename,[center_coords],[noflip=True],
                                [platesolve=True], [focal=],[pixelsize=],
                                [limitmag=[+-]], [catalog=],
                                [localasnet=True],[downscale=True])
        Parameters :
            - center_coords= approximate image center coordinates
            - noflip       =  disable flip during the plate solving operation.
            - platesolve   = force the plate solving to be remade
            - focal        = focal length if no metadata
            - pixelsize    = pixel size if no metadata
            - limitmag     = limit magnitude of stars
            - catalog      = choice of the star catalog
            - localasnet   = astrometry.net's local solve-field
            - downscale    = downsampling the image
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(center_coords)
        if self.AddParam(platesolve, "-platesolve"):
            self.AddParam(noflip    , "-noflip"     )
            self.AddParam(focal     , "-focal="     )
            self.AddParam(pixelsize , "-pixelsize=" )
            self.AddParam(limitmag  , "-limitmag="  )
            self.AddParam(catalog   , "-catalog="   )
            self.AddParam(localasnet, "-localasnet")
            self.AddParam(downscale , "-downscale" )
        return (self.Execute("seqplatesolve"),)

    # TODO : output
    def seqpsf(self,sequencename, channel=None, at=None, wcs=None):
        """ Same command than PSF but works for sequences.
        Results are dumped in the console in a form that can be used to produce
        brightness variation curves.

        Syntax     : status=cmd.seqpsf( [sequencename channel { -at=x,y | -wcs=ra,dec }] )
        Parameters :
            - sequence= basename of input images
            - channel = selects the image channel on which the psf will be processed
            - at      = coordinates (in degrees)
            - wcs     = the WCS information of the image
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        if self.AddParam(sequencename):
            self.AddParam(channel)
            if not self.AddParam(at,"-at=") :
                self.AddParam(wcs,"-wcs=")
        return ( self.Execute("seqpsf"), )

    def seqrl(self, sequencename, alpha=None, iters=None, stop=None,gdstep=None,
                 tv=False, fh=False, mul=False):
        """ Restores an image using the Richardson-Lucy method.

        Syntax     : status=cmd.seqrl(sequencename,[alpha=], [iters=], [stop=], [gdstep=],
                                   [tv=True], [fh=True], [mul=])
        Parameters :
            - sequence= basename of input images
            - alpha = provides the regularization strength (lower value = more
                       regularization, default = 3000)
            - iters = number of iterations (10)
            - stop  = stopping criterion
            - gdstep= gradient descent step
            - tv    = Total Variation
            - fh    = Frobenius norm of the Hessian matrix
            - mul   = multiplicative method
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(aplpha,"-alpha=")
        self.AddParam(iters,"-iters=")
        self.AddParam(stop,"-stop=")
        self.AddParam(gdstep,"-gdstep=")
        self.AddParam(tv,"-tv")
        self.AddParam(fh,"-fh")
        self.AddParam(mul,"-mul")
        return (self.Execute("seqrl"),)


    def seqsb(self, sequencename, alpha=None, iters=None ):
        """ Restores an image using the Split Bregman method.

        Syntax     : status=cmd.seqsb( sequencename,[alpha=], [iters=])
        Parameters :
            - sequence= basename of input images
            - alpha = regularization strength (lower value = more regularization,
                                               default = 3000)
            - iters = number of iterations (the default is 1).
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(alpha,"-alpha=")
        self.AddParam(iters,"-iters=")
        return (self.Execute("seqsb"),)

    def seqsplit_cfa(self, sequencename, prefix=None ):
        """ Same command as SPLIT_CFA but for the sequence "sequencename".

        Syntax     : status=cmd.seqsplit_cfa( sequencename, [prefix="xxx"])
        Parameters :
            - sequence = basename of input images
            - prefix   = set the prefix of output images  (default="CFA_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqsplit_cfa"),)

    def seqstarnet(self, sequencename, stretch=False, upscale=False,
                         stride=None , nostarmask=False ):
        """ same as for the STARNET command but for the sequence "sequencename".

        Syntax     : status=cmd.seqstarnet( sequencename, [stretch=True],
                                           [upscale=True], [stride=value],
                                           [nostarmask=True])
        Parameters :
            - sequence = basename of input images
            - stretch    = apply a pre-stretch for linear images
            - upscale    = improve star removal on images with very tight stars
            - stride     = (default:256)
            - nostarmask = disable creating the star mask image in current directory
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(stretch,"-stretch")
        self.AddParam(upscale,"-upscale")
        self.AddParam(stride ,"-stride=")
        self.AddParam(nostarmask,"-nostarmask")
        return (self.Execute("seqstarnet"),)

    def seqstat(self, sequencename, output="statistic.csv" , option = "basic" , cfa=False):
        """ Returns global statistic of the images sequence

        syntax     : status=cmd.seqstat( sequencename, [output] , [option],[cfa=True] )
        Parameters :
            - sequencename = basename of input images
            - output       = csv output filename (default="statistic.csv")
            - option       = "basic", "main" or "full"
            - cfa          = enable CFA mode
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted

        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(output,path=True)
        self.AddParam(option)
        self.AddParam(cfa,"-cfa")
        return (self.Execute("seqstat"),)

    def seqsubsky(self, sequencename, degree=None, rbf=False, samples=None,tolerance=None, smooth=None, prefix=None ):
        """ Same command that SUBSKY but for the sequence sequencename

        Syntax     : status=cmd.seqsubsky( sequencename, { -rbf | degree }, [samples=20], [tolerance=1.0], [smooth=0.5], [-prefix=][prefix=xxx])
        Parameters :
            - sequencename = basename of input images
            - degree       = order degree
            - rbf          = enable RBF mode
            - samples      = (only RBF mode)
            - tolerance    = (only RBF mode)
            - smooth       = (only RBF mode)
            - prefix       = set the prefix of output images (defualt:"bkg_")
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        if self.AddParam(rbf,"-rbf") :
            self.AddParam(samples,"-samples=")
            self.AddParam(tolerance,"-tolerance=")
            self.AddParam(smooth,"-smooth=")
        else:
            self.AddParam(degree)
        self.AddParam(prefix,"-prefix=",path=True)
        return (self.Execute("seqsubsky"),)

    def seqtilt(self, sequencename):
        """ Same command as TILT but for the loaded sequence or the sequence
            "sequencename".

        Syntax     : status=cmd.seqtilt( sequencename )
        Parameters :
            - sequencename = basename of input images
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        return (self.Execute("seqtilt"),)

    def seqwiener(self, sequencename, alpha=None):
        """ Restores an image using the Wiener deconvolution method.

        Syntax     : status=cmd.seqwiener(sequencename,[-alpha=])
        Parameters :
            - sequencename = basename of input images
            - alpha = provides the Gaussian noise modelled regularization factor
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(alpha,"-alpha=")
        return (self.Execute("seqwiener"),)

    def set(self, *variables, inifile=None):
        """ Update a setting value, using its variable name, with the given value,
           or a set of values using an existing ini file with "-import=" option.

        See "get" to get values or the list of variables.

        Syntax     : status=cmd.set( { inifile=inifilepath | variable=value })
        Parameters :
            - sequencename = basename of input images
            - inifile      = variables setting file
            - liste        = variables setting "name1=value1","name2=value2", ...
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(inifile,"-import=",path=True)
        for variable in variables :
            self.AddParam(variable)
        return (self.Execute("set"),)


    def set16bits(self):
        """ Disallow images to be saved with 32 bits per channel on processing,
        use 16 instead

        Syntax     : status=cmd.set16bits( )
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("set16bits"),)

    def set32bits(self):
        """ Allow images to be saved with 32 bits per channel on processing.

        Syntax     : status=cmd.set32bits( )
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("set32bits"),)

    def setcompress(self, enable, type=None, quantif=16 ):
        """ Defines if images are compressed or not: 0 means no compression.

        Syntax     : status=cmd.setcompress(enable, [type], [quantif]))
        Parameters :
            - enable   = set or unset the compression
            - type     = set the compression type ("rice", "gzip1", "gzip2")
            - quantif  = quantization value ([0, 256])
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        Example    :
            status=cmd.setcompress(0)
            status=cmd.setcompress(1,type="rice")
            status=cmd.setcompress(1,type="gzip1",quantif=4)
        """
        self.InitParam()
        self.AddParam(enable)
        if enable  :
            if type==None :
                return(False,)
            self.AddParam(type,"-type=")
            self.AddParam(quantif)
        return (self.Execute("setcompress"),)

    def setcpu(self, number):
        """ Defines the number of processing threads used for calculation.

        Syntax     : status=cmd.setcpu( number )
        Parameters :
            - number = set the number of cpu used
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(number)
        return (self.Execute("setcpu"),)

    def setext(self, ext):
        """ Sets the extension used and recognized by sequences. The argument
        "extension" can be "fit", "fts" or "fits".

        Syntax     : status=cmd.setext( ext )
        Parameters :
            - ext = set the extension value ( "fit", "fts" or "fits" )
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(ext)
        return (self.Execute("setext"),)

    def setfindstar(self, reset=False,radius=None,sigma=None,roundness=None,
                    focal=None,pixelsize=None,convergence=None,
                    gaussian=False, moffat=False,minbeta=None,relax=None,
                    minA=None,maxA=None,maxR=None):
        """ Defines stars detection parameters for FINDSTAR and REGISTER commands.

        Syntax     : status=cmd.setfindstar([reset], [radius=], [sigma=],
                             [roundness=], [focal=], [pixelsize=], [convergence=]
                             [ [gaussian=True] | [moffat=True] ] [minbeta=] [relax=on|off])
        Parameters :
            - reset       = set the default values
            - radius      = radius of the initial search box ([3..50])
            - sigma       = threshold above noise (>=0.05)
            - roundness   = minimum star roundness ([0..0.95])
            - focal       = focal length of the telescope (in mm)
            - pixelsize   = pixel size of the sensor (in µm)
            - convergence = number of iterations performed to fit PSF ([1..3])
            - gaussian    = enable gaussian solver model
            - moffat      = enable moffat solver model
            - minbeta     = minimum value of beta for which candidate stars
                            will be accepted (only wit moffat) ([0.0..10.0])
            - relax       = relaxes the checks that are done on star candidates
            - minA, maxA  = define limits for the minimum and maximum amplitude
                            of stars to keep, normalized between 0 and 1.
            - maxR        = allows an upper bound to roundness to be set

        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = liste of properties
        """
        reset="reset" if reset else None
        relax=self.setBool(relax,'off','on')
        self.InitParam()
        self.AddParam(reset)
        self.AddParam(radius,"-radius=")
        self.AddParam(sigma,"-sigma=")
        self.AddParam(roundness,"-roundness=")
        self.AddParam(focal,"-focal=")
        self.AddParam(pixelsize,"-pixelsize=")
        self.AddParam(convergence,"-convergence=")
        self.AddParam(gaussian,"-gaussian")
        if self.AddParam(moffat,"-moffat") :
            self.AddParam(minbeta,"-minbeta=")
        self.AddParam(relax,"-relax=")
        self.AddParam(minA,"-minA=")
        self.AddParam(maxA,"-maxA=")
        self.AddParam(maxR,"-maxR=")

        status = self.Execute("setfindstar")
        if not status :
            return (status,)

        log = self.filt_log(self.GetData())[1:]
        prop_values={}
        for line in log :
            cle,valeur = line.split('=')
            valeur=valeur.strip()
            cle=cle.strip()
            try:
                valeur=float(valeur)
            except:
                pass
            prop_values[cle]=valeur

        return (status,prop_values)

    def setmem(self, ratio):
        """ Sets a new ratio of free memory on memory used for stacking.

        Syntax     : status=cmd.setmem( ratio )
        Parameters :
            - ratio : ratio of used memory (between 0 and 1)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(ratio)
        return (self.Execute("setmem"),)

    def setphot(self, inner=None, outer=None, aperture=None,force_radius=None,
                gain=None,min_val=None,max_val=None):
        """ "Gets or sets photometry settings, mostly used by SEQPSF..

        Syntax     : status=cmd.setphot( [inner=20],[outer=30],[aperture=10],
                       [force_radius=no],[gain=2.3] [min_val=0] [max_val=60000] )
        Parameters :
            - ratio = ratio of used memory (between 0 and 1)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = liste of properties
        """
        force_radius=self.setBool(force_radius,'no','yes')
        self.InitParam()
        self.AddParam(inner,"-inner=")
        self.AddParam(outer,"-outer=")
        self.AddParam(aperture,"-aperture=")
        self.AddParam(force_radius,"-force_radius=")
        self.AddParam(gain,"-gain=")
        self.AddParam(min_val,"-min_val=")
        self.AddParam(max_val,"-max_val=")

        status = self.Execute("setphot")
        if not status :
            return (status,)

        resultat={}
        log = self.filt_log(self.GetData())[1:]

        chaine=log[0].split(',')[0].split(':')[-1].strip().split(' ')
        resultat["inner"]=float(chaine[0])
        resultat["outer"]=float(chaine[2])

        chaine=log[0].split(',')[1].split(':')[-1].strip().split('(')
        resultat["aperture"]=float(chaine[0])

        chaine=log[0].split(')')[0].split('(')[-1].strip()
        resultat["force_radius"]=chaine

        chaine=log[0].split(':')[3].strip().split(' ')
        resultat["gain"]=float(chaine[0])

        chaine=log[0].split(']')[1][:-1].split(',')
        resultat["min_val"]=float(chaine[0])
        resultat["max_val"]=float(chaine[1])

        return (status,resultat)

    def setref(self, sequencename, image_number):
        """ Sets the reference image of the sequence given in first argument.

        Syntax     : status=cmd.setref( sequencename, image_number )
        Parameters :
            - sequencename = basename of input images
            - image_number = number of reference image
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(image_number)
        return (self.Execute("setref"),)

    def solsys(self, mag=None ):
        """ Sets the reference image of the sequence given in first argument.

        Syntax     : status=cmd.solsys( mag )
        Parameters :
            - mag : change the limit magnitude (default=20)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(mag,"-mag=")
        return (self.Execute("solsys"),)

    def split(self, fileR, fileG, fileB,hsl=False,hsv=False,lab=False):
        """ Splits the color image into three distincts files and save them in r g and b file.

        Syntax     : status=cmd.split(fileR, fileG, fileB, [hsl=True | hsv=True | lab=True])
        Parameters :
            - fileR = basename of red layer
            - fileG = basename of green layer
            - fileB = basename of blue layer
            - hsl or hsv  or lab = to perform an HSL, HSV or CieLAB extraction.
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(fileR,path=True)
        self.AddParam(fileG,path=True)
        self.AddParam(fileB,path=True)
        if not self.AddParam(hsl,"-hsl") :
            if not self.AddParam(hsv,"-hsv") :
                self.AddParam(lab,"-lab")
        return (self.Execute("split"),)

    def split_cfa(self):
        """ Splits the CFA image into four distinct files (one for each channel)
        and save them in files.

        Syntax     : status=cmd.split_cfa()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("split_cfa"),)

    def stack(self, sequencename, type=None, rejection_type=None,
              sigma_low=3, sigma_high=3,
              norm=None, output_norm=False, rgb_equal=False, out=None,
              filter_fwhm=None, filter_wfwhm=None, filter_round=None,
              filter_bkg=None,filter_nbstars=None,
              filter_quality=None,filter_included=False, filter_incl=False,
              weight_from_noise=False, weight_from_nbstack=False,
              weight_from_nbstars=False, weight_from_wfwhm=False,
              fastnorm=False, rejmap=False, rejmaps=False ):
        """ Stacks the seqfilename sequence, using options.

        Syntax     : status=cmd.stack(seqfilename)
                     status=cmd.stack(seqfilename, type={sum|min|max}, [filtering] [output_norm] [weighted] [out=filename])
                     status=cmd.stack(seqfilename, type={med|median},  [norm=no, norm=] [filter-included] [weighted] [out=filename])
                     status=cmd.stack(seqfilename, type={rej|mean}, [rejection_type], sigma_low, sigma_high, [nonorm,norm=] [filtering]  [weighted] [out=filename]

                    status=cmd.stack(seqfilename,[type],[rejection type],[sigma_low, sigma_high,],
                                                 [nonorm, norm=], [output_norm],[rgb_equal]
                                                 [out=result_filename],
                                                 [filter_fwhm=value[%|k]], [filter_wfwhm=value[%|k]],
                                                 [filter_round=value[%|k]], [filter_bkg=value[%|k]],
                                                 [filter_nbstars=value[%|k]], [filter_quality=value[%|k]],
                                                 [filter_incl[uded]],
                                                 [weight_from_noise],
                                                 [weight_from_nbstack],
                                                 [weight_from_nbstars],
                                                 [weight_from_wfwhm],
                                                 [fastnorm],[-rejmap[s]]
         Parameters :
            - sequencename       = basename of input images
            - type               = stack type (sum|min|max|med|median|rej|mean)
            - rejection_type     = The rejection type is one of :
                                   {n[none], p[ercentile] , s[igma] , m[edian],
                                   w[insorized] , l[inear] , g[eneralized]}
            - sigma_low          = low threshold for sigma clipping rejection
            - sigma_high         = high threshold for sigma clipping rejection
            - norm               = value are: no, add, addscale, mul or mulscale
            - output_norm        = normalization at the end of the stacking
            - rgb_equal          = output name of stacked image
            - out                = output name of stacked image
            - filter_fwhm        = fwhm threshold ( absolu value or pourcent with % )
            - filter_wfwhm       = wfwhm threshold ( absolu value or pourcent with % )
            - filter_bkg         = background threshold ( absolu value or pourcent with % )
            - filter_nbstars     = stars number threshold ( absolu value or pourcent with % )
            - filter_round       = roudness threshold ( absolu value or pourcent with % )
            - filter_quality     = quality threshold ( absolu value or pourcent with % )
            - filter_included    =
            - weight_from_noise  = add larger weights to frames with lower background noise.
            - weight_from_nbstack= weights input images based on how many images were used to create them.
            - weight_from_nbstars= weights input images based on number of stars.
            - weight_from_wfwhm  = weights input images based on wFWHM computed during registration.
            - fast_norm          = specifies to use faster estimators for location and scale than the default IKSS
            - rejmap             = rejection maps can be created, showing where pixels were rejected in one created images
            - rejmaps            = rejection maps can be created, showing where pixels were rejected in two newly created images
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        nonorm=False
        if norm != None and norm == "no":
            nonorm= True
            norm=None

        filter_included = filter_included or filter_incl

        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(type)
        if type==None : return (self.Execute("stack"),)

        if ( type=="sum") or ( type=="min") or ( type=="max") :
            #  stack seqfilename { sum | min | max } [filtering] [-output_norm] [-out=filename]
            pass
        else:
            if ( type=="med") or ( type=="median") :
                #  stack seqfilename { med | median } [-nonorm, norm=] [-filter-incl[uded]] [-out=filename]
                self.AddParam(nonorm,"-nonorm")
                self.AddParam(norm  ,"-norm=")
            else:
                #  stack seqfilename { rej | mean } sigma_low sigma_high [-nonorm, norm=] [filtering] [-out=filename]
                if rejection_type == None : rejection_type="w"
                self.AddParam(rejection_type)

                if rejection_type != "n" :
                    self.AddParam(sigma_low)
                    self.AddParam(sigma_high)

                self.AddParam(nonorm,"-nonorm")
                self.AddParam(norm  ,"-norm=")

        self.AddFiltering(filter_fwhm,filter_wfwhm,filter_round, filter_bkg,
                          filter_nbstars, filter_quality, filter_included)
        self.AddParam(output_norm        ,"-output_norm"        )
        self.AddParam(rgb_equal          ,"-rgb_equal"          )
        self.AddParam(out                ,"-out="               , path=True)
        self.AddParam(weight_from_noise  ,"-weight_from_noise"  )
        self.AddParam(weight_from_nbstack,"-weight_from_nbstack")
        self.AddParam(weight_from_nbstars,"-weight_from_nbstars")
        self.AddParam(weight_from_wfwhm  ,"-weight_from_wfwhm"  )
        self.AddParam(fastnorm           ,"-fastnorm"           )
        if self.AddParam(rejmap          ,"-rejmap"             ) :
            self.AddParam(rejmaps        ,"-rejmaps"            )
        return (self.Execute("stack"),)

    def stackall(self, type=None,  rejection_type=None, sigma_low=3, sigma_high=3,
              norm=None, output_norm=False,
              filter_fwhm=None, filter_wfwhm=None, filter_round=None,
              filter_bkg=None,filter_nbstars=None,
              filter_quality=None,filter_included=False,filter_incl=False,
              weight_from_noise=None, weight_from_nbstack=None, fastnorm=False ):
        """ Opens all sequences in the current working directory (CWD) and
        stacks them with the optionally specified stacking type or with sum
        stacking.

        Syntax     : status=cmd.stackall(seqfilename)
                     status=cmd.stackall(seqfilename, type={sum|min|max}, [filtering], [weighted], [out=filename])
                     status=cmd.stackall(seqfilename, type={med|median},  [norm=no, norm=], [filter-included], [-weighted], [out=filename])
                     status=cmd.stackall(seqfilename, type={rej|mean}, [rejection_type], sigma_low, sigma_high, [nonorm,norm=], [output_norm], [weighted], [filtering] [out=filename]

                    status=cmd.stackall(seqfilename,[type],[rejection type],[sigma_low sigma_high],
                                       [nonorm, norm=],[output_norm=False],
                                       [filter_fwhm=value[%|k]],[filter_wfwhm=value[%|k]],
                                       [filter_round=value[%|k]],[filter_bkg=value[%|k]],
                                       [filter_nbstars=value[%|k]],[filter_quality=value[%|k]],
                                       [filter-incl[uded]],
                                       [weight_from_noise],[weight_from_nbstack],[fastnorm])

        Parameters :
            - sequencename       = basename of input images
            - type               = stack type (sum|min|max|med|median|rej|mean)
            - rejection_type     = The rejection type is one of :
                                   {n[none], p[ercentile] , s[igma] , m[edian],
                                   w[insorized] , l[inear] , g[eneralized]}
            - sigma_low          = low threshold for sigma clipping rejection
            - sigma_high         = high threshold for sigma clipping rejection
            - norm               = value are: no, add, addscale, mul or mulscale
            - output_norm        = normalization at the end of the stacking
            - filter_fwhm        = fwhm threshold ( absolu value or pourcent with % )
            - filter_wfwhm       = wfwhm threshold ( absolu value or pourcent with % )
            - filter_round       = roudness threshold ( absolu value or pourcent with % )
            - filter_bkg         = background threshold ( absolu value or pourcent with % )
            - filter_nbstars     = stars number threshold ( absolu value or pourcent with % )
            - filter_quality     = quality threshold ( absolu value or pourcent with % )
            - filter_included    =
            - weight_from_noise  = add larger weights to frames with lower background noise.
            - weight_from_nbstack= weights input images based on how many images
                                   were used to create them.
            - fast_norm          = specifies to use faster estimators for location and scale than the default IKSS
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        nonorm=False
        if norm != None and norm == "no":
            nonorm= True
            norm=None

        filter_included = filter_included or filter_incl

        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(type)

        if type==None : return (self.Execute("stackall" ), )

        if ( type=="sum") or ( type=="min") or ( type=="max") :
            #  stack seqfilename { sum | min | max } [filtering] [-output_norm] [-out=filename]
            pass
        else:
            if ( type=="med") or ( type=="median") :
                #  stack seqfilename { med | median } [-nonorm, norm=] [-filter-incl[uded]] [-out=filename]
                self.AddParam(nonorm,"-nonorm")
                self.AddParam(norm  ,"-norm=")
            else:
                #  stack seqfilename { rej | mean } sigma_low sigma_high [-nonorm, norm=] [filtering] [-out=filename]
                if rejection_type == None : rejection_type="w"
                self.AddParam(rejection_type)

                if rejection_type != "n" :
                    self.AddParam(sigma_low)
                    self.AddParam(sigma_high)

                self.AddParam(nonorm,"-nonorm")
                self.AddParam(norm  ,"-norm=")

        self.AddFiltering(filter_fwhm,filter_wfwhm,filter_round, filter_bkg,
                          filter_nbstars, filter_quality, filter_included)
        self.AddParam(output_norm        ,"-output_norm"        )
        self.AddParam(weight_from_noise  ,"-weight_from_noise"  )
        self.AddParam(weight_from_nbstack,"-weight_from_nbstack")
        self.AddParam(fastnorm           ,"-fastnorm"           )

        return (self.Execute("stackall"),)

    def starnet(self, stretch=False,upscale=False,stride=None,nostarmask=False):
        """ This command calls "https://www.starnetastro.com/">Starnet++ to remove
        stars from the current image..

        Syntax     : status=cmd.starnet([stretch=True],[upscale=True],[stride=value],[nostarmask=True])
        Parameters :
            - stretch    = apply a pre-stretch for linear images
            - upscale    = improve star removal on images with very tight stars
            - stride     = (default:256)
            - nostarmask = disable creating the star mask image in current directory
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(stretch   ,"-stretch")
        self.AddParam(upscale   ,"-upscale")
        self.AddParam(stride    ,"-stride=")
        self.AddParam(nostarmask,"-nostarmask")
        return (self.Execute("starnet"), )

    def start_ls(self, dark=None,flat=None,rotate=False,_32bits=False):
        """ Initialize a livestacking session, using the optional calibration files
            and wait for input files to be provided by the LIVESTACK command until
            STOP_LS is called.

        Syntax     : status=cmd.start_ls([dark=filename],[flat=filename],[rotate=True],[_32bits=True])
        Parameters :
            - dark    = dark calibration filename
            - flat    = flat calibration filename
            - rotate  = enable rotation
            - _32bits = enable 32bits
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(dark   ,"-dark=" , path=True)
        self.AddParam(flat   ,"-flat=" , path=True)
        self.AddParam(rotate ,"-rotate")
        self.AddParam(_32bits,"-32bits")
        return (self.Execute("start_ls"), )

    def stat(self):
        """ Returns global statistic of the current image. If a selection is
        made, the command returns global statistic within the selection.

        Syntax     : status=cmd.stat()
        Parameters : None
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
            - status[1] = statistic values of the current image
        """
        self.InitParam()
        status = self.Execute("stat", bEndTest = True  )
        if status is False :
            return (False,)

        log = self.filt_log(self.GetData())[1:]

        res_stat =[]
        for line in log :
            rr = line.replace( ' ', '').replace(',',':').split(':')
            label=rr[0].lower().replace('layer','').replace('canal','')
            label=label.upper().replace(u"\u202f","")
            res_stat.append({ "layer"  : label,
                              "mean"   : float(rr[2]),
                              "median" : float(rr[4]),
                              "sigma"  : float(rr[6]),
                              "avgdev" : float(rr[12]),
                              "min"    : float(rr[8]),
                              "max"    : float(rr[10])
                            })
        return (status, res_stat )

    def stop_ls(self):
        """ Stop the live stacking session. Only possible after START_LS.

        Syntax     : status=cmd.stop_ls()
        Parameters : none
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("stop_ls"), )

    def subsky(self, degree=None, rbf=False, samples=None,tolerance=None, smooth=None):
        """ Computes a synthetic background gradient using either the polynomial
            function model of "degree" degrees or the RBF model.

        Syntax     : status=cmd.subsky( { -rbf | degree }, [samples=20], [tolerance=1.0], [smooth=0.5])
        Parameters :
            - degree    = order degree
            - rbf       = enable RBF mode
            - samples   = (only RBF mode)
            - tolerance = (only RBF mode)
            - smooth    = (only RBF mode)
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        if self.AddParam(rbf,"-rbf") :
            self.AddParam(samples  ,"-samples="  )
            self.AddParam(tolerance,"-tolerance=")
            self.AddParam(smooth   ,"-smooth="   )
        else:
            self.AddParam(degree)
        return (self.Execute("subsky"),)

    def synthstar(self):
        """ Synthstar fixes bad stars.

        Syntax     : status=cmd.synthstar( )
        Parameters : none
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("synthstar"),)

    def threshlo(self,value):
        """ replaces values below threshold with threshold

        Syntax     : status=cmd.threshlo(value)
        Parameters :
            - value= low threshold
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(value)
        return (self.Execute("threshlo"),)

    def threshhi(self,value):
        """ replaces values above threshold with threshold

        Syntax     : status=cmd.threshhi(value)
        Parameters :
            - value= high threshold
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(value)
        return (self.Execute("threshhi"),)

    def thresh(self,low,high):
        """ replaces values below low threshold with low threshold and
        replaces values above high threshold with high threshold

        Syntax     : status=cmd.thresh(low,high)
        Parameters :
            - low  = low threshold
            - value= high threshold
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(low)
        self.AddParam(high)
        return (self.Execute("thresh"),)

    def unclipstars(self):
        """ Re-profiles clipped stars to desaturate them, scaling the output so
            that all pixel values are <= 1.0.

        Syntax     : status=cmd.unclipstars( )
        Parameters : none
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        return (self.Execute("unclipstars"),)


    def unselect(self, sequencename, _from, _to):
        """ This command allows easy mass unselection of images in the
        sequence "sequencename" (from "_from" to "_to" included)

        Syntax     : status=cmd.unselect(sequencename, _from, _to)
        Parameters :
            - sequencename
            - _from, _to  = range
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sequencename)
        self.AddParam(_from )
        self.AddParam(_to )
        return (self.Execute("unselect"),)

    def unsharp(self, sigma, multi):
        """ Applies to the working image an unsharp mask with sigma sigma and
        coefficient multi.

        Syntax     : status=cmd.unsharp(sigma, multi)
        Parameters :
            - sigma
            - multi
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(sigma)
        self.AddParam(multi)
        return (self.Execute("unsharp"),)

    def wavelet(self, nbr_plan, type):
        """ Computes the wavelet transform on "nbr_plan" plans using linear
        (type=1) or bspline (type=2) version of the 'a trous' algorithm. The
        result is stored in a file as a structure containing the planes, ready
        for weighted reconstruction with WRECONS.

        Syntax     : status=cmd.wavelet(plan_number, type)
        Parameters :
            - nbr_plan = number of plans
            - type     = 1=linear , 2=bspline
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(nbr_plan)
        self.AddParam(type)
        return (self.Execute("wavelet"),)

    def wiener(self, alpha=None):
        """ Restores an image using the Wiener deconvolution method.

        Syntax     : status=cmd.wiener([-alpha=])
        Parameters :
            - alpha = provides the Gaussian noise modelled regularization factor
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        self.AddParam(alpha,"-alpha=")
        return (self.Execute("wiener"),)

    def wrecons(self, *list_c):
        """ Reconstructs to current image from the planes previously computed
        with wavelets and weighted with coefficients c1, c2, ..., cn according
        to the number of planes used for wavelet transform.

        Syntax     : status=cmd.wrecons(list_coef)
        Parameters :
            - list_c : coefficients list according to the number of planes
        Return     :
            - status[0] = True: execution ok /status[0] = False: Aborted
        """
        self.InitParam()
        for c in list_c : self.AddParam(c)
        return (self.Execute("wrecons"),)

