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'])
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)
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()
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!')
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()
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)
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!')
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'])
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
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'])
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!')
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()
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()