예제 #1
0
def assemble(options):
    # check output directory
    out_dir = create_dir(options['--output'])
    # check tophat results
    tophat_dir = options['--tophat']
    # check cufflinks
    if which('cufflinks') is None:
        sys.exit('Cufflinks is required for CIRCexplorer2 assemble!')
    # check genePredToGtf
    if which('genePredToGtf') is None:
        sys.exit('genePredToGtf is required for CIRCexplorer2 assemble!')
    # check gtfToGenePred
    if which('gtfToGenePred') is None:
        sys.exit('gtfToGenePred is required for CIRCexplorer2 assemble!')
    # prepare cufflinks directory
    cufflinks_dir = out_dir
    create_dir(cufflinks_dir)
    # filter ref file
    ref_filter(options['--ref'], tophat_dir, cufflinks_dir)
    # assemble with cufflinks
    cufflinks_assemble(tophat_dir, cufflinks_dir, options['--thread'],
                       options['--remove-rRNA'], options['--max-bundle-frags'])
    # convert assembly results
    convert_assembly_gtf(tophat_dir, cufflinks_dir, options['--ref'],
                         options['--bb'], options['--chrom-size'])
예제 #2
0
    def run(self):
        """Run fastqc and fastqc report"""
        fq_files = []
        # list fastq files
        for x in self.input:
            q1 = self.get_fq_files(x)
            fq_files.extend(q1)

        if not os.path.exists(self.output):
            os.makedirs(self.output)

        fastqc_exe = which('fastqc')

        # check fastqc output
        log.info('fastqc')
        fq_files = self.check_fastqc(self.output, fq_files, overwrite=False)

        # run fastqc
        fq_list = ' '.join(fq_files)
        cmd1 = '{} -t 8 -o {} {} 2> {}'.format(fastqc_exe, self.output,
                                               fq_list,
                                               self.output + '.fastqc.log')
        # cmd1 = 'fastqc -t 8 -o %s %s' % (self.output, fq_list)
        if len(fq_files) > 0:
            run_shell_cmd(cmd1)
            # self.run_shell_cmd(cmd1)

        # fastqc report
        log.info('fastqc-report')
        main_script = os.path.realpath(__file__)
        home = os.path.dirname(main_script)
        report_r = os.path.join(home, 'qc_report.R')
        report_html = os.path.join(self.output, 'fastqc_report.html')
        ## for update template
        if self.template is None:
            self.template = ''
        elif os.path.exists(self.template):
            self.template = os.path.abspath(self.template)
        else:
            self.template = ''

        Rscript_exe = which('Rscript')
        cmd2 = ' '.join([Rscript_exe, report_r, self.output, self.template])

        if os.path.exists(report_html):
            log.info('file exists, fastqc-report skipped')
        else:
            run_shell_cmd(cmd2)

        if not os.path.exists(report_html):
            log.error('failed, generating html file')

        # finish
        log.info('output - %s' % report_html)
예제 #3
0
def main(hostname, port, ca_file, clientcert_file, server_certificates, proxy, insecure):

    print_h1("Überprüfe Systemvorraussetzungen")
    if which('openssl')==None:
        logger.error('Could not find openssl in the path. Please install openssl and add it to the path. The call this script again. Will exit now.')
        exit (1)
    
    if server_certificates is None and proxy is not None:                       
        if ssl.OPENSSL_VERSION_NUMBER < 9999999999: # TODO: ab welcher version von openssl wird --proxy unterstuetz
            logger.error('Your version of OpenSSL does not support proxy setting. Please install OpenSSL x.x.x or later or try --servercertificates argument.')
            exit(1)
    

    if ca_file is not None:
        if os.path.exists(ca_file):
            logger.info("Using the following ca certificate file: "+ca_file)
        else:
            logger.error("ca file not found")
            sys.exit()
    else:
        logger.info("No dedicated ca_file provided. Using system ca.")

    if clientcert_file is not None:
        if os.path.exists(clientcert_file):
            logger.info("Using the following client certificate file: "+clientcert_file)
        else:
            logger.info("client certificate file not found.")
            sys.exit()

    if which('sslyze')==None:
        logger.error('Could not find sslyze in the path. Please install sslyze and add it to the path. The call this script again. Will exit now.')
        exit (1)


    svr=Server(hostname,port,ca_file,clientcert_file,server_certificates, split_proxy(proxy), insecure)

    svr.test_server_for_protocol()

    svr.read_certificates(server_certificates)

    if len(svr.certs)<1:
        logger.error("Zertifikate konnten nicht gelesen werden.")
        exit (1)

    svr.certs[0].check_leaf_certificate()

    if len(svr.certs)>1:
        svr.certs[-1].check_root_certificate()

    if len(svr.certs)>2:
        for crt in svr.certs[1:-1]:
            crt.check_intermediate_certificate()
예제 #4
0
def tophat_map(gtf, out_dir, prefix, fastq, thread, bw=False, scale=False,
               gtf_flag=1):
    '''
    1. Map reads with TopHat2
    2. Extract unmapped reads
    3. Create BigWig file if needed
    '''
    # tophat2 mapping
    print('Map reads with TopHat2...')
    tophat_cmd = 'tophat2 -g 1 --microexon-search -m 2 '
    if gtf_flag:
        tophat_cmd += '-G %s ' % gtf
    tophat_cmd += '-p %s -o %s ' % (thread, out_dir + '/tophat')
    tophat_cmd += '%s/bowtie2_index/%s ' % (out_dir, prefix) + ','.join(fastq)
    tophat_cmd += ' 2> %s/tophat.log' % out_dir
    print('TopHat2 mapping command:')
    print(tophat_cmd)
    return_code = os.system(tophat_cmd) >> 8
    if return_code:
        sys.exit('Error: cannot map reads with TopHat2!')
    # extract unmapped reads
    print('Extract unmapped reads...')
    unmapped_bam = pybedtools.BedTool('%s/tophat/unmapped.bam' % out_dir)
    unmapped_bam.bam_to_fastq(fq='%s/tophat/unmapped.fastq' % out_dir)
    # create Bigwig file if needed
    if bw and which('bedGraphToBigWig') is not None:
        print('Create BigWig file...')
        map_bam_fname = '%s/tophat/accepted_hits.bam' % out_dir
        # index bam if not exist
        if not os.path.isfile(map_bam_fname + '.bai'):
            pysam.index(map_bam_fname)
        map_bam = pysam.AlignmentFile(map_bam_fname, 'rb')
        # extract chrom size file
        chrom_size_fname = '%s/tophat/chrom.size' % out_dir
        with open(chrom_size_fname, 'w') as chrom_size_f:
            for seq in map_bam.header['SQ']:
                chrom_size_f.write('%s\t%s\n' % (seq['SN'], seq['LN']))
        if scale:  # scale to HPB
            mapped_reads = map_bam.mapped
            for read in map_bam:
                read_length = read.query_length
                break
            s = 1000000000.0 / mapped_reads / read_length
        else:
            s = 1
        map_bam = pybedtools.BedTool(map_bam_fname)
        bedgraph_fname = '%s/tophat/accepted_hits.bg' % out_dir
        with open(bedgraph_fname, 'w') as bedgraph_f:
            for line in map_bam.genome_coverage(bg=True, g=chrom_size_fname,
                                                scale=s, split=True):
                value = str(int(float(line[3]) + 0.5))
                bedgraph_f.write('\t'.join(line[:3]) + '\t%s\n' % value)
        bigwig_fname = '%s/tophat/accepted_hits.bw' % out_dir
        return_code = os.system('bedGraphToBigWig %s %s %s' %
                                (bedgraph_fname, chrom_size_fname,
                                 bigwig_fname)) >> 8
        if return_code:
            sys.exit('Error: cannot convert bedGraph to BigWig!')
    else:
        print('Could not find bedGraphToBigWig, so skip this step!')
예제 #5
0
def main(hostname, port, ca_file, server_certificates, proxy):

    print_h1("Überprüfe Systemvorraussetzungen")
    if which('openssl') == None:
        logger.error(
            'Could not find openssl in the path. Please install openssl and add it to the path. The call this script again. Will exit now.'
        )
        exit(1)

    if server_certificates is None and proxy is not None:
        if ssl.OPENSSL_VERSION_NUMBER < 9999999999:  # TODO: ab welcher version von openssl wird --proxy unterstuetz
            logger.error(
                'Your version of OpenSSL does not support proxy setting. Please install OpenSSL x.x.x or later or try --servercertificates argument.'
            )
            exit(1)

    if ca_file is None:
        logger.info("No dedicated ca_file provided. Using default vaule.")
        ca_file = ssl.get_default_verify_paths().openssl_cafile

    logger.info("Using the follwing ca_file: " + ca_file)

    if which('sslyze') == None:
        logger.error(
            'Could not find sslyze in the path. Please install sslyze and add it to the path. The call this script again. Will exit now.'
        )
        exit(1)

    svr = Server(hostname, port, ca_file, server_certificates,
                 split_proxy(proxy))

    svr.test_server_for_protocol()

    svr.read_certificates(server_certificates)

    svr.certs[0].check_leaf_certificate()

    if len(svr.certs) > 1:
        svr.certs[-1].check_root_certificate()

    if len(svr.certs) > 2:
        for crt in svr.certs[1:-1]:
            crt.check_intermediate_certificate()
예제 #6
0
def align(options):
    # check options
    if options['--skip-tophat'] and options['--skip-tophat-fusion']:
        sys.exit('Cannot set --skip-tophat and --skip-tophat-fusion together!')
    if not options['--genome']:
        if not options['--bowtie1'] and not options['--skip-tophat-fusion']:
            sys.exit('TopHat-Fusion require bowtie1 index files!')
        elif not options['--bowtie2'] and not options['--skip-tophat']:
            sys.exit('TopHat2 require bowtie2 index files!')
    skip_tophat = True if options['--skip-tophat'] else False
    skip_tophat_fusion = True if options['--skip-tophat-fusion'] else False
    # check output directory
    out_dir = check_outdir(options['--output'])
    # check tophat
    if which('tophat2') is None:
        sys.exit('TopHat2 is required for CIRCexplorer2 align!')
    # check index files
    if options['--genome']:  # build index
        index_flag = (True, skip_tophat, skip_tophat_fusion)
        prefix1, prefix2 = check_index(index_flag, out_dir,
                                       options['--genome'],
                                       options['--thread'])
    else:  # index exist
        index_flag = (False, skip_tophat, skip_tophat_fusion)
        prefix1, prefix2 = check_index(
            index_flag, out_dir, (options['--bowtie1'], options['--bowtie2']),
            options['--thread'])
    if not skip_tophat:
        # tophat2 mapping
        tophat_map(options['--gtf'],
                   out_dir,
                   prefix2,
                   options['<fastq>'],
                   options['--thread'],
                   bw=options['--bw'],
                   scale=options['--scale'])
    if not skip_tophat_fusion:
        # tophat fusion mapping
        if skip_tophat:  # skip tophat, so use fastq files directly
            tophat_fusion_map(out_dir,
                              prefix1,
                              options['--thread'],
                              fq=options['<fastq>'])
        else:
            tophat_fusion_map(out_dir, prefix1, options['--thread'])
        # parse tophat fusion results
        fusion_bam_f = '%s/tophat_fusion/accepted_hits.bam' % out_dir
        out = '%s/fusion_junction.bed' % out_dir
        tophat_fusion_parse(fusion_bam_f, out)
예제 #7
0
def convert_assembly_gtf(tophat_dir, cufflinks_dir, ref, bb, chrom_size):
    '''
    1. Convert Cufflinks GTF to GenePred
    2. Add gene symbols
    3. Convert to BigBed file if needed
    '''
    # convert cufflinks gtf to genepred
    print('Convert Cufflinks GTF to GenePred...')
    gtf_path = '%s/transcripts.gtf' % cufflinks_dir
    genePred_path = '%s/transcripts.txt' % cufflinks_dir
    return_code = os.system('gtfToGenePred %s %s' %
                            (gtf_path, genePred_path)) >> 8
    if return_code:
        sys.exit('Error: cannot convert gtf to GenePred!')
    # add gene symbol
    print('Add gene symbols...')
    with open(ref, 'r') as ref_f:
        gene_symbol = {line.split()[1]: line.split()[0] for line in ref_f}
    ref_path = '%s/transcripts_ref.txt' % cufflinks_dir
    with open(genePred_path, 'r') as genePred_f, open(ref_path, 'w') as ref_f:
        for line in genePred_f:
            iso = line.split()[0]
            symbol = gene_symbol[iso] if iso in gene_symbol else iso
            ref_f.write(symbol + '\t' + line)
    # convert to bigbed if needed
    if bb:
        if which('bedToBigBed') is not None:
            print('Convert to BigBed file...')
            if not chrom_size:  # no chromsize file, search it in tophat folder
                chrom_size = '%s/tophat/chrom.size' % tophat_dir
                if not os.path.isfile(chrom_size):
                    sys.exit('Please offer the path of chrom.size!')
            bed_path = '%s/transcripts_ref.bed' % cufflinks_dir
            genepred_to_bed(ref_path, bed_path)
            sorted_bed_path = '%s/transcripts_ref_sorted.bed' % cufflinks_dir
            bed = pybedtools.BedTool(bed_path)
            bed = bed.sort()
            bed.saveas(sorted_bed_path)
            bb_path = '%s/transcripts_ref_sorted.bb' % cufflinks_dir
            return_code = os.system(
                'bedToBigBed -type=bed12 %s %s %s' %
                (sorted_bed_path, chrom_size, bb_path)) >> 8
            if return_code:
                sys.exit('Error: cannot convert bed to BigBed!')
        else:
            print('Could not find bedToBigBed, so skip this step!')
예제 #8
0
def align(options):
    # check output directory
    out_dir = check_outdir(options['--output'])
    # check tophat
    if which('tophat2') is None:
        sys.exit('TopHat2 is required for CIRCexplorer2 align!')
    # check index files
    if options['--genome']:  # build index
        prefix1, prefix2 = check_index(False, out_dir, options['--genome'])
    else:  # index exist
        prefix1, prefix2 = check_index(True, out_dir, (options['--bowtie1'],
                                                       options['--bowtie2']))
    # tophat2 mapping
    tophat_map(options['--gtf'], out_dir, prefix2, options['<fastq>'],
               options['--thread'], bw=options['--bw'],
               scale=options['--scale'])
    if not options['--no-tophat-fusion']:
        # tophat fusion mapping
        tophat_fusion_map(out_dir, prefix1, options['--thread'])
예제 #9
0
def anno_run(fn, fout, flog, genome):
    """Run annotatePeaks.pl from HOMER"""
    assert os.path.exists(fn)
    assert isinstance(fout, str)
    assert isinstance(flog, str)
    assert isinstance(genome, str)

    annotatePeaks = which('annotatePeaks.pl')
    if annotatePeaks is None:
        raise ValueError('%10s | command not found: annotatePeaks.pl' %
                         'failed')

    logging.info('running annotatePeaks.pl for %s' % os.path.basename(fn))
    c1 = '%s %s %s' % (annotatePeaks, fn, genome)
    with open(fout, 'wt') as ffout, open(flog, 'wt') as fflog:
        p1 = subprocess.run(shlex.split(c1), stdout=ffout, stderr=fflog)

    if os.path.exists(fout):
        return fout
    else:
        return None
예제 #10
0
def align(options):
    # check output directory
    out_dir = check_outdir(options['--output'])
    # check tophat
    if which('tophat2') is None:
        sys.exit('TopHat2 is required for CIRCexplorer2 align!')
    # check index files
    if options['--genome']:  # build index
        prefix1, prefix2 = check_index(False, out_dir, options['--genome'])
    else:  # index exist
        prefix1, prefix2 = check_index(
            True, out_dir, (options['--bowtie1'], options['--bowtie2']))
    # tophat2 mapping
    tophat_map(options['--gtf'],
               out_dir,
               prefix2,
               options['<fastq>'],
               options['--thread'],
               bw=options['--bw'],
               scale=options['--scale'])
    if not options['--no-tophat-fusion']:
        # tophat fusion mapping
        tophat_fusion_map(out_dir, prefix1, options['--thread'])
예제 #11
0
def tophat_map(gtf, out_dir, prefix, fastq, thread, bw=False, scale=False,
               gtf_flag=1):
    '''
    1. Map reads with TopHat2
    2. Extract unmapped reads
    3. Create BigWig file if needed
    '''
    # tophat2 mapping
    print('Map reads with TopHat2...')
    tophat_cmd = 'tophat2 -g 1 --microexon-search -m 2 '
    if gtf_flag:
        tophat_cmd += '-G %s ' % gtf
    tophat_cmd += '-p %s -o %s ' % (thread, out_dir + '/tophat')
    tophat_cmd += '%s/bowtie2_index/%s ' % (out_dir, prefix) + fastq
    tophat_cmd += ' 2> %s/tophat.log' % out_dir
    print('TopHat2 mapping command:')
    print(tophat_cmd)
    return_code = os.system(tophat_cmd) >> 8
    if return_code:
        sys.exit('Error: cannot map reads with TopHat2!')
    # extract unmapped reads
    print('Extract unmapped reads...')
    unmapped_bam = pybedtools.BedTool('%s/tophat/unmapped.bam' % out_dir)
    unmapped_bam.bam_to_fastq(fq='%s/tophat/unmapped.fastq' % out_dir)
    # create Bigwig file if needed
    if bw:
        if which('bedGraphToBigWig') is not None:
            print('Create BigWig file...')
            map_bam_fname = '%s/tophat/accepted_hits.bam' % out_dir
            # index bam if not exist
            if not os.path.isfile(map_bam_fname + '.bai'):
                pysam.index(map_bam_fname)
            map_bam = pysam.AlignmentFile(map_bam_fname, 'rb')
            # extract chrom size file
            chrom_size_fname = '%s/tophat/chrom.size' % out_dir
            with open(chrom_size_fname, 'w') as chrom_size_f:
                for seq in map_bam.header['SQ']:
                    chrom_size_f.write('%s\t%s\n' % (seq['SN'], seq['LN']))
            if scale:  # scale to HPB
                mapped_reads = map_bam.mapped
                for read in map_bam:
                    read_length = read.query_length
                    break
                s = 1000000000.0 / mapped_reads / read_length
            else:
                s = 1
            map_bam = pybedtools.BedTool(map_bam_fname)
            bedgraph_fname = '%s/tophat/accepted_hits.bg' % out_dir
            with open(bedgraph_fname, 'w') as bedgraph_f:
                for line in map_bam.genome_coverage(bg=True,
                                                    g=chrom_size_fname,
                                                    scale=s, split=True):
                    value = str(int(float(line[3]) + 0.5))
                    bedgraph_f.write('\t'.join(line[:3]) + '\t%s\n' % value)
            bigwig_fname = '%s/tophat/accepted_hits.bw' % out_dir
            return_code = os.system('bedGraphToBigWig %s %s %s' %
                                    (bedgraph_fname, chrom_size_fname,
                                     bigwig_fname)) >> 8
            if return_code:
                sys.exit('Error: cannot convert bedGraph to BigWig!')
        else:
            print('Could not find bedGraphToBigWig, so skip this step!')
예제 #12
0
    def __init__(self):
        """
        Create the main window.
        :return:
        """
        super(RF_Qt, self).__init__()

        # Define variables
        self.fnt_styles = ["Regular", "Italic", "Bold", "Bold Italic"]
        self.fnt_sty_combo_list = []
        self.fnt_file_name_list = []
        self.font_files = None
        self.font_info = FontInfo()
        # Create a QProcess object, and connect it to appropriate slots
        self.cli_process = QProcess(self)
        self.cli_process.setProcessChannelMode(QProcess.MergedChannels)
        self.cli_process.readyRead.connect(self.read_proc_output)
        self.cli_process.started.connect(self.manage_proc)
        self.cli_process.finished.connect(self.manage_proc)
        self.cli_process.error.connect(self.manage_proc)

        # Style for all groupbox labels
        gb_style = "QGroupBox { font-weight: bold; }"
        # Top level layout manager for the window.
        win_layout = QVBoxLayout()
        gb_fnt_files = QGroupBox("Font Files")
        gb_fnt_files.setStyleSheet(gb_style)
        grid_f_f = QGridLayout()
        grid_pos = 0

        # Font Files and styles #

        # Create a grid of font names with their respective font style combo boxes
        for i in range(len(self.fnt_styles)):
            self.fnt_file_name_list.append(QLabel("Load font file..."))
            cmb = QComboBox()
            cmb.addItem("")
            cmb.addItems(self.fnt_styles)
            cmb.setEnabled(False)
            cmb.setToolTip(
                "<qt/>If not automatically detected when the font is added, allows you to select what font "
                "sub-family the font file belongs to"
            )
            self.fnt_sty_combo_list.append(cmb)
            row, col = helper.calc_grid_pos(grid_pos, 2)
            grid_f_f.addWidget(self.fnt_file_name_list[i], row, col)
            grid_pos += 1
            row, col = helper.calc_grid_pos(grid_pos, 2)
            grid_f_f.addWidget(self.fnt_sty_combo_list[i], row, col)
            grid_pos += 1
        grid_f_f.setColumnStretch(0, 1)
        gb_fnt_files.setLayout(grid_f_f)
        win_layout.addWidget(gb_fnt_files)

        # New Font Name #
        gb_fnt_name = QGroupBox("Font Family Name")
        gb_fnt_name.setStyleSheet(gb_style)
        hb_fnt_name = QHBoxLayout()
        self.new_fnt_name = QLineEdit()
        self.new_fnt_name.setToolTip("Enter a name for the modified font.")
        self.new_fnt_name.textEdited[str].connect(self.set_family_name)
        hb_fnt_name.addWidget(self.new_fnt_name)
        gb_fnt_name.setLayout(hb_fnt_name)
        win_layout.addWidget(gb_fnt_name)

        # Options #
        hb_options = QHBoxLayout()

        ## Kerning, Panose, Alt. Name ##
        gb_basic_opt = QGroupBox("Basic Options")
        gb_basic_opt.setStyleSheet(gb_style)
        hb_basic_opt = QHBoxLayout()
        self.basic_opt_list = []
        basic_tooltips = (
            "<qt/>Some readers and software require 'legacy', or 'old style' kerning to be "
            "present for kerning to work.",
            "<qt/>Kobo readers can get confused by PANOSE settings. This option sets all "
            "PANOSE information to 0, or 'any'",
            "<qt/>Some fonts have issues with renaming. If the generated font does not have "
            "the same internal font name as you entered, try enabling this option.",
        )

        for opt, tip in zip(("Legacy Kerning", "Clear PANOSE", "Alt. Name"), basic_tooltips):
            self.basic_opt_list.append(QCheckBox(opt))
            self.basic_opt_list[-1].setToolTip(tip)
            hb_basic_opt.addWidget(self.basic_opt_list[-1])

        gb_basic_opt.setLayout(hb_basic_opt)
        hb_options.addWidget(gb_basic_opt)

        ## Hinting ##
        gb_hint_opt = QGroupBox("Hinting Option")
        gb_hint_opt.setStyleSheet(gb_style)
        hb_hint_opt = QHBoxLayout()
        self.hint_opt_list = []
        hint_tooltips = (
            "<qt/>Keep font hinting as it exists in the orginal font files.<br />"
            "In most cases, this will look fine on most ebook reading devices.",
            '<qt/>Some fonts are manually, or "hand" hinted for specific display types (such as LCD). '
            "These fonts may not look good on other display types such as e-ink, therefore they can be "
            "removed.",
            "<qt/>If you don't like the original hinting, but you want your font to be hinted, "
            "this option will auto hint your font.",
        )
        for opt, tip in zip(("Keep Existing", "Remove Existing", "AutoHint"), hint_tooltips):
            self.hint_opt_list.append(QRadioButton(opt))
            self.hint_opt_list[-1].setToolTip(tip)
            self.hint_opt_list[-1].toggled.connect(self.set_hint)
            hb_hint_opt.addWidget(self.hint_opt_list[-1])

        self.hint_opt_list[0].setChecked(Qt.Checked)
        gb_hint_opt.setLayout(hb_hint_opt)
        hb_options.addWidget(gb_hint_opt)

        win_layout.addLayout(hb_options)

        ## Darken ##
        gb_dark_opt = QGroupBox("Darken Options")
        gb_dark_opt.setStyleSheet(gb_style)
        hb_dark_opt = QHBoxLayout()
        self.darken_opt = QCheckBox("Darken Font")
        self.darken_opt.setToolTip("<qt/>Darken, or add weight to a font to make it easier to read on e-ink screens.")
        self.darken_opt.toggled.connect(self.set_darken_opt)
        hb_dark_opt.addWidget(self.darken_opt)
        self.mod_bearing_opt = QCheckBox("Modify Bearings")
        self.mod_bearing_opt.setToolTip(
            "<qt/>By default, adding weight to a font increases glyph width. Enable this "
            "option to set the glyph width to be roughly equal to the original.<br/><br/>"
            "WARNING: This reduces the spacing between glyphs, and should not be used if "
            "you have added too much weight."
        )
        self.mod_bearing_opt.toggled.connect(self.set_mod_bearing)
        self.mod_bearing_opt.setEnabled(False)
        hb_dark_opt.addWidget(self.mod_bearing_opt)

        self.lbl = QLabel("Darken Amount:")
        self.lbl.setEnabled(False)
        hb_dark_opt.addWidget(self.lbl)
        self.darken_amount_opt = QSlider(Qt.Horizontal)
        self.darken_amount_opt.setMinimum(1)
        self.darken_amount_opt.setMaximum(50)
        self.darken_amount_opt.setValue(12)
        self.darken_amount_opt.setEnabled(False)
        self.darken_amount_opt.setToolTip(
            "<qt/>Set the amount to darken a font by. 50 is considered turning a "
            "regular weight font into a bold weight font. It is not recommended to "
            "darken a font that much however."
        )
        self.darken_amount_opt.valueChanged[int].connect(self.set_darken_amount)
        hb_dark_opt.addWidget(self.darken_amount_opt)
        self.darken_amount_lab = QLabel()
        self.darken_amount_lab.setText(str(self.darken_amount_opt.value()))
        self.darken_amount_lab.setEnabled(False)
        hb_dark_opt.addWidget(self.darken_amount_lab)
        gb_dark_opt.setLayout(hb_dark_opt)

        win_layout.addWidget(gb_dark_opt)

        # Buttons #
        hb_buttons = QHBoxLayout()
        # hb_buttons.addStretch()
        self.gen_ttf_btn = QPushButton("Generate TTF")
        self.gen_ttf_btn.setEnabled(False)
        self.gen_ttf_btn.setToolTip(
            "<qt/>Generate a new TrueType font based on the options chosen in this program. "
            "<br /><br />"
            "The new fonts are saved in a directory of your choosing."
        )
        self.gen_ttf_btn.clicked.connect(self.gen_ttf)
        hb_buttons.addWidget(self.gen_ttf_btn)
        self.load_font_btn = QPushButton("Load Fonts")
        self.load_font_btn.setToolTip("<qt/>Load font files to modify.")
        self.load_font_btn.clicked.connect(self.load_fonts)
        hb_buttons.addWidget(self.load_font_btn)
        self.prog_bar = QProgressBar()
        self.prog_bar.setRange(0, 100)
        hb_buttons.addWidget(self.prog_bar)
        win_layout.addLayout(hb_buttons)

        # Output Log #
        gb_log_win = QGroupBox("Log Window")
        gb_log_win.setStyleSheet(gb_style)
        vb_log = QVBoxLayout()
        out_font = QFont("Courier")
        out_font.setStyleHint(QFont.Monospace)
        self.log_win = QTextEdit()
        self.log_win.setAcceptRichText(False)
        self.log_win.setFont(out_font)
        vb_log.addWidget(self.log_win)
        gb_log_win.setLayout(vb_log)
        win_layout.addWidget(gb_log_win)

        # Show Window #
        self.setCentralWidget(QWidget(self))
        self.centralWidget().setLayout(win_layout)
        self.setWindowTitle("Readify Font")

        self.show()

        # Check if fontforge is actually in users PATH. If it isn't, prompt user to provice a location
        self.ff_path = helper.which("fontforge")
        if not self.ff_path:
            self.set_ff_path()
예제 #13
0
    def __init__(self):
        """
        Create the main window.
        :return:
        """
        super(RF_Qt, self).__init__()

        # Define variables
        self.fnt_styles = ['Regular', 'Italic', 'Bold', 'Bold Italic']
        self.fnt_sty_combo_list = []
        self.fnt_file_name_list = []
        self.font_files = None
        self.font_info = FontInfo()
        # Create a QProcess object, and connect it to appropriate slots
        self.cli_process = QProcess(self)
        self.cli_process.setProcessChannelMode(QProcess.MergedChannels)
        self.cli_process.readyRead.connect(self.read_proc_output)
        self.cli_process.started.connect(self.manage_proc)
        self.cli_process.finished.connect(self.manage_proc)
        self.cli_process.error.connect(self.manage_proc)

        # Style for all groupbox labels
        gb_style = 'QGroupBox { font-weight: bold; }'
        # Top level layout manager for the window.
        win_layout = QVBoxLayout()
        gb_fnt_files = QGroupBox('Font Files')
        gb_fnt_files.setStyleSheet(gb_style)
        grid_f_f = QGridLayout()
        grid_pos = 0

        # Font Files and styles #

        # Create a grid of font names with their respective font style combo boxes
        for i in range(len(self.fnt_styles)):
            self.fnt_file_name_list.append(QLabel('Load font file...'))
            cmb = QComboBox()
            cmb.addItem('')
            cmb.addItems(self.fnt_styles)
            cmb.setEnabled(False)
            cmb.setToolTip(
                '<qt/>If not automatically detected when the font is added, allows you to select what font '
                'sub-family the font file belongs to')
            self.fnt_sty_combo_list.append(cmb)
            row, col = helper.calc_grid_pos(grid_pos, 2)
            grid_f_f.addWidget(self.fnt_file_name_list[i], row, col)
            grid_pos += 1
            row, col = helper.calc_grid_pos(grid_pos, 2)
            grid_f_f.addWidget(self.fnt_sty_combo_list[i], row, col)
            grid_pos += 1
        grid_f_f.setColumnStretch(0, 1)
        gb_fnt_files.setLayout(grid_f_f)
        win_layout.addWidget(gb_fnt_files)

        # New Font Name #
        gb_fnt_name = QGroupBox('Font Family Name')
        gb_fnt_name.setStyleSheet(gb_style)
        hb_fnt_name = QHBoxLayout()
        self.new_fnt_name = QLineEdit()
        self.new_fnt_name.setToolTip('Enter a name for the modified font.')
        self.new_fnt_name.textEdited[str].connect(self.set_family_name)
        hb_fnt_name.addWidget(self.new_fnt_name)
        gb_fnt_name.setLayout(hb_fnt_name)
        win_layout.addWidget(gb_fnt_name)

        # Options #
        hb_options = QHBoxLayout()

        ## Kerning, Panose, Alt. Name ##
        gb_basic_opt = QGroupBox('Basic Options')
        gb_basic_opt.setStyleSheet(gb_style)
        hb_basic_opt = QHBoxLayout()
        self.basic_opt_list = []
        basic_tooltips = (
            '<qt/>Some readers and software require \'legacy\', or \'old style\' kerning to be '
            'present for kerning to work.',
            '<qt/>Kobo readers can get confused by PANOSE settings. This option sets all '
            'PANOSE information to 0, or \'any\'',
            '<qt/>Some fonts have issues with renaming. If the generated font does not have '
            'the same internal font name as you entered, try enabling this option.'
        )

        for opt, tip in zip(('Legacy Kerning', 'Clear PANOSE', 'Alt. Name'),
                            basic_tooltips):
            self.basic_opt_list.append(QCheckBox(opt))
            self.basic_opt_list[-1].setToolTip(tip)
            hb_basic_opt.addWidget(self.basic_opt_list[-1])

        gb_basic_opt.setLayout(hb_basic_opt)
        hb_options.addWidget(gb_basic_opt)

        ## Hinting ##
        gb_hint_opt = QGroupBox('Hinting Option')
        gb_hint_opt.setStyleSheet(gb_style)
        hb_hint_opt = QHBoxLayout()
        self.hint_opt_list = []
        hint_tooltips = (
            '<qt/>Keep font hinting as it exists in the orginal font files.<br />'
            'In most cases, this will look fine on most ebook reading devices.',
            '<qt/>Some fonts are manually, or "hand" hinted for specific display types (such as LCD). '
            'These fonts may not look good on other display types such as e-ink, therefore they can be '
            'removed.',
            '<qt/>If you don\'t like the original hinting, but you want your font to be hinted, '
            'this option will auto hint your font.')
        for opt, tip in zip(('Keep Existing', 'Remove Existing', 'AutoHint'),
                            hint_tooltips):
            self.hint_opt_list.append(QRadioButton(opt))
            self.hint_opt_list[-1].setToolTip(tip)
            self.hint_opt_list[-1].toggled.connect(self.set_hint)
            hb_hint_opt.addWidget(self.hint_opt_list[-1])

        self.hint_opt_list[0].setChecked(Qt.Checked)
        gb_hint_opt.setLayout(hb_hint_opt)
        hb_options.addWidget(gb_hint_opt)

        win_layout.addLayout(hb_options)

        ## Darken ##
        gb_dark_opt = QGroupBox('Darken Options')
        gb_dark_opt.setStyleSheet(gb_style)
        hb_dark_opt = QHBoxLayout()
        self.darken_opt = QCheckBox('Darken Font')
        self.darken_opt.setToolTip(
            '<qt/>Darken, or add weight to a font to make it easier to read on e-ink screens.'
        )
        self.darken_opt.toggled.connect(self.set_darken_opt)
        hb_dark_opt.addWidget(self.darken_opt)
        self.mod_bearing_opt = QCheckBox('Modify Bearings')
        self.mod_bearing_opt.setToolTip(
            '<qt/>By default, adding weight to a font increases glyph width. Enable this '
            'option to set the glyph width to be roughly equal to the original.<br/><br/>'
            'WARNING: This reduces the spacing between glyphs, and should not be used if '
            'you have added too much weight.')
        self.mod_bearing_opt.toggled.connect(self.set_mod_bearing)
        self.mod_bearing_opt.setEnabled(False)
        hb_dark_opt.addWidget(self.mod_bearing_opt)

        self.lbl = QLabel('Darken Amount:')
        self.lbl.setEnabled(False)
        hb_dark_opt.addWidget(self.lbl)
        self.darken_amount_opt = QSlider(Qt.Horizontal)
        self.darken_amount_opt.setMinimum(1)
        self.darken_amount_opt.setMaximum(50)
        self.darken_amount_opt.setValue(12)
        self.darken_amount_opt.setEnabled(False)
        self.darken_amount_opt.setToolTip(
            '<qt/>Set the amount to darken a font by. 50 is considered turning a '
            'regular weight font into a bold weight font. It is not recommended to '
            'darken a font that much however.')
        self.darken_amount_opt.valueChanged[int].connect(
            self.set_darken_amount)
        hb_dark_opt.addWidget(self.darken_amount_opt)
        self.darken_amount_lab = QLabel()
        self.darken_amount_lab.setText(str(self.darken_amount_opt.value()))
        self.darken_amount_lab.setEnabled(False)
        hb_dark_opt.addWidget(self.darken_amount_lab)
        gb_dark_opt.setLayout(hb_dark_opt)

        win_layout.addWidget(gb_dark_opt)

        # Buttons #
        hb_buttons = QHBoxLayout()
        #hb_buttons.addStretch()
        self.gen_ttf_btn = QPushButton('Generate TTF')
        self.gen_ttf_btn.setEnabled(False)
        self.gen_ttf_btn.setToolTip(
            '<qt/>Generate a new TrueType font based on the options chosen in this program. '
            '<br /><br />'
            'The new fonts are saved in a directory of your choosing.')
        self.gen_ttf_btn.clicked.connect(self.gen_ttf)
        hb_buttons.addWidget(self.gen_ttf_btn)
        self.load_font_btn = QPushButton('Load Fonts')
        self.load_font_btn.setToolTip('<qt/>Load font files to modify.')
        self.load_font_btn.clicked.connect(self.load_fonts)
        hb_buttons.addWidget(self.load_font_btn)
        self.prog_bar = QProgressBar()
        self.prog_bar.setRange(0, 100)
        hb_buttons.addWidget(self.prog_bar)
        win_layout.addLayout(hb_buttons)

        # Output Log #
        gb_log_win = QGroupBox('Log Window')
        gb_log_win.setStyleSheet(gb_style)
        vb_log = QVBoxLayout()
        out_font = QFont('Courier')
        out_font.setStyleHint(QFont.Monospace)
        self.log_win = QTextEdit()
        self.log_win.setAcceptRichText(False)
        self.log_win.setFont(out_font)
        vb_log.addWidget(self.log_win)
        gb_log_win.setLayout(vb_log)
        win_layout.addWidget(gb_log_win)

        # Show Window #
        self.setCentralWidget(QWidget(self))
        self.centralWidget().setLayout(win_layout)
        self.setWindowTitle('Readify Font')

        self.show()

        # Check if fontforge is actually in users PATH. If it isn't, prompt user to provice a location
        self.ff_path = helper.which('fontforge')
        if not self.ff_path:
            self.set_ff_path()