Uses bcl2fastq to create .fastq files from a MiSeqRun

def createfastq(self):
        """Uses bcl2fastq to create .fastq files from a MiSeqRun"""
        # If the fastq destination folder is not provided, make the default value of :path/:miseqfoldername
        self.fastqdestination = self.fastqdestination if self.fastqdestination else \
            os.path.join(self.path, self.miseqfoldername)
        # Make the path
        make_path(self.fastqdestination)
        # Create a new sample sheet using self.project name instead of the provided Sample_Project. This ensures
        # that all the FASTQ files are stored in the same output folder
        projectsamplesheet = os.path.join(self.fastqdestination, 'SampleSheet_modified.csv')
        with open(projectsamplesheet, "w") as modifiedsamplesheet:
            # Use the 'original' sample sheet as the template for the new sheet
            with open(self.customsamplesheet) as samplesheet:
                # Iterate through the template sheet, and write lines until the header for the data portion of the sheet
                for line in samplesheet:
                    modifiedsamplesheet.write(line)
                    if 'Sample_ID' in line:
                        # Create a list of the header values
                        header = line.split(',')
                        for subline in samplesheet:
                            # Split the line on commas
                            data = subline.split(',')
                            # Initialise a list to store the values for each sample
                            updateddata = list()
                            # Iterate through the entries in the header, and extract the corresponding value
                            for i, value in enumerate(header):
                                # Find the Sample_Project value, and update it to be self.projectname
                                if data[i] in self.projectlist:
                                    data[i] = self.projectname
                                # If demultiplexing is disabled, don't add the samples to the SampleSheet
                                if self.demultiplex:
                                    # Add the (modified) data to the list
                                    updateddata.append(data[i])
                            # Write the updated string to the new sheet
                            modifiedsamplesheet.write(','.join(updateddata))
        # Set :forward/reverse length to :header.forward/reverse length if the argument is not provided, or it's 'full',
        # otherwise  use the supplied argument
        self.forwardlength = self.header.forwardlength if self.forwardlength.lower()\
            == 'full' else self.forwardlength
        # Set :reverselength to :header.reverselength
        self.reverselength = self.header.reverselength if self.reverselength.lower() \
            == 'full' else self.reverselength
        # As the number of cycles required is the number of forward reads + the index(8) + the second index(8)
        # Also set the basemask variable as required
        if self.reverselength != '0':
            self.readsneeded = int(self.forwardlength) + int(self.reverselength) + self.indexlength
            basemask = "Y{}n*,{},Y{}n*".format(self.forwardlength, self.index, self.reverselength)
        else:
            self.readsneeded = int(self.forwardlength) + self.indexlength
            basemask = "Y{}n*,{},n*".format(self.forwardlength, self.index)
        # Handle plurality appropriately
        samples = 'samples' if self.samplecount != 1 else 'sample'
        number = 'are' if self.samplecount != 1 else 'is'
        logging.info('There {num} {num_samples} {plural} in this run.\n'
                     'MiSeqPath: {miseqpath},\n'
                     'MiSeqFolder: {miseqfolder},\n'
                     'FASTQ destination: {destination},\n'
                     'SampleSheet: {sample_sheet}'
                     .format(num=number,
                             num_samples=self.samplecount,
                             plural=samples,
                             miseqpath=self.miseqpath,
                             miseqfolder=self.miseqfolder,
                             destination=self.fastqdestination,
                             sample_sheet=projectsamplesheet))
        # Count the number of completed cycles in the run of interest
        cycles = glob(os.path.join(self.miseqpath, self.miseqfolder, 'Data', 'Intensities', 'BaseCalls', 'L001', 'C*'))
        while len(cycles) < self.readsneeded:
            logging.info('Currently at {num_cycles} cycles. Waiting until the MiSeq reaches cycle {target_cycle}'
                         .format(num_cycles=len(cycles),
                                 target_cycle=self.readsneeded))
            sleep(300)
            cycles = glob(os.path.join(self.miseqpath, self.miseqfolder,
                                       'Data', 'Intensities', 'BaseCalls', 'L001', 'C*'))
        # configureBClToFastq requires :self.miseqfolder/Data/Intensities/BaseCalls/config.xml in order to work
        # When you download runs from BaseSpace, this file is not provided. There is an empty config.xml file that
        # can be populated with run-specific values and moved to the appropriate folder
        if not os.path.isfile(os.path.join(self.miseqfolder, 'Data', 'Intensities', 'BaseCalls', 'config.xml')):
            self.configfilepopulator()
        if self.debug:
            # Define the bcl2fastq system call for the unit test
            bclcall = "bcl2fastq --input-dir {basecalls} " \
                      "--output-dir {outdir} --sample-sheet {samplesheet} " \
                      "--barcode-mismatches 0 -r 1 -p 1 -w 1 -R {runfolder} --use-bases-mask {mask} " \
                      "--tiles s_1_1101 --minimum-trimmed-read-length 1" \
                .format(basecalls=os.path.join(self.miseqfolder, 'Data', 'Intensities', 'BaseCalls'),
                        outdir=self.fastqdestination,
                        samplesheet=projectsamplesheet,
                        runfolder=self.miseqfolder,
                        mask=basemask)
        # elif not self.demultiplex:
        #     bclcall = "bcl2fastq --input-dir {basecalls} " \
        #               "--output-dir {outdir} --sample-sheet {samplesheet} --no-lane-splitting " \
        #               "-r 1 -p 1 -w 1 -R {runfolder} --use-bases-mask {mask}"\
        #         .format(basecalls=os.path.join(self.miseqfolder, 'Data', 'Intensities', 'BaseCalls'),
        #                 outdir=self.fastqdestination,
        #                 samplesheet=projectsamplesheet,
        #                 runfolder=self.miseqfolder,
        #                 mask=basemask)
        else:
            bclcall = "bcl2fastq --input-dir {basecalls} " \
                      "--output-dir {outdir} --sample-sheet {samplesheet} " \
                      "--barcode-mismatches 1 -r 1 -p 1 -w 1 -R {runfolder} --use-bases-mask {mask}"\
                .format(basecalls=os.path.join(self.miseqfolder, 'Data', 'Intensities', 'BaseCalls'),
                        outdir=self.fastqdestination,
                        samplesheet=projectsamplesheet,
                        runfolder=self.miseqfolder,
                        mask=basemask)
        process = False
        if self.demultiplex:
            if not os.path.isdir(self.projectpath):
                process = True
        else:
            if not os.path.isfile(os.path.join(self.fastqdestination, 'Undetermined_S0_R1_001.fastq.gz')):
                process = True
        if process:
            # Call bcl2fastq
            logging.info('Running bcl2fastq')
            # Run the command
            out, err = run_subprocess(bclcall)
            write_to_logfile(bclcall,
                             bclcall,
                             self.logfile)
            write_to_logfile(out,
                             err,
                             self.logfile)
        # Populate the metadata
        for sample in self.metadata.samples:
            sample.commands = GenObject()
            sample.commands.bcl = bclcall
            sample.run.forwardlength = self.forwardlength
            sample.run.reverselength = self.reverselength
        # Copy the fastq files to a central folder so they can be processed
        self.fastqmover()