##################### generated by xml-casa (v2) from subvs.xml #####################
##################### 359882fd4602fc4cb310cc193180fe92 ##############################
from __future__ import absolute_import
from casashell.private.stack_manip import find_local as __sf__
from casashell.private.stack_manip import find_frame as _find_frame
from casatools.typecheck import validator as _pc
from casatools.coercetype import coerce as _coerce
from suncasatasks import subvs as _subvs_t
from collections import OrderedDict
import numpy
import sys
import os

import shutil

def static_var(varname, value):
    def decorate(func):
        setattr(func, varname, value)
        return func
    return decorate

class _subvs:
    """
    subvs ---- Vector-subtraction in UV using selected time ranges and spectral channels as background

    
    
    
    Split is the general purpose program to make a new data set that is a
    subset or averaged form of an existing data set.  General selection
    parameters are included, and one or all of the various data columns
    (DATA, LAG_DATA and/or FLOAT_DATA, and possibly MODEL_DATA and/or
    CORRECTED_DATA) can be selected.
    
    Split is often used after the initial calibration of the data to make a
    smaller measurement set with only the data that will be used in
    further flagging, imaging and/or self-calibration.  split can
    average over frequency (channels) and time (integrations).

    --------- parameter descriptions ---------------------------------------------

    vis         Name of input measurement set
    outputvis   Name of output measurement set
    timerange   Select the time range of the input visbility to be subtracted from
    spw         Select the spectral channels of the input visibility to be subtracted from
    mode        Operation: linear, highpass
    subtime1    Select the first time range as the background for uv subtraction
    subtime2    Select the second time range as the background for uv subtraction
    smoothaxis  Select the axis along which smooth is performed
    smoothtype  Select the smooth type
    smoothwidth Select the width of the smoothing window
    splitsel    Split the selected timerange and spectral channels as outputvis
    reverse     Reverse the sign of the background-subtracted data (for absorptive structure)
    overwrite   Overwrite the already existing output measurement set

    --------- examples -----------------------------------------------------------

    
    
    Subvs is a task to do UV vector-subtraction, by selecting time ranges
    in the data as background. Subvs can be used to subtract the background
    continuum emission to separate the time-dependent emission, e.g. solar
    coherent radio bursts.
    
    Keyword arguments:
    vis -- Name of input visibility file (MS)
    default: none; example: vis='ngc5921.ms'
    outputvis -- Name of output uv-subtracted visibility file (MS)
    default: none; example: outputvis='ngc5921_src.ms'
    timerange -- Time range of performing the UV subtraction:
    default='' means all times.  examples:
    timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss'
    timerange = 'hh:mm:ss~hh:mm:ss'
    spw -- Select spectral window/channel.
    default = '' all the spectral channels. Example: spw='0:1~20'
    mode -- operation mode
    default 'linear'
    mode = 'linear': use a linear fit for the background to be subtracted
    mode = 'lowpass': act as a lowpass filter---smooth the data using different smooth
    types and smooth window size. Can be performed along either time
    or frequency axis
    mode = 'highpass': act as a highpass filter---smooth the data first, and
    subtract the smoothed data from the original. Can be performed along either time
    or frequency axis
    mode = 'linear' expandable parameters:
    subtime1 -- Time range 1 of the background to be subtracted from the data
    default='' means all times.  format:
    timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss'
    timerange = 'hh:mm:ss~hh:mm:ss'
    subtime2 -- Time range 2 of the backgroud to be subtracted from the data
    default='' means all times.  examples:
    timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss'
    timerange = 'hh:mm:ss~hh:mm:ss'
    mode = 'lowpass' or 'highpass' expandable parameters:
    smoothaxis -- axis of smooth
    Default: 'time'
    smoothaxis = 'time': smooth is along the time axis
    smoothaxis = 'freq': smooth is along the frequency axis
    smoothtype -- type of the smooth depending on the convolving kernel
    Default: 'flat'
    smoothtype = 'flat': convolving kernel is a flat rectangle,
    equivalent to a boxcar moving smooth
    smoothtype = 'hanning': Hanning smooth kernel. See numpy.hanning
    smoothtype = 'hamming': Hamming smooth kernel. See numpy.hamming
    smoothtype = 'bartlett': Bartlett smooth kernel. See numpy.bartlett
    smoothtype = 'blackman': Blackman smooth kernel. See numpy.blackman
    smoothwidth -- width of the smooth kernel
    Default: 5
    Examples: smoothwidth=5, meaning the width is 5 pixels
    splitsel -- True or False. default = False. If splitsel = False, then the entire input
    measurement set is copied as the output measurement set (outputvis), with
    background subtracted at selected timerange and spectral channels.
    If splitsel = True,then only the selected timerange and spectral channels
    are copied into the output measurement set (outputvis).
    reverse -- True or False. default = False. If reverse = False, then the times indicated
    by subtime1 and/or subtime2 are treated as background and subtracted; If reverse
    = True, then reverse the sign of the background-subtracted data. The option can
    be used for mapping absorptive structure.
    overwrite -- True or False. default = False. If overwrite = True and
    outputvis already exists, the selected subtime and spw in the
    output measurment set will be replaced with background subtracted
    visibilities


    """

    _info_group_ = """misc"""
    _info_desc_ = """Vector-subtraction in UV using selected time ranges and spectral channels as background"""

    __schema = {'vis': {'type': 'cReqPath', 'coerce': _coerce.expand_path}, 'outputvis': {'type': 'cPath', 'coerce': _coerce.expand_path}, 'timerange': {'type': 'cStr', 'coerce': _coerce.to_str}, 'spw': {'type': 'cStr', 'coerce': _coerce.to_str}, 'mode': {'type': 'cStr', 'coerce': _coerce.to_str, 'allowed': [ 'linear', 'lowpass', 'highpass' ]}, 'subtime1': {'type': 'cStr', 'coerce': _coerce.to_str}, 'subtime2': {'type': 'cStr', 'coerce': _coerce.to_str}, 'smoothaxis': {'type': 'cStr', 'coerce': _coerce.to_str}, 'smoothtype': {'type': 'cStr', 'coerce': _coerce.to_str}, 'smoothwidth': {'type': 'cInt'}, 'splitsel': {'type': 'cBool'}, 'reverse': {'type': 'cBool'}, 'overwrite': {'type': 'cBool'}}

    def __init__(self):
        self.__stdout = None
        self.__stderr = None
        self.__root_frame_ = None

    def __globals_(self):
        if self.__root_frame_ is None:
            self.__root_frame_ = _find_frame( )
            assert self.__root_frame_ is not None, "could not find CASAshell global frame"
        return self.__root_frame_

    def __to_string_(self,value):
        if type(value) is str:
            return "'%s'" % value
        else:
            return str(value)

    def __validate_(self,doc,schema):
        return _pc.validate(doc,schema)

    def __do_inp_output(self,param_prefix,description_str,formatting_chars):
        out = self.__stdout or sys.stdout
        description = description_str.split( )
        prefix_width = 23 + 14 + 4
        output = [ ]
        addon = ''
        first_addon = True
        while len(description) > 0:
            ## starting a new line.....................................................................
            if len(output) == 0:
                ## for first line add parameter information............................................
                if len(param_prefix)-formatting_chars > prefix_width - 1:
                    output.append(param_prefix)
                    continue
                addon = param_prefix + ' #'
                first_addon = True
                addon_formatting = formatting_chars
            else:
                ## for subsequent lines space over prefix width........................................
                addon = (' ' * prefix_width) + '#'
                first_addon = False
                addon_formatting = 0
            ## if first word of description puts us over the screen width, bail........................
            if len(addon + description[0]) - addon_formatting + 1 > self.term_width:
                ## if we're doing the first line make sure it's output.................................
                if first_addon: output.append(addon)
                break
            while len(description) > 0:
                ## if the next description word puts us over break for the next line...................
                if len(addon + description[0]) - addon_formatting + 1 > self.term_width: break
                addon = addon + ' ' + description[0]
                description.pop(0)
            output.append(addon)
        out.write('\n'.join(output) + '\n')

    #--------- return nonsubparam values ----------------------------------------------

    def __vis_dflt( self, glb ):
        return ''

    def __vis( self, glb ):
        if 'vis' in glb: return glb['vis']
        return ''

    def __spw_dflt( self, glb ):
        return ''

    def __spw( self, glb ):
        if 'spw' in glb: return glb['spw']
        return ''

    def __mode_dflt( self, glb ):
        return 'linear'

    def __mode( self, glb ):
        if 'mode' in glb: return glb['mode']
        return 'linear'

    def __outputvis_dflt( self, glb ):
        return ''

    def __outputvis( self, glb ):
        if 'outputvis' in glb: return glb['outputvis']
        return ''

    def __timerange_dflt( self, glb ):
        return ''

    def __timerange( self, glb ):
        if 'timerange' in glb: return glb['timerange']
        return ''

    def __splitsel_dflt( self, glb ):
        return True

    def __splitsel( self, glb ):
        if 'splitsel' in glb: return glb['splitsel']
        return True

    def __reverse_dflt( self, glb ):
        return False

    def __reverse( self, glb ):
        if 'reverse' in glb: return glb['reverse']
        return False

    def __overwrite_dflt( self, glb ):
        return False

    def __overwrite( self, glb ):
        if 'overwrite' in glb: return glb['overwrite']
        return False



    #--------- return inp/go default --------------------------------------------------
    def __smoothaxis_dflt( self, glb ):
        if self.__mode( glb ) == "lowpass": return "time"
        if self.__mode( glb ) == "highpass": return "time"
        return None
    def __smoothwidth_dflt( self, glb ):
        if self.__mode( glb ) == "lowpass": return int(5)
        if self.__mode( glb ) == "highpass": return int(5)
        return None
    def __subtime2_dflt( self, glb ):
        if self.__mode( glb ) == "linear": return ""
        return None
    def __subtime1_dflt( self, glb ):
        if self.__mode( glb ) == "linear": return ""
        return None
    def __smoothtype_dflt( self, glb ):
        if self.__mode( glb ) == "lowpass": return "hanning"
        if self.__mode( glb ) == "highpass": return "hanning"
        return None

    #--------- return subparam values -------------------------------------------------
    def __subtime1( self, glb ):
        if 'subtime1' in glb: return glb['subtime1']
        dflt = self.__subtime1_dflt( glb )
        if dflt is not None: return dflt
        return ''
    def __subtime2( self, glb ):
        if 'subtime2' in glb: return glb['subtime2']
        dflt = self.__subtime2_dflt( glb )
        if dflt is not None: return dflt
        return ''
    def __smoothaxis( self, glb ):
        if 'smoothaxis' in glb: return glb['smoothaxis']
        dflt = self.__smoothaxis_dflt( glb )
        if dflt is not None: return dflt
        return 'time'
    def __smoothtype( self, glb ):
        if 'smoothtype' in glb: return glb['smoothtype']
        dflt = self.__smoothtype_dflt( glb )
        if dflt is not None: return dflt
        return 'flat'
    def __smoothwidth( self, glb ):
        if 'smoothwidth' in glb: return glb['smoothwidth']
        dflt = self.__smoothwidth_dflt( glb )
        if dflt is not None: return dflt
        return int(5)

    #--------- subparam inp output ----------------------------------------------------
    def __vis_inp(self):
        description = ''
        value = self.__vis( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'vis': value},{'vis': self.__schema['vis']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('%-14.14s = %s%-23s%s' % ('vis',pre,self.__to_string_(value),post),description,0+len(pre)+len(post))
    def __outputvis_inp(self):
        description = ''
        value = self.__outputvis( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'outputvis': value},{'outputvis': self.__schema['outputvis']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('%-14.14s = %s%-23s%s' % ('outputvis',pre,self.__to_string_(value),post),description,0+len(pre)+len(post))
    def __timerange_inp(self):
        description = ''
        value = self.__timerange( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'timerange': value},{'timerange': self.__schema['timerange']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('%-14.14s = %s%-23s%s' % ('timerange',pre,self.__to_string_(value),post),description,0+len(pre)+len(post))
    def __spw_inp(self):
        description = ''
        value = self.__spw( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'spw': value},{'spw': self.__schema['spw']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('%-14.14s = %s%-23s%s' % ('spw',pre,self.__to_string_(value),post),description,0+len(pre)+len(post))
    def __mode_inp(self):
        description = ''
        value = self.__mode( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'mode': value},{'mode': self.__schema['mode']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('\x1B[1m\x1B[47m%-14.14s =\x1B[0m %s%-23s%s' % ('mode',pre,self.__to_string_(value),post),description,13+len(pre)+len(post))
    def __subtime1_inp(self):
        if self.__subtime1_dflt( self.__globals_( ) ) is not None:
             description = ''
             value = self.__subtime1( self.__globals_( ) )
             (pre,post) = ('','') if self.__validate_({'subtime1': value},{'subtime1': self.__schema['subtime1']}) else ('\x1B[91m','\x1B[0m')
             self.__do_inp_output('   \x1B[92m%-11.11s =\x1B[0m %s%-23s%s' % ('subtime1',pre,self.__to_string_(value),post),description,9+len(pre)+len(post))
    def __subtime2_inp(self):
        if self.__subtime2_dflt( self.__globals_( ) ) is not None:
             description = ''
             value = self.__subtime2( self.__globals_( ) )
             (pre,post) = ('','') if self.__validate_({'subtime2': value},{'subtime2': self.__schema['subtime2']}) else ('\x1B[91m','\x1B[0m')
             self.__do_inp_output('   \x1B[92m%-11.11s =\x1B[0m %s%-23s%s' % ('subtime2',pre,self.__to_string_(value),post),description,9+len(pre)+len(post))
    def __smoothaxis_inp(self):
        if self.__smoothaxis_dflt( self.__globals_( ) ) is not None:
             description = ''
             value = self.__smoothaxis( self.__globals_( ) )
             (pre,post) = ('','') if self.__validate_({'smoothaxis': value},{'smoothaxis': self.__schema['smoothaxis']}) else ('\x1B[91m','\x1B[0m')
             self.__do_inp_output('   \x1B[92m%-11.11s =\x1B[0m %s%-23s%s' % ('smoothaxis',pre,self.__to_string_(value),post),description,9+len(pre)+len(post))
    def __smoothtype_inp(self):
        if self.__smoothtype_dflt( self.__globals_( ) ) is not None:
             description = ''
             value = self.__smoothtype( self.__globals_( ) )
             (pre,post) = ('','') if self.__validate_({'smoothtype': value},{'smoothtype': self.__schema['smoothtype']}) else ('\x1B[91m','\x1B[0m')
             self.__do_inp_output('   \x1B[92m%-11.11s =\x1B[0m %s%-23s%s' % ('smoothtype',pre,self.__to_string_(value),post),description,9+len(pre)+len(post))
    def __smoothwidth_inp(self):
        if self.__smoothwidth_dflt( self.__globals_( ) ) is not None:
             description = ''
             value = self.__smoothwidth( self.__globals_( ) )
             (pre,post) = ('','') if self.__validate_({'smoothwidth': value},{'smoothwidth': self.__schema['smoothwidth']}) else ('\x1B[91m','\x1B[0m')
             self.__do_inp_output('   \x1B[92m%-11.11s =\x1B[0m %s%-23s%s' % ('smoothwidth',pre,self.__to_string_(value),post),description,9+len(pre)+len(post))
    def __splitsel_inp(self):
        description = ''
        value = self.__splitsel( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'splitsel': value},{'splitsel': self.__schema['splitsel']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('%-14.14s = %s%-23s%s' % ('splitsel',pre,self.__to_string_(value),post),description,0+len(pre)+len(post))
    def __reverse_inp(self):
        description = ''
        value = self.__reverse( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'reverse': value},{'reverse': self.__schema['reverse']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('%-14.14s = %s%-23s%s' % ('reverse',pre,self.__to_string_(value),post),description,0+len(pre)+len(post))
    def __overwrite_inp(self):
        description = ''
        value = self.__overwrite( self.__globals_( ) )
        (pre,post) = ('','') if self.__validate_({'overwrite': value},{'overwrite': self.__schema['overwrite']}) else ('\x1B[91m','\x1B[0m')
        self.__do_inp_output('%-14.14s = %s%-23s%s' % ('overwrite',pre,self.__to_string_(value),post),description,0+len(pre)+len(post))

    #--------- global default implementation-------------------------------------------
    @static_var('state', __sf__('casa_inp_go_state'))
    def set_global_defaults(self):
        self.set_global_defaults.state['last'] = self
        glb = self.__globals_( )
        if 'smoothaxis' in glb: del glb['smoothaxis']
        if 'outputvis' in glb: del glb['outputvis']
        if 'vis' in glb: del glb['vis']
        if 'reverse' in glb: del glb['reverse']
        if 'smoothwidth' in glb: del glb['smoothwidth']
        if 'subtime2' in glb: del glb['subtime2']
        if 'splitsel' in glb: del glb['splitsel']
        if 'mode' in glb: del glb['mode']
        if 'subtime1' in glb: del glb['subtime1']
        if 'overwrite' in glb: del glb['overwrite']
        if 'smoothtype' in glb: del glb['smoothtype']
        if 'spw' in glb: del glb['spw']
        if 'timerange' in glb: del glb['timerange']


    #--------- inp function -----------------------------------------------------------
    def inp(self):
        print("# subvs -- %s" % self._info_desc_)
        self.term_width, self.term_height = shutil.get_terminal_size(fallback=(80, 24))
        self.__vis_inp( )
        self.__outputvis_inp( )
        self.__timerange_inp( )
        self.__spw_inp( )
        self.__mode_inp( )
        self.__subtime1_inp( )
        self.__subtime2_inp( )
        self.__smoothaxis_inp( )
        self.__smoothtype_inp( )
        self.__smoothwidth_inp( )
        self.__splitsel_inp( )
        self.__reverse_inp( )
        self.__overwrite_inp( )

    #--------- tget function ----------------------------------------------------------
    @static_var('state', __sf__('casa_inp_go_state'))
    def tget(self,file=None):
        from casashell.private.stack_manip import find_frame
        from runpy import run_path
        filename = None
        if file is None:
            if os.path.isfile("subvs.last"):
                filename = "subvs.last"
        elif isinstance(file, str):
            if os.path.isfile(file):
                filename = file
        if filename is not None:
            glob = find_frame( )
            newglob = run_path( filename, init_globals={ } )
            for i in newglob:
                glob[i] = newglob[i]
            self.tget.state['last'] = self
        else:
            print("could not find last file, setting defaults instead...")
            self.set_global_defaults( )

    def __call__( self, vis=None, outputvis=None, timerange=None, spw=None, mode=None, subtime1=None, subtime2=None, smoothaxis=None, smoothtype=None, smoothwidth=None, splitsel=None, reverse=None, overwrite=None ):
        def noobj(s):
           if s.startswith('<') and s.endswith('>'):
               return "None"
           else:
               return s
        _prefile = os.path.realpath('subvs.pre')
        _postfile = os.path.realpath('subvs.last')
        _return_result_ = None
        _arguments = [vis,outputvis,timerange,spw,mode,subtime1,subtime2,smoothaxis,smoothtype,smoothwidth,splitsel,reverse,overwrite]
        _invocation_parameters = OrderedDict( )
        if any(map(lambda x: x is not None,_arguments)):
            # invoke python style
            # set the non sub-parameters that are not None
            local_global = { }
            if vis is not None: local_global['vis'] = vis
            if outputvis is not None: local_global['outputvis'] = outputvis
            if timerange is not None: local_global['timerange'] = timerange
            if spw is not None: local_global['spw'] = spw
            if mode is not None: local_global['mode'] = mode
            if splitsel is not None: local_global['splitsel'] = splitsel
            if reverse is not None: local_global['reverse'] = reverse
            if overwrite is not None: local_global['overwrite'] = overwrite

            # the invocation parameters for the non-subparameters can now be set - this picks up those defaults
            _invocation_parameters['vis'] = self.__vis( local_global )
            _invocation_parameters['outputvis'] = self.__outputvis( local_global )
            _invocation_parameters['timerange'] = self.__timerange( local_global )
            _invocation_parameters['spw'] = self.__spw( local_global )
            _invocation_parameters['mode'] = self.__mode( local_global )
            _invocation_parameters['splitsel'] = self.__splitsel( local_global )
            _invocation_parameters['reverse'] = self.__reverse( local_global )
            _invocation_parameters['overwrite'] = self.__overwrite( local_global )

            # the sub-parameters can then be set. Use the supplied value if not None, else the function, which gets the appropriate default
            _invocation_parameters['subtime1'] = self.__subtime1( _invocation_parameters ) if subtime1 is None else subtime1
            _invocation_parameters['subtime2'] = self.__subtime2( _invocation_parameters ) if subtime2 is None else subtime2
            _invocation_parameters['smoothaxis'] = self.__smoothaxis( _invocation_parameters ) if smoothaxis is None else smoothaxis
            _invocation_parameters['smoothtype'] = self.__smoothtype( _invocation_parameters ) if smoothtype is None else smoothtype
            _invocation_parameters['smoothwidth'] = self.__smoothwidth( _invocation_parameters ) if smoothwidth is None else smoothwidth

        else:
            # invoke with inp/go semantics
            _invocation_parameters['vis'] = self.__vis( self.__globals_( ) )
            _invocation_parameters['outputvis'] = self.__outputvis( self.__globals_( ) )
            _invocation_parameters['timerange'] = self.__timerange( self.__globals_( ) )
            _invocation_parameters['spw'] = self.__spw( self.__globals_( ) )
            _invocation_parameters['mode'] = self.__mode( self.__globals_( ) )
            _invocation_parameters['subtime1'] = self.__subtime1( self.__globals_( ) )
            _invocation_parameters['subtime2'] = self.__subtime2( self.__globals_( ) )
            _invocation_parameters['smoothaxis'] = self.__smoothaxis( self.__globals_( ) )
            _invocation_parameters['smoothtype'] = self.__smoothtype( self.__globals_( ) )
            _invocation_parameters['smoothwidth'] = self.__smoothwidth( self.__globals_( ) )
            _invocation_parameters['splitsel'] = self.__splitsel( self.__globals_( ) )
            _invocation_parameters['reverse'] = self.__reverse( self.__globals_( ) )
            _invocation_parameters['overwrite'] = self.__overwrite( self.__globals_( ) )
        try:
            with open(_prefile,'w') as _f:
                for _i in _invocation_parameters:
                    _f.write("%-11s = %s\n" % (_i,noobj(repr(_invocation_parameters[_i]))))
                _f.write("#subvs( ")
                count = 0
                for _i in _invocation_parameters:
                    _f.write("%s=%s" % (_i,noobj(repr(_invocation_parameters[_i]))))
                    count += 1
                    if count < len(_invocation_parameters): _f.write(",")
                _f.write(" )\n")
        except: pass
        try:
            _return_result_ = _subvs_t( _invocation_parameters['vis'],_invocation_parameters['outputvis'],_invocation_parameters['timerange'],_invocation_parameters['spw'],_invocation_parameters['mode'],_invocation_parameters['subtime1'],_invocation_parameters['subtime2'],_invocation_parameters['smoothaxis'],_invocation_parameters['smoothtype'],_invocation_parameters['smoothwidth'],_invocation_parameters['splitsel'],_invocation_parameters['reverse'],_invocation_parameters['overwrite'] )
        except Exception as e:
            from traceback import format_exc
            from casatasks import casalog
            casalog.origin('subvs')
            casalog.post("Exception Reported: Error in subvs: %s" % str(e),'SEVERE')
            casalog.post(format_exc( ))
            _return_result_ = False
        try:
            os.rename(_prefile,_postfile)
        except: pass
        return _return_result_

subvs = _subvs( )

