def singularity_job(self, image, config, singularity_image_dir,
            input=None, output=None, msdir=None,
            **kw):
        
        """
            Run task in singularity
            
        image   :   stimela cab name, e.g. 'cab/simms'
        name    :   This name will be part of the name of the contaier that will 
                    execute the task (now optional)
        config  :   Dictionary of options to parse to the task. This will modify 
                    the parameters in the default parameter file which 
                    can be viewd by running 'stimela cabs -i <cab name>', e.g 'stimela cabs -i simms'
        input   :   input dirctory for cab
        output  :   output directory for cab
        msdir   :   MS directory for cab. Only specify if different from recipe ms_dir


        """

        # check if name has any offending charecters
        offenders = re.findall('\W', self.name)
        if offenders:
            raise StimelaCabParameterError('The cab name \'{:s}\' has some non-alphanumeric characters.'
                                           ' Charecters making up this name must be in [a-z,A-Z,0-9,_]'.format(self.name))

        ## Update I/O with values specified on command line
        # TODO (sphe) I think this feature should be removed
        script_context = self.recipe.stimela_context
        input = script_context.get('_STIMELA_INPUT', None) or input
        output = script_context.get('_STIMELA_OUTPUT', None) or output
        msdir = script_context.get('_STIMELA_MSDIR', None) or msdir

        # Get location of template parameters file
        cabpath = self.recipe.stimela_path + "/cargo/cab/{0:s}/".format(image.split("/")[1])
        parameter_file = cabpath+'/parameters.json'

        name = '{0}-{1}{2}'.format(self.name, id(image), str(time.time()).replace('.', ''))
        _name = '{0}-{1}{2}'.format(self.name, id(image), str(time.time()).replace('.', ''))
        name = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(3))

        _cab = cab.CabDefinition(indir=input, outdir=output,
                    msdir=msdir, parameter_file=parameter_file)

        cab.IODEST = {
            "input"     : "/scratch/input",
            "output"    : "/scratch/output",
            "msfile"    : "/scratch/msdir",
        }
        
        cont = singularity.Container(image, name, 
                    logger=self.log, time_out=self.time_out)

        # Container parameter file will be updated and validated before the container is executed
        cont._cab = _cab
        cont.parameter_file_name = '{0}/{1}.json'.format(self.recipe.parameter_file_dir, name)

        # Remove dismissable kw arguments:
        ops_to_pop = []
        for op in config:
            if isinstance(config[op], dismissable):
                ops_to_pop.append(op)
        for op in ops_to_pop:
            arg = config.pop(op)()
            if arg is not None:
                config[op] = arg
        cont.config = config

        # These are standard volumes and
        # environmental variables. These will be
        # always exist in a cab container
        cont.add_volume(self.recipe.stimela_path, '/scratch/stimela', perm='ro')
        cont.add_volume(cont.parameter_file_name, '/scratch/configfile', perm='ro', noverify=True)
        cont.add_volume("{0:s}/cargo/cab/{1:s}/src/".format( 
                self.recipe.stimela_path, _cab.task), "/scratch/code", "ro")
        cont.add_volume("{0:s}/cargo/cab/singularity_run".format(self.recipe.stimela_path, 
                _cab.task), "/singularity")

        if msdir:
            md = '/scratch/msdir'
            cont.add_volume(msdir, md)
            # Keep a record of the content of the
            # volume
            dirname, dirs, files = [a for a in next(os.walk(msdir))]
            cont.msdir_content = {
                "volume"    :   dirname,
                "dirs"      :   dirs,
                "files"     :   files,
            }

            self.log.debug('Mounting volume \'{0}\' from local file system to \'{1}\' in the container'.format(msdir, md))

        if input:
            cont.add_volume( input,'/scratch/input', perm='ro')
            # Keep a record of the content of the
            # volume
            dirname, dirs, files = [a for a in next(os.walk(input))]
            cont.input_content = {
                "volume"    :   dirname,
                "dirs"      :   dirs,
                "files"     :   files,
            }

            self.log.debug('Mounting volume \'{0}\' from local file system to \'{1}\' in the container'.format(input, '/scratch/input'))

        if not os.path.exists(output):
            os.mkdir(output)

        od = '/scratch/output'
        self.logfile = cont.logfile = '{0}/log-{1}.txt'.format(self.log_dir, _name.split('-')[0])
        if not os.path.exists(self.logfile):
            with open(self.logfile, 'w') as std:
                pass
        cont.add_volume(self.log_dir, "/scratch/logs/logfile")
        cont.add_volume(output, od)
        self.log.debug('Mounting volume \'{0}\' from local file system to \'{1}\' in the container'.format(output, od))
        
        simage = _cab.base.replace("/", "_")
        cont.image = '{0:s}/{1:s}_{2:s}.img'.format(singularity_image_dir, simage, _cab.tag)
        # Added and ready for execution
        self.job = cont

        return 0
Run task in singularity
            
        image   :   stimela cab name, e.g. 'cab/simms'
        name    :   This name will be part of the name of the contaier that will 
                    execute the task (now optional)
        config  :   Dictionary of options to parse to the task. This will modify 
                    the parameters in the default parameter file which 
                    can be viewd by running 'stimela cabs -i <cab name>', e.g 'stimela cabs -i simms'
        input   :   input dirctory for cab
        output  :   output directory for cab
        msdir   :   MS directory for cab. Only specify if different from recipe ms_dir