def save(self, path_file):
        """ Save the model paremeters of the model (.params) and Compress 
            them into a zip file
        """

        # Ensuring the file has the proper name
        folder_name = os.path.dirname(path_file) + '/'
        file_name = os.path.basename(path_file)

        # Checking if the folder is accessible
        if not os.access(folder_name, os.W_OK):
            error_msg = '{} is not an accessible directory.'.format(folder_name)
            raise OSError(error_msg)

        # Delete the CPP object before saving
        del self.model
        
        # Saving the model
        super(NonParametricModel, self).save(path_file)

        # Re-introduce the C++ object
        if 'smooth' in self.name.lower() :
            self.model = _KernelModel(self.bandwidth, self.kernel_type)
        else:
            self.model = _KaplanMeierModel()
        self.load_properties()
    def load(self, path_file):
        """ Load the model paremeters from a zip file into a C++ external
            model 
        """        

        # Loading the model
        super(NonParametricModel, self).load(path_file)

        # Re-introduce the C++ object
        if 'smooth' in self.name.lower() :
            self.model = _KernelModel(self.bandwidth, self.kernel_type)
        else:
            self.model = _KaplanMeierModel()
        self.load_properties()
    def __init__(self,  bandwidth = 0.1, kernel = 'normal' ):

        # Kernel function
        if kernel.lower() == 'uniform' : 
            kernel_type = 0 # Uniform kernel 
            kernel = 'Uniform'
            
        elif kernel.lower().startswith("epa"):
            kernel_type = 1 # Epanechnikov kernel 
            kernel = 'Epanechnikov'
            
        elif kernel.lower() == "normal" : 
            kernel_type = 2 # Normal kernel 
            kernel = 'Normal'
            
        elif kernel.lower().startswith("bi"): 
            kernel_type = 3 # Biweight kernel 
            kernel = 'Biweight'
            
        elif kernel.lower().startswith("tri"): 
            kernel_type = 4 # Triweight kernel 
            kernel = 'Triweight'
            
        elif kernel.lower().startswith("cos"): 
            kernel_type = 5 # Cosine kernel 
            kernel = 'Cosine'

        else:
            raise NotImplementedError('{} is not a valid kernel function.'
                .format(kernel))

        # bandwidth
        if bandwidth <= 0.:
            raise ValueError('bandwidth has to be positive.')

        # Initializing the C++ object
        self.model = _KernelModel(bandwidth, kernel_type)

        # Saving the attributes
        self.bandwidth = bandwidth
        self.kernel = kernel
        self.kernel_type = kernel_type

        # Creating the representation of the object
        self.__repr__()
        self.not_implemented_error = "{} does not have this method."\
            .format(self.name)