From c0632e2caa92b7c9a91391f183bd76982cf98bd3 Mon Sep 17 00:00:00 2001 From: aregano Date: Tue, 18 Nov 2025 15:50:10 +0100 Subject: [PATCH 1/2] methylcheck integrating EPICv2 data types on pipeline --- methylcheck/QCreport.py | 2 + methylcheck/cli.py | 11 +- methylcheck/data_files/EPICv2_control.npy | Bin 0 -> 83365 bytes methylcheck/data_files/EPICv2_sex.npy | Bin 0 -> 612886 bytes methylcheck/data_files/epicv2_extC.csv | 16186 ++++++++++++++++++++ methylcheck/data_files/epicv2_extT.csv | 16186 ++++++++++++++++++++ methylcheck/filters.py | 304 + methylcheck/postprocessQC.py | 676 + methylcheck/predict/sex.py | 10 +- methylcheck/probes/filters.py | 12 +- methylcheck/qc_plot.py | 2 + methylcheck/qc_report.py | 657 + methylcheck/rawQC.py | 165 + methylcheck/reports/bead_array.py | 12 +- methylcheck/reports/qc_report.py | 2 +- methylcheck/samples/assign.py | 185 + 16 files changed, 34395 insertions(+), 15 deletions(-) create mode 100644 methylcheck/QCreport.py create mode 100644 methylcheck/data_files/EPICv2_control.npy create mode 100644 methylcheck/data_files/EPICv2_sex.npy create mode 100644 methylcheck/data_files/epicv2_extC.csv create mode 100644 methylcheck/data_files/epicv2_extT.csv create mode 100644 methylcheck/filters.py create mode 100644 methylcheck/postprocessQC.py create mode 100644 methylcheck/qc_report.py create mode 100644 methylcheck/rawQC.py create mode 100644 methylcheck/samples/assign.py diff --git a/methylcheck/QCreport.py b/methylcheck/QCreport.py new file mode 100644 index 0000000..633f866 --- /dev/null +++ b/methylcheck/QCreport.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- + diff --git a/methylcheck/cli.py b/methylcheck/cli.py index 1510c11..f687bd3 100644 --- a/methylcheck/cli.py +++ b/methylcheck/cli.py @@ -47,9 +47,12 @@ def get_filename(array_name): if on_lambda: man_path = Path(MANIFEST_DIR_PATH_LAMBDA).expanduser() else: - man_path = Path(MANIFEST_DIR_PATH).expanduser() - man_filename = ARRAY_FILENAME[array_name] - man_filepath = Path(man_path, man_filename) + if array_name == "epicv2": + man_path = "../software/MethylationEPIC_v2.0" # location of the epicv2 manifest file + else: + man_path = Path(MANIFEST_DIR_PATH).expanduser() + man_filename = ARRAY_FILENAME[array_name] + man_filepath = Path(man_path, man_filename) return man_filepath # shape: should be wide, with more columns than rows. The larger dimension is the probe count. @@ -66,6 +69,8 @@ def get_filename(array_name): return 'epic+' if returns == 'name' else (ArrayType('epic+'), get_filename('epic+')) elif 860000 <= col_count <= 868000: # actual: 865860 return 'epic' if returns == 'name' else (ArrayType('epic'), get_filename('epic')) + elif 868001 <= col_count <= 1999999: # actual: 990k approx + return 'epic' if returns == 'name' else (ArrayType('epicv2'), get_filename('epicv2')) elif 200000 <= col_count <= 300000: # actual: 236685 C20, 262812 v2, 284762 V3-V4, MM285 293220 --- testing, changed max from 270k to 290k for v1.4.6 return 'mouse' if returns == 'name' else (ArrayType('mouse'), get_filename('mouse')) else: diff --git a/methylcheck/data_files/EPICv2_control.npy b/methylcheck/data_files/EPICv2_control.npy new file mode 100644 index 0000000000000000000000000000000000000000..007ee1dfd58615546c2c004651dabb683c83c2e8 GIT binary patch literal 83365 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
    !Ca=z`t_;}JplY}~0o0d86nhdN;>O%9GqE=T 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´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%0D0o?l9 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 r#p>^ len(df.index): + df = df.transpose() + FLIPPED = True # use this to reverse at end, so returned in original orientation. + + # next, actually remove probes from all samples matching these lists. + filtered = df.drop(exclude, errors='ignore') + + # errors = ignore: if a probe is missing from df, or present multiple times, drop what you can. + if verbose == True: + print("""Array {4}: Removed {0} sex linked probes and {1} internal control probes \ +from {2} samples. {3} probes remaining.""".format( + len(exclude_sex), + len(exclude_control), + len(filtered.columns), + len(filtered), + array + )) + discrepancy = (len(exclude_sex) + len(exclude_control)) - (len(df) - len(filtered)) + if discrepancy != 0: + print("Discrepancy between number of probes to exclude ({0}) and number actually removed ({1}): {2}".format( + len(exclude_sex) + len(exclude_control), + len(df) - len(filtered), + discrepancy + )) + if len(exclude_control) == discrepancy: + print("It appears that your sample had no control probes, or that the control probe names didn't match the manifest ({0}).".format(array)) + else: + print("This happens when probes are present multiple times in array, or the manifest doesn't match the array ({0}).".format(array)) + # reverse the FLIP + if FLIPPED: + filtered = filtered.transpose() + return filtered + +def exclude_probes(array, probe_list): + """ +How to: + use list_problem_probes to obtain a list of probes, then pass that in as a probe_list along with the dataframe of beta values (array) + +Resolves a problem whereby probe lists have basic names, but samples have additional meta data added. +Example: + +probe list + ['cg24168924', 'cg15886294', 'cg05943251', 'cg05579622', 'cg01797553', 'cg14885690', 'cg12490816', 'cg02631583', 'cg17361593', 'cg15000031', 'cg21515494', 'cg17219246', 'cg10838001', 'cg13913475', 'cg00492169', 'cg20352786', 'cg05932698', 'cg06736139', 'cg08333283', 'cg10010298', 'cg25984048', 'cg27287823', 'cg19269713', 'cg12456833', 'cg26161708', 'cg04984052', 'cg00033806', 'cg23255774', 'cg10717379', 'cg00880984', 'cg01818617', 'cg18563133', 'cg15895341', 'cg08155050', 'cg06820286', 'cg04325909', 'cg15094920', 'cg08037129', 'cg11161730', 'cg06044537', 'cg11936560', 'cg12404870', 'cg12670496', 'cg01473643', 'cg08605930', 'cg16553354', 'cg22175254', 'cg22966295', 'cg07346931', 'cg06234741'] +sample probe names + Index(['cg00000029_II_F_C_rep1_EPIC', 'cg00000103_II_F_C_rep1_EPIC', 'cg00000109_II_F_C_rep1_EPIC', 'cg00000155_II_F_C_rep1_EPIC', + 'cg00000158_II_F_C_rep1_EPIC', 'cg00000165_II_R_C_rep1_EPIC', 'cg00000221_II_R_C_rep1_EPIC', 'cg00000236_II_R_C_rep1_EPIC', + ... + 'ch.9.98957343R_II_R_O_rep1_EPIC', 'ch.9.98959675F_II_F_O_rep1_EPIC', 'ch.9.98989607R_II_R_O_rep1_EPIC', 'ch.9.991104F_II_F_O_rep1_EPIC'] + +This chops off anything after the first underscore, and compares with probe_list to see if percent match increases. +It then drops probes from array that match probe_list, at least partially. + +ADDED: checking whether array.index is string or int type. Regardless, this should work and not alter the original index.""" + + # 1 - check shape of array, to ensure probes are the index/values + ARRAY = array.index + if len(array.index) < len(array.columns): + ARRAY = array.columns + + pre_overlap = len(set(ARRAY) & set(probe_list)) + + # probe_list is always a list of strings. COERCING to strings here for matching. + array_probes = [str(probe).split('_')[0] for probe in list(ARRAY)] + post_overlap = len(set(array_probes) & set(probe_list)) + + if pre_overlap != post_overlap: + print("matching probes: {0} vs {1} after name fix, yielding {2} probes.".format(pre_overlap, post_overlap, len(array)-post_overlap)) + else: + print("Of {0} probes, {1} matched, yielding {2} probes after filtering.".format(len(array), post_overlap, len(array)-post_overlap)) + if post_overlap >= pre_overlap: + # match which probes to drop from array. + array_probes_lookup = {str(probe).split('_')[0]: probe for probe in list(ARRAY)} + # get a list of unmodified array_probe_names to drop, based on matching the overlapping list with the modified probe names. + exclude = [array_probes_lookup[probe] for probe in (set(array_probes) & set(probe_list))] + return array.drop(exclude, errors='ignore') + print("Nothing removed.") + return array + +def list_problem_probes(array, criteria=None, custom_list=None): + """Function to create a list of probes to exclude from downstream processes. + By default, all probes that have been noted in the literature to have + polymorphisms, cross-hybridization, repeat sequence elements and base color + changes are included in the DEFAULT exclusion list. + + - You can customize the exclusion list by passing in either publication shortnames or criteria into the function. + - you can combine pubs and reasons into the same list of exclusion criteria. + - if a publication doesn't match your array type, it will raise an error and tell you. + + Including any of these labels in pubs (publications) or criteria (described below) + will result in these probes NOT being included in the final exclusion list. + + User also has ability to add custom list of probes to include in final returned list. + + Parameters + ---------- + array: string + name for type of array used + 'IlluminaHumanMethylationEPIC', 'IlluminaHumanMethylation450k' + This shorthand names are also okay: + 'EPIC','EPIC+','450k','27k' + + criteria: list + List of the publications to use when excluding probes. + If the array is 450K the publications may include: + 'Chen2013' + 'Price2013' + 'Zhou2016' + 'Naeem2014' + 'DacaRoszak2015' + If the array is EPIC the publications may include: + 'Zhou2016' + 'McCarthey2016' + If no publication list is specified, probes from + all publications will be added to the exclusion list. + If more than one publication is specified, all probes + from all publications in the list will be added to the + exclusion list. + + criteria: lists + List of the criteria to use when excluding probes. + List may contain the following exculsion criteria: + 'Polymorphism' + 'CrossHybridizing' + 'BaseColorChange' + 'RepeatSequenceElements' + If no criteria list is specified, all critera will be + excluded. If more than one criteria is specified, + all probes meeting any of the listed criteria will be + added to the exclusion list. + + custom_list: list, default None + User-provided list of probes to be excluded. + These probe names have to match the probe names in your data exactly. + + Returns + ------- + probe_exclusion_list: list + List containing probe identifiers to be excluded""" + + translate = { + 'EPIC+': 'IlluminaHumanMethylationEPIC', + 'EPIC': 'IlluminaHumanMethylationEPIC', + '450k': 'IlluminaHumanMethylation450k', + '27k': 'IlluminaHumanMethylation27k', + } + + probe_pubs_translate = { + 'Price2013': 'Price_etal_2013', + 'Chen2013': 'Chen_etal_2013', + 'Naeem2014': 'Naeem_etal_2014', + 'DacaRoszak2015': 'Daca-Roszak_etal_2015', + 'McCartney2016': 'McCartney_etal_2016', + 'Zhou2016': 'Zhou_etal_2016', + } + if array in translate: + array = translate[array] + probe_dataframe = _import_probe_filter_list(array) + """ + I had no idea how this works, so I replaced it. MM July 2019. + -- syntax error when I ran it: these vars are not defined. + args = [Polymorphism, CrossHybridization, + BaseColorChange, RepeatSequenceElements, + Chen2013, Price2013, Zhou2016, Naeem2014, + DacaRoszak2015, McCartney2016]""" + if not custom_list: + custom_list = [] + if not criteria: + probe_exclusion_list = list(set(probe_dataframe['Probe'].values)) + probe_exclusion_list = list(set(probe_exclusion_list + custom_list)) + return probe_exclusion_list + else: + probe_exclusion_list = [] + + # rename criteria to match probe_dataframe names, or pass through. + criteria = [probe_pubs_translate.get(crit, crit) for crit in criteria] + + reasons = ['Polymorphism', 'CrossHybridization', 'BaseColorChange', 'RepeatSequenceElements'] + for reason in criteria: + if reason not in reasons: + continue + df = probe_dataframe[probe_dataframe['Reason'] == reason] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + + epic_pubs = ['Zhou_etal_2016', 'McCartney_etal_2016'] + fourfifty_pubs = ['Chen_etal_2013', 'Price_etal_2013', 'Naeem_etal_2014', 'Daca-Roszak_etal_2015'] + for pub in criteria: + if pub not in (epic_pubs + fourfifty_pubs): + continue + + if pub in fourfifty_pubs and array == 'IlluminaHumanMethylationEPIC': + raise ValueError( + "Citation {0} does not exist for '{1}'.".format(pub, array)) + + if pub in epic_pubs and array == 'IlluminaHumanMethylation450k': + raise ValueError( + "Citation {0} does not exist for '{1}'.".format(pub, array)) + + df = probe_dataframe[probe_dataframe['ShortCitation'] == pub] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + + probe_exclusion_list = list(set(probe_exclusion_list + custom_list)) + return probe_exclusion_list diff --git a/methylcheck/postprocessQC.py b/methylcheck/postprocessQC.py new file mode 100644 index 0000000..d76a51d --- /dev/null +++ b/methylcheck/postprocessQC.py @@ -0,0 +1,676 @@ +# -*- coding: utf-8 -*- +# built ins +import logging +import os +import datetime + +# package +import pandas as pd +import numpy as np +import seaborn as sns +import matplotlib.pyplot as plt +import matplotlib.lines as mlines +from sklearn.manifold import MDS +from tqdm import tqdm + +LOGGER = logging.getLogger(__name__) + + +def mean_beta_plot(df, verbose=False, save=False, silent=False): + """Returns a plot of the average beta values for all probes in a batch of samples. + + Input (df): + - a dataframe with probes in rows and sample_ids in columns. + - to get this formatted import, use `methylprep.consolidate_values_for_sheet()`, + as this will return a matrix of beta-values for a batch of samples (by default).""" + if df.shape[0] < df.shape[1]: + ## ensure probes in rows and samples in cols + if verbose: + print("Your data needed to be transposed (df = df.transpose()).") + LOGGER.info("Your data needed to be transposed (df = df.transpose()).") + df = df.copy().transpose() # don't overwrite the original + + data = df.copy(deep=True) + data['mean'] = data.mean(numeric_only=True, axis=1) + fig, ax = plt.subplots(figsize=(12, 9)) + sns.distplot(data['mean'], hist=False, rug=False, ax=ax, axlabel='beta') + plt.title('Mean Beta Plot') + plt.grid() + plt.xlabel('Mean Beta') + if save: + plt.savefig('mean_beta.png') + if not silent: + plt.show() + else: + plt.close(fig) + + +def beta_density_plot(df, verbose=False, save=False, silent=False): + """Returns a plot of beta values for each sample in a batch of samples as a separate line. + Y-axis values is the count (of what? intensity? normalized?). + X-axis values are beta values (0 to 1) for a single samples + + Input (df): + - a dataframe with probes in rows and sample_ids in columns. + - to get this formatted import, use `methylprep.consolidate_values_for_sheet()`, + as this will return a matrix of beta-values for a batch of samples (by default). + + Returns: + None""" + if df.shape[0] < df.shape[1]: + ## ensure probes in rows and samples in cols + if verbose: + print("Your data needed to be transposed (df = df.transpose()).") + LOGGER.info("Your data needed to be transposed (df = df.transpose()).") + df = df.copy().transpose() # don't overwrite the original + + fig, ax = plt.subplots(figsize=(12, 9)) + + for col in df.columns: + if col != 'Name': # probe name + if len(df.columns) <= 30: + sns.distplot( + df[col], hist=False, rug=False, + label=col, ax=ax, axlabel='beta') + else: + sns.distplot( + df[col], hist=False, rug=False, axlabel='beta') + + if len(df.columns) <= 30: + plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) + #else: + # ax.get_legend().set_visible(False) + # print('suppressing legend') + + plt.title('Beta Density Plot') + plt.grid() + plt.xlabel('Beta values') + if save: + plt.savefig('beta.png') + if not silent: + plt.show() + else: + plt.clf() + plt.cla() + plt.close() + + +def cumulative_sum_beta_distribution(df, cutoff=0.7, verbose=False, save=False, silent=False): + """ attempts to filter outlier samples based on the cumulative area under the curve + exceeding a reasonable value (cutoff). + + Inputs: + DataFrame -- wide format (probes in columns, samples in rows) + cutoff (default 0.7) + silent -- suppresses figure, so justs returns transformed data if False. + if save==True: saves figure to disk. + + Returns: + dataframe with subjects removed that exceed cutoff value.""" + # ensure probes in colums, samples in rows + if df.shape[1] < df.shape[0]: + df = df.copy().transpose() # don't overwrite the original + if verbose: + print("Your data needed to be transposed (df = df.transpose()).") + LOGGER.info("Your data needed to be transposed (df = df.transpose()).") + + good_samples = [] + outliers = [] + if not silent: + print("Calculating area under curve for each sample.") + fig, ax = plt.subplots(figsize=(12, 9)) + # first, check if probes aren't consistent, to avoid a crash here + df = drop_nan_probes(df, silent=silent, verbose=verbose) + + # if silent is True, tqdm will not show process bar. + for subject_num, (row, subject_id) in tqdm(enumerate(zip(df.values, + df.index)), disable=silent): + hist_vals = np.histogram(row, bins=10)[0] + hist_vals = hist_vals / np.sum(hist_vals) + cumulative_sum = np.cumsum(hist_vals) + if cumulative_sum[5] < cutoff: + good_samples.append(subject_num) + sns.distplot(row, hist=False, norm_hist=False) + else: + outliers.append(subject_id) # drop uses ids, not numbers. + + plt.title('Cumulative Sum Beta Distribution (filtered at {0})'.format(cutoff)) + plt.grid() + if len(df.columns) <= 30: + plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) + else: + ax.legend_ = None + if save: + plt.savefig('cum_beta.png') + if not silent: + plt.show() + plt.clf() + plt.cla() + plt.close() + return df.drop(outliers, axis=0) + + +def beta_mds_plot(df, filter_stdev=1.5, verbose=True, save=False, silent=False, multi_params={'draw_box':True}): + """ + 1 needs to read the manifest file for the array, or at least a list of probe names to exclude/include. + manifest_file = pd.read_csv('/Users/nrigby/GitHub/stp-prelim-analysis/working_data/CombinedManifestEPIC.manifest.CoreColumns.csv')[['IlmnID', 'CHR']] + probe_names_no_sex_probes = manifest_file.loc[manifest_file['CHR'].apply(lambda x: x not in ['X', 'Y', np.nan]), 'IlmnID'].values + probe_names_sex_probes = manifest_file.loc[manifest_file['CHR'].apply(lambda x: x in ['X', 'Y']), 'IlmnID'].values + + df_no_sex_probes = df[probe_names_no_sex_probes] + df_no_sex_probes.head() + + Arguments + --------- + df + dataframe of beta values for a batch of samples (rows are probes; cols are samples) + filter_stdev + a value (unit: standard deviations) between 0 and 3 (typically) that represents + the fraction of samples to include, based on the standard deviation of this batch of samples. + So using the default value of 1.5 means that all samples whose MDS-transformed beta sort_values + are within +/- 1.5 standard deviations of the average beta are retained in the data returned. + multi_params + is a dict, passed into this function from a multi-compare-MDS wrapper function, containing: + {return_plot_obj=True, + fig=None, + ax=None, + draw_box=False, + xy_lim=None, + color_num=0, + PSF=1.2 -- plot scale factor (margin beyond points to display)} + + Options + -------- + silent + if running from command line in an automated process, you can run in `silent` mode to suppress any user interaction. + In this case, whatever `filter_stdev` you assign is the final value, and a file will be processed with that param. + Silent also suppresses plots (images) from being generated. only files are returned. + + returns + ------- + returns a filtered dataframe. + if `return_plot_obj` is True, it returns the plot, for making overlays in methylize. + + requires + -------- + pandas, numpy, pyplot, sklearn.manifold.MDS """ + + # ensure "long format": probes in rows and samples in cols. This is how methylprep returns data. + if df.shape[1] < df.shape[0]: + ## methylcheck needs probes in rows and samples in cols. but MDS needs a wide matrix. + df = df.copy().transpose() # don't overwrite the original + if verbose: + print("Your data needed to be transposed (df = df.transpose()).") + LOGGER.info("Your data needed to be transposed (df = df.transpose()).") + if verbose == True: + print(df.shape) + df.head() + LOGGER.info('DataFrame has shape: {0}'.format(df.shape)) + print("Making sure that probes are in columns (the second number should be larger than the first).") + LOGGER.info("Making sure that probes are in columns (the second number should be larger than the first).") + # before running this, you'd typically exclude probes. + print("Starting MDS fit_transform. this may take a while.") + LOGGER.info("Starting MDS fit_transform. this may take a while.") + + #df = drop_nan_probes(df, silent=silent, verbose=verbose) + + # CHECK for missing probe values NaN + missing_probe_counts = df.isna().sum() + total_missing_probes = sum([i for i in missing_probe_counts])/len(df) # sum / columns + if sum([i for i in missing_probe_counts]) > 0: + df = df.dropna() + if verbose == True: + print("We found {0} probe(s) were missing values and removed them from MDS calculations.".format(total_missing_probes)) + if silent == False: + LOGGER.info("{0} probe(s) were missing values removed from MDS calculations.".format(total_missing_probes)) + + mds = MDS(n_jobs=-1, random_state=1, verbose=1) + #n_jobs=-1 means "use all processors" + mds_transformed = mds.fit_transform(df.values) + # pass in df.values (a np.array) instead of a dataframe, as it processes much faster. + # old range is used for plotting, with some margin on outside for chart readability + + # plot_scale_fator -- an empirical number to stretch the plot out and show clusters more easily. + if 'PSF' in multi_params: + PSF = multi_params.get('PSF') + else: + PSF = 2 + + if df.shape[0] < 40: + DOTSIZE = 16 + elif 40 < df.shape[0] < 60: + DOTSIZE = 14 + elif 40 < df.shape[0] < 60: + DOTSIZE = 12 + elif 60 < df.shape[0] < 80: + DOTSIZE = 10 + elif 80 < df.shape[0] < 100: + DOTSIZE = 8 + elif 100 < df.shape[0] < 300: + DOTSIZE = 7 + else: + DOTSIZE = 5 + old_X_range = [min(mds_transformed[:, 0]), max(mds_transformed[:, 0])] + old_Y_range = [min(mds_transformed[:, 1]), max(mds_transformed[:, 1])] + #old_X_range = [old_X_range[0] - PSF*old_X_range[0], old_X_range[1] + PSF*old_X_range[1]] + #old_Y_range = [old_Y_range[0] - PSF*old_Y_range[0], old_Y_range[1] + PSF*old_Y_range[1]] + x_std, y_std = np.std(mds_transformed,axis=0) + x_avg, y_avg = np.mean(mds_transformed,axis=0) + + adj = filter_stdev #(1.5) + + if verbose == True: + print("""You can now remove outliers based on their transformed beta values + falling outside a range, defined by the sample standard deviation.""") + + while True: + df_indexes_to_retain = [] + df_indexes_to_exclude = [] + # xy_lim is a manual override preset boundary cutoff range for MDS filtering. + if multi_params.get('xy_lim'): + xy_lim = multi_params['xy_lim'] + if type(xy_lim) in (list,tuple): # ((xmin, xmax), (ymin, ymax)) + minX = xy_lim[0][0] + maxX = xy_lim[0][1] + minY = xy_lim[1][0] + maxY = xy_lim[1][1] + else: + raise ValueError ("xy_lim in multi_params must be a list or tuple") + else: + minX = round(x_avg - adj*x_std) + maxX = round(x_avg + adj*x_std) + minY = round(y_avg - adj*y_std) + maxY = round(y_avg + adj*y_std) + + if verbose == True: + print('Your acceptable value range: x=({0} to {1}), y=({2} to {3}).'.format( + minX, maxX, + minY, maxY + )) + # md2 are the dots that fall inside the cutoff. + md2 = [] + for idx,row in enumerate(mds_transformed): + if minX <= row[0] <= maxX and minY <= row[1] <= maxY: + md2.append(row) + df_indexes_to_retain.append(idx) + else: + df_indexes_to_exclude.append(idx) + #pandas style: mds2 = mds_transformed[mds_transformed[:, 0] == class_number[:, :2] + + # this is a np array, not a df. Remove all dots that are retained from the "exluded" data set (mds_transformed)) + mds_transformed = np.delete(mds_transformed, [df_indexes_to_retain], axis=0) + md2 = np.array(md2) + + color_num = multi_params.get('color_num',0) + # ADD TO EXISTING FIG... up to 24 colors (repeated 3x for 72 total) + COLORSET = dict(enumerate(['xkcd:blue', 'xkcd:green', 'xkcd:coral', 'xkcd:lightblue', 'xkcd:magenta', 'xkcd:goldenrod', 'xkcd:plum', 'xkcd:beige', + 'xkcd:orange', 'xkcd:orchid', 'xkcd:silver', 'xkcd:purple', 'xkcd:pink', 'xkcd:teal', 'xkcd:tomato', 'xkcd:yellow', + 'xkcd:olive', 'xkcd:lavender', 'xkcd:indigo', 'xkcd:black', 'xkcd:azure', 'xkcd:brown', 'xkcd:aquamarine', 'xkcd:darkblue', + + 'xkcd:blue', 'xkcd:green', 'xkcd:coral', 'xkcd:lightblue', 'xkcd:magenta', 'xkcd:goldenrod', 'xkcd:plum', 'xkcd:beige', + 'xkcd:orange', 'xkcd:orchid', 'xkcd:silver', 'xkcd:purple', 'xkcd:pink', 'xkcd:teal', 'xkcd:tomato', 'xkcd:yellow', + 'xkcd:olive', 'xkcd:lavender', 'xkcd:indigo', 'xkcd:black', 'xkcd:azure', 'xkcd:brown', 'xkcd:aquamarine', 'xkcd:darkblue', + + 'xkcd:blue', 'xkcd:green', 'xkcd:coral', 'xkcd:lightblue', 'xkcd:magenta', 'xkcd:goldenrod', 'xkcd:plum', 'xkcd:beige', + 'xkcd:orange', 'xkcd:orchid', 'xkcd:silver', 'xkcd:purple', 'xkcd:pink', 'xkcd:teal', 'xkcd:tomato', 'xkcd:yellow', + 'xkcd:olive', 'xkcd:lavender', 'xkcd:indigo', 'xkcd:black', 'xkcd:azure', 'xkcd:brown', 'xkcd:aquamarine', 'xkcd:darkblue'])) + + if multi_params.get('fig') == None: + fig = plt.figure(figsize=(12, 9)) + plt.title('MDS Plot of betas from methylation data') + plt.grid() # adds fig.axes implied + else: + fig = multi_params.get('fig') + + if multi_params.get('ax') == None and fig.axes != []: + if verbose: + print('axes', multi_params.get('ax'), fig.axes, 'assigned to ax.') + ax = fig.axes[0] # appears to get implicitly created when plot.grid() runs + elif multi_params.get('ax') == None: + # passing the 'ax' (fig.axes[0]) object back in will avoid the plotlib warning. + ax = fig.add_subplot(1,1,1) + else: + ax = multi_params.get('ax') + + ax.scatter(md2[:, 0], md2[:, 1], s=DOTSIZE, c=COLORSET.get(color_num,'black')) # RETAINED + ax.scatter(mds_transformed[:, 0], mds_transformed[:, 1], s=DOTSIZE, c='xkcd:ivory', edgecolor='black', linewidth='0.2',) # EXCLUDED + + x_range_min = PSF*old_X_range[0] if PSF*old_X_range[0] < minX else PSF*minX + x_range_max = PSF*old_X_range[1] if PSF*old_X_range[1] > maxX else PSF*maxX + y_range_min = PSF*old_Y_range[0] if PSF*old_Y_range[0] < minY else PSF*minY + y_range_max = PSF*old_Y_range[1] if PSF*old_Y_range[1] > maxY else PSF*maxY + ax.set_xlim([x_range_min, x_range_max]) + ax.set_ylim([y_range_min, y_range_max]) + #print(int(x_range_min), int(x_range_max), int(y_range_min), int(y_range_max)) + + if multi_params.get('draw_box') == True: + ax.vlines([minX, maxX], minY, maxY, color=COLORSET.get(color_num,'red'), linestyle=':') + ax.hlines([minY, maxY], minX, maxX, color=COLORSET.get(color_num,'red'), linestyle=':') + + if multi_params.get('return_plot_obj') == True: + return fig, ax, df_indexes_to_retain + + if silent == True: + # take the original dataframe (df) and remove samples that are outside the sample thresholds, returning a new dataframe + df.drop(df.index[df_indexes_to_exclude], inplace=True) + image_name = df.index.name or 'beta_mds_n={0}_p={1}'.format(len(df.index), len(df.columns)) # np.size(df,0), np.size(md2,1) + outfile = '{0}_s={1}_{2}.png'.format(image_name, filter_stdev, datetime.date.today()) + plt.savefig(outfile) + LOGGER.info("Saved {0}".format(outfile)) + plt.close(fig) + # returning DataFrame in original structure: rows are probes; cols are samples. + return df # may need to transpose this first. + else: + plt.show() + plt.close(fig) + + ########## BEGIN INTERACTIVE MODE ############# + print("Original samples {0} vs filtered {1}".format(mds_transformed.shape, md2.shape)) + print('Your scale factor was: {0}'.format(adj)) + adj = input("Enter new scale factor, to accept and save:") + if adj == '': + break + try: + adj = float(adj) + except ValueError: + print("Not a valid number. Type a number with a decimal value, or Press to quit.") + continue + + prev_df = len(df) + if save: + # save file. return dataframe. + fig = plt.figure(figsize=(12, 9)) + plt.title('MDS Plot of betas from methylation data') + plt.grid() # adds fig.axes implied + ax = fig.add_subplot(1,1,1) + ax.scatter(md2[:, 0], md2[:, 1], s=DOTSIZE, c=COLORSET.get(color_num,'black')) # RETAINED + ax.scatter(mds_transformed[:, 0], mds_transformed[:, 1], s=DOTSIZE, c='xkcd:ivory', edgecolor='black', linewidth='0.2',) # EXCLUDED + ax.set_xlim(old_X_range) + ax.set_ylim(old_Y_range) + # take the original dataframe (df) and remove samples that are outside the sample thresholds, returning a new dataframe + df_out = df.drop(df.index[df_indexes_to_exclude]) # inplace=True will modify the original DF outside this function. + + # UNRESOLVED BUG. + # was getting 1069 samples back from this; expected 1076. discrepancy is because + # pre_df_excl = len(df.index[df_indexes_to_exclude]) + # unique_df_excl = len(set(df.index[df_indexes_to_exclude])) + # print(pre_df_excl, unique_df_excl) + + image_name = df.index.name or 'beta_mds_n={0}_p={1}'.format(len(df.index), len(df.columns)) # np.size(df,0), np.size(md2,1) + outfile = '{0}_s={1}_{2}.png'.format(image_name, filter_stdev, datetime.date.today()) + plt.savefig(outfile) + plt.close(fig) # avoids displaying plot again in jupyter. + if verbose: + print("Saved {0}".format(outfile)) + LOGGER.info("Saved {0}".format(outfile)) + else: + df_out = df + # returning DataFrame in original structure: rows are probes; cols are samples. + return df_out #, df_indexes_to_exclude # may need to transpose this first. + + +def mean_beta_compare(df1, df2, save=False, verbose=False, silent=False): + """Use this function to compare two dataframes, pre-vs-post filtering and removal of outliers. + + silent: suppresses figure, so no output unless save==True too.""" + if df1.shape[0] < df1.shape[1]: + ## ensure probes in rows and samples in cols + if verbose: + print("Your first data set needed to be transposed (df = df.transpose()).") + LOGGER.info("Your data needed to be transposed (df = df.transpose()).") + df1 = df1.copy().transpose() # don't overwrite the original + if df2.shape[0] < df2.shape[1]: + ## ensure probes in rows and samples in cols + if verbose: + print("Your second data set needed to be transposed (df = df.transpose()).") + LOGGER.info("Your data needed to be transposed (df = df.transpose()).") + df2 = df2.copy().transpose() # don't overwrite the original + + data1 = df1.copy(deep=True) + data1['mean'] = data1.mean(numeric_only=True, axis=1) + data2 = df2.copy(deep=True) + data2['mean'] = data2.mean(numeric_only=True, axis=1) + + fig, ax = plt.subplots(figsize=(12, 9)) + line1 = sns.distplot(data1['mean'], hist=False, rug=False, ax=ax, axlabel='beta', color='xkcd:blue') + line2 = sns.distplot(data2['mean'], hist=False, rug=False, color='xkcd:green') + plt.title('Mean Beta Plot (Compare pre (blue) vs post (green) filtering)') + plt.grid() + plt.xlabel('Mean Beta') + #plt.legend([line1, line2], ['pre','post'], bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) + if save: + plt.savefig('mean_beta_compare.png') + if not silent: + plt.show() + else: + plt.close('all') + + +def combine_mds(*args, **kwargs): + """ + combine (or segment) datasets how it works + ------------------------------------------ + Use this function on multiple dataframes to combine datasets, or to visualize + parts of the same dataset in separate colors. It is a wrapper of `methylcheck.beta_mds_plot()` and applies + multidimensional scaling to cluster similar samples based on patterns in probe values, as well as identify + possible outlier samples (and exclude them). + + - combine datasets, + - run MDS, + - see how each dataset (or subset) overlaps with the others on a plot, + - exclude outlier samples based on a composite cutoff box (the average bounds of the component data sets) + - calculate the percent of data excluded from the group + + inputs + ------ + - *args: pass in any number of pandas dataframes, and it will combine them into one mds plot. + - alternatively, you may pass in a list of filepaths as strings, and it will attempt to load these files as pickles. + but they must be pickles of pandas dataframes + + optional keyword arguments + -------------------------- + - silent: (default False) + (automated processing mode) + if True, suppresses most information and avoids prompting user for anything. + silent mode processes data but doesn't show the plot. + - save: (default False) + if True, saves the plot png to disk. + - verbose: (default False) + if True, prints extra debug information to screen or logger. + + analysis parameters + ------------------- + - filter_stdev (how broadly should you retain samples? units are standard deviations, defaulting to 1.5 STDEV.) + if you increase this number, fewer outlier samples will be removed. + + returns + ------ + - TODO: one dataframe of the retained samples, cutoff box is avg of datasets + ~~nothing returned (currently)~~ + - TODO: each dataset's results as a transformed file + - default: list of samples retained or excluded + - option: a list of pyplot subplot objects + """ + + # check if already dataframes, or are they strings? + list_of_dfs = list(args) + if any([not isinstance(item, pd.DataFrame) for item in list_of_dfs]): + if set([type(item) for item in list_of_dfs]) == {str}: + try: + list_of_dfs = _load_data(list_of_dfs) + except Exception as e: + raise FileNotFoundError ("Either your files don't exist, or they are not pickled: {0}".format(e)) + # kwargs + save = kwargs.get('save', False) + silent = kwargs.get('silent', False) + verbose = kwargs.get('verbose', True) + filter_stdev = kwargs.get('filter_stdev', 1.5) + output_format = kwargs.get('output') + PRINT = print if verbose else _noprint + + # data to combine + dfs = pd.DataFrame() + # OPTIONAL OUTPUT: TRACK each source df's samples for plot color coding prior to merging + # i.e. was this sample included or excluded at end? + # maybe use a simple class here to track the data as it is being manipulated? + sample_source = {} + frame_transposed = {} + # subplots: possibly useful - list of subplot objects within the figure, and their metadata. + subplots = [] + # track x/y ranges to adjust plot area later + xy_lims = [] + + # PROCESS MDS + fig = None + ax = None + for idx, df in enumerate(list_of_dfs): + transposed = False + if df.shape[1] > df.shape[0]: # put probes in rows + df = df.transpose() + transposed = True + for sample in df.columns: + if sample in sample_source: + print("WARNING: sample names are not unique across data sets") + sample_source[sample] = idx + frame_transposed[idx] = transposed + + # first, PLOT separate MDS, each with its own box. + try: + fig,ax,df_indexes_to_retain = beta_mds_plot(df, filter_stdev=filter_stdev, save=save, verbose=verbose, silent=silent, + multi_params={'return_plot_obj':True, + 'fig':fig, + 'ax':ax, + 'color_num':idx, + 'draw_box':True, + 'PSF':1.2, + }) + subplots.append(fig) + xy_lims.append( (fig.axes[0].get_xlim(), fig.axes[0].get_ylim()) ) # (x_range, y_range) + except Exception as e: + PRINT(e) + + #set max range + x_range_min = min(item[0][0] for item in xy_lims) + x_range_max = max(item[0][1] for item in xy_lims) + y_range_min = min(item[1][0] for item in xy_lims) + y_range_max = max(item[1][1] for item in xy_lims) + fig.axes[0].set_xlim([x_range_min, x_range_max]) + fig.axes[0].set_ylim([y_range_min, y_range_max]) + #PRINT('full chart range', int(x_range_min), int(x_range_max), int(y_range_min), int(y_range_max)) + if not silent: + plt.show() + plt.close('all') + + # PART 2 - calculate the average MDS QC score + #1 run the loop. calc avg MDS boundary box for group. + #2 rerun the loop with this as the specified boundary. + #3 calculate percent retained per dataset + #4 overall QC score is avg percent retained per dataset. + avg_x_range_min = int(sum(item[0][0] for item in xy_lims)/len(xy_lims)) + avg_x_range_max = int(sum(item[0][1] for item in xy_lims)/len(xy_lims)) + avg_y_range_min = int(sum(item[1][0] for item in xy_lims)/len(xy_lims)) + avg_y_range_max = int(sum(item[1][1] for item in xy_lims)/len(xy_lims)) + xy_lim = ((avg_x_range_min, avg_x_range_max), (avg_y_range_min, avg_y_range_max)) + PRINT('Average MDS window coordinate range: (x: {0}, y:{1}'.format(xy_lim[0], xy_lim[1])) + fig = None + ax = None + transformed_dfs = [] + for idx, df in enumerate(list_of_dfs): + if df.shape[1] > df.shape[0]: # put probes in rows + df = df.transpose() + fig,ax,df_indexes_to_retain = beta_mds_plot(df, + filter_stdev=filter_stdev, save=save, verbose=verbose, silent=silent, + multi_params={ + 'return_plot_obj':True, + 'fig':fig, + 'ax':ax, + 'color_num':idx, + 'draw_box':True, + 'xy_lim':xy_lim, + 'PSF':1.2, + }) + try: + if frame_transposed[idx]: + # this data (df) was transposed from file-orientation, so samples are in rows now; probes in columns + df_transformed = df.iloc[df_indexes_to_retain, :] # samples in rows + print(df.shape, df_transformed.shape) + else: + # iloc: first list is row index; 2nd is column index + df_transformed = df.iloc[:, df_indexes_to_retain] # samples in columns + print(df.shape, df_transformed.shape) + transformed_dfs.append(df_transformed) + except: + import pdb;pdb.set_trace() + fig.axes[0].set_xlim([x_range_min, x_range_max]) + fig.axes[0].set_ylim([y_range_min, y_range_max]) + + # https://stackoverflow.com/questions/32213889/get-positions-of-points-in-pathcollection-created-by-scatter + #print(len(fig.axes[0].collections)) # collections has data in every 4th list item. + # items in the collections after the main data set are the excluded points + all_coords = [] + retained = [] + excluded = [] + retained_sample_dfs = [] + for i in range(0, 4*len(list_of_dfs), 1): + DD = fig.axes[0].collections[i] + DD.set_offset_position('data') + #print(DD.get_offsets()) + all_coords.extend(DD.get_offsets().tolist()) + #print(i, len(all_coords)) + if i % 4 == 0: # 0, 4, 8 -- this is the first data set applied to plot. (x,y plot coords) + retained.extend( DD.get_offsets().tolist() ) + # go from plot sample x,y to idx of samples in original dfs. + if i % 4 == 1: # 1, 5, 9, etc -- this is the second data set applied to plot. + excluded.extend( DD.get_offsets().tolist() ) + if verbose: + PRINT('{0} % retained overall ({1} out of {2} samples)'.format( + round(100*len(retained) / (len(retained) + len(excluded))), + len(retained), len(retained) + len(excluded) )) + if not silent: + plt.show() + plt.close('all') + + # TODO: output_format + return transformed_dfs + + +def _load_data(filepaths): + dfs = [] + for ff in filepaths: + df = pd.read_pickle(ff) + dfs.append(df) + return dfs + + +def _noprint(*messages): + """ a helper function to suppress print() if not verbose mode. """ + pass + + +def drop_nan_probes(df, silent=False, verbose=False): + """ accounts for df shape (probes in rows or cols) so dropna() will work. + + the method used inside MDS may be faster, but doesn't tell you which probes were dropped.""" + ### histogram can't have NAN values -- so need to exclude before running, or warn user. + # from https://dzone.com/articles/pandas-find-rows-where-columnfield-is-null -- returns a slimmer df of col/rows with NAN. + dfnan = df[df.isnull().any(axis=1)][df.columns[df.isnull().any()]] + if len(dfnan) > 0 and df.shape[0] > df.shape[1]: # a list of probe names that contain nan. + #probes in rows + pre_shape = df.shape + df = df.dropna() + note = "(probes,samples)" + if not silent: + LOGGER.info(f"dropping probe(s) that are missing a value (for this calculation): {dfnan}") + LOGGER.info(f"retained {df.shape} {note} from the original {pre_shape} {note}.") + if verbose: + print("We found {0} probe(s) were missing values and removed them from calculations.".format(len(dfnan))) + elif len(dfnan.columns) > 0 and df.shape[1] > df.shape[0]: + pre_shape = df.shape + df = df.dropna(axis='columns') + note = "(samples,probes)" + if not silent: + LOGGER.info(f"dropping probe(s) that are missing a value (for this calculation): {dfnan.columns}") + LOGGER.info(f"retained {df.shape} {note} from the original {pre_shape} {note}.") + if verbose: + print("We found {0} probe(s) were missing values and removed them from calculations.".format(len(dfnan.columns))) + return df diff --git a/methylcheck/predict/sex.py b/methylcheck/predict/sex.py index 55a8b28..8606a2d 100644 --- a/methylcheck/predict/sex.py +++ b/methylcheck/predict/sex.py @@ -71,7 +71,7 @@ def get_sex(data_source, array_type=None, verbose=False, plot=False, save=False, This feature won't work if a containers object or tuple of dataframes is passed in, instead of a path. Note: ~90% of Y probes should fail if the sample is female. That chromosome is missing.""" - allowed_array_types = {'27k','450k','epic','epic+','mouse'} + allowed_array_types = {'27k','450k','epic','epic+', 'epicv2', 'mouse'} try: from methylprep.files import Manifest @@ -129,11 +129,15 @@ def get_sex(data_source, array_type=None, verbose=False, plot=False, save=False, array_type = ArrayType(array_type) else: raise ValueError(f"Your array_type must be one of these: {allowed_array_types} or None.") - + print("Array type:", array_type) + if verbose: LOGGER.debug(array_type) LOGGER.setLevel(logging.WARNING) - manifest = Manifest(array_type, on_lambda=on_lambda, verbose=verbose)._Manifest__data_frame # 'custom', '27k', '450k', 'epic', 'epic+' + if str(array_type) == 'epicv2': + manifest = Manifest(array_type, filepath_or_buffer='../software/MethylationEPIC_v2.0/EPIC-8v2-0_A2.csv')._Manifest__data_frame + else: + manifest = Manifest(array_type, on_lambda=on_lambda, verbose=verbose)._Manifest__data_frame # 'custom', '27k', '450k', 'epic', 'epic+' LOGGER.setLevel(logging.INFO) x_probes = manifest.index[manifest['CHR']=='X'] y_probes = manifest.index[manifest['CHR']=='Y'] diff --git a/methylcheck/probes/filters.py b/methylcheck/probes/filters.py index 3702dd3..e66dabf 100644 --- a/methylcheck/probes/filters.py +++ b/methylcheck/probes/filters.py @@ -65,11 +65,13 @@ def _import_probe_exclusion_list(array, _type): Parameters ---------- - array -- [EPIC, EPIC+, 450k, 27k] or ['IlluminaHumanMethylationEPIC', 'IlluminaHumanMethylationEPIC+', 'IlluminaHumanMethylation450k'] + array -- [EPICv2, EPIC, EPIC+, 450k, 27k] or ['IlluminaHumanMethylationEPICv2', 'IlluminaHumanMethylationEPIC', 'IlluminaHumanMethylationEPIC+', 'IlluminaHumanMethylation450k'] type -- [sex, control]""" if array in ('IlluminaHumanMethylation450k','450k','450K'): filename = '450k_{0}.npy'.format(_type) + elif array in ('IlluminaHumanMethylationEPICv2','EPICv2','epicv2'): + filename = 'EPICv2_{0}.npy'.format(_type) elif array in ('IlluminaHumanMethylationEPIC','EPIC','epic'): filename = 'EPIC_{0}.npy'.format(_type) elif array in ('IlluminaHumanMethylationEPIC+','EPIC+','epic+','EPICPLUS','EPIC_PLUS'): @@ -81,7 +83,7 @@ def _import_probe_exclusion_list(array, _type): return [] else: raise ValueError("""Did not recognize array type. Please specify one of - 'IlluminaHumanMethylation450k', 'IlluminaHumanMethylationEPIC', '450k', 'EPIC', 'EPIC+', '27k', 'mouse'.""") + 'EPICv2', 'IlluminaHumanMethylation450k', 'IlluminaHumanMethylationEPIC', '450k', 'EPIC', 'EPIC+', '27k', 'mouse'.""") with resources.path(pkg_namespace, filename) as filepath: probe_list = np.load(filepath, allow_pickle=True) return probe_list @@ -94,8 +96,8 @@ def exclude_sex_control_probes(df, array, no_sex=True, no_control=True, verbose= ---------- df: dataframe of beta values or m-values. array: type of array used. - {'27k', '450k', 'EPIC', 'EPICPLUS', 'MOUSE'} or {'IlluminaHumanMethylation27k','IlluminaHumanMethylation450k','IlluminaHumanMethylationEPIC', 'mouse'} - or {'27k', '450k', 'epic', 'epic+', 'mouse'} + {'27k', '450k', 'EPIC', 'EPICPLUS', 'EPICV2, 'MOUSE'} or {'IlluminaHumanMethylation27k','IlluminaHumanMethylation450k','IlluminaHumanMethylationEPIC', 'mouse'} + or {'27k', '450k', 'epic', 'epic+', 'epicv2', 'mouse'} Optional Arguments ------------------ @@ -125,6 +127,8 @@ def exclude_sex_control_probes(df, array, no_sex=True, no_control=True, verbose= 'EPIC_PLUS': 'epic+', '450K': '450k', '27K': '27k', + 'EPICv2': 'epicv2', + 'IlluminaHumanMethylationEPICv2': 'epicv2', } if array in translate: array = translate[array] diff --git a/methylcheck/qc_plot.py b/methylcheck/qc_plot.py index b5e924f..c0c3525 100644 --- a/methylcheck/qc_plot.py +++ b/methylcheck/qc_plot.py @@ -883,6 +883,8 @@ def bis_conversion_control(path_or_df, use_median=False, on_lambda=False, verbos except ImportError: import pkg_resources pkg_namespace = 'methylcheck.data_files' + + try: with resources.path(pkg_namespace, f'{array_type}_extC.csv') as probe_filepath: ext_C_probes = pd.read_csv(probe_filepath) diff --git a/methylcheck/qc_report.py b/methylcheck/qc_report.py new file mode 100644 index 0000000..314b098 --- /dev/null +++ b/methylcheck/qc_report.py @@ -0,0 +1,657 @@ +import pandas as pd +from pathlib import Path +from io import StringIO +import re +import sys +import logging +import math +LOGGER = logging.getLogger(__name__) +# app +import methylcheck + +run_qc = methylcheck.run_qc + +__all__ = ['run_pipeline', 'run_qc'] + +def run_pipeline(df, **kwargs): + """Run a variety of probe and sample filters in tandem, then plot results + +by specifying all of your options at once, instead of running every part of methylcheck +in piacemeal fashion. + +this is analogous to using the methylcheck CLI, but for notebooks/scripts + +required: + df: (required) + - data as a DataFrame of beta values + - sample names in columns and probes in rows + +parameters: + verbose: (True/False) + default: False -- shows extra info about processing if True + silent: (True/False) + default: False -- suppresses all warnings/info + + exclude_sex: + filters out probes on sex-chromosomes + exclude_control: + filters out illumina control probes + exclude_all: + filters out the most probes (sex-linked, control, and all sketchy-listed probes from papers) + exclude: (list of strings, shorthand references to papers with sketchy probes to exclude) + + If the array is 450K the publications may include: + ``'Chen2013' + 'Price2013' + 'Zhou2016' + 'Naeem2014' + 'DacaRoszak2015'`` + If the array is EPIC the publications may include: + ``'Zhou2016' + 'McCartney2016'`` + or these reasons: + ``'Polymorphism' + 'CrossHybridization' + 'BaseColorChange' + 'RepeatSequenceElements'`` + or use ``'exclude_all'``: + to do maximum filtering, including all of these papers' lists. + + plot: (list of strings) + ['mean_beta_plot', 'beta_density_plot', 'cumulative_sum_beta_distribution', 'beta_mds_plot', 'all'] + if 'all', then all of these plots will be generated. if omitted, no plots are created. + save_plots: (True|False) + default: False + export (True|False): + default: False -- will export the filtered df as a pkl file if True + +note: + this pipeline cannot also apply the array-level methylcheck.run_qc() function + because that relies on additional probe information that may not be present. Everything + in this pipeline applies to a dataframe of beta or m-values for a set of samples. + +returns: + a filtered dataframe object + """ + # verify kwargs are expected strings + param_list ={ + 'exclude': ['Chen2013', + 'Price2013', + 'Zhou2016', + 'Naeem2014' + 'DacaRoszak2015', + 'Zhou2016', + 'McCartney2016', + 'Polymorphism', + 'CrossHybridization', + 'BaseColorChange', + 'RepeatSequenceElements'], + 'verbose': [True, False], + 'silent': [True, False], + 'exclude_sex': [True, False], + 'exclude_control': [True, False], + 'exclude_all': [True, False], + 'plot': ['mean_beta_plot', 'beta_density_plot', 'cumulative_sum_beta_distribution', 'beta_mds_plot', 'all'], + 'save_plots': [True, False], + 'export': [True, False], + 'run_qc': [True, False], + 'on_lambda': [True, False], + } + for k,v in kwargs.items(): + if k not in param_list: + raise KeyError(f"{k} not an option among {list(param_list.keys())}") + possible_values = param_list[k] + if type(v) is list: + for item in v: + if item not in possible_values: + raise ValueError(f"{item} not a valid option for {k}: {possible_values}") + else: + if v not in possible_values: + raise ValueError(f"{item} not a valid option for {k}: {possible_values}") + # now we know all inputs are among the allowed/expected params. + + # set detail level of messages + if kwargs.get('verbose') == True: + logging.basicConfig(level=logging.INFO) + else: + kwargs['verbose'] = False + logging.basicConfig(level=logging.WARNING) + if kwargs.get('silent') == True: + logging.basicConfig(level=logging.ERROR) + else: + kwargs['silent'] = False + + # assign some default pipeline params, if not specified by user + default_params = { + 'verbose': False, + 'silent': False, + 'exclude_all': True, + 'plot': 'all', + 'save_plots': False, + 'export': False, + 'on_lambda': False} + for param,setting in default_params.items(): + if kwargs.get(param) is None: + kwargs[param] = setting + + # determine array type + array_type = methylcheck.detect_array(df, on_lambda=kwargs.get('on_lambda')) + + # apply some filters + if kwargs.get('exclude_all'): + try: + df = methylcheck.exclude_sex_control_probes(df, array_type, verbose=kwargs.get('verbose')) + sketchy_probe_list = methylcheck.list_problem_probes(array_type) + df = methylcheck.exclude_probes(df, sketchy_probe_list) + except ValueError: + exc_type, exc_value, exc_traceback = sys.exc_info() + if "probe list" in str(exc_value) or "probe exclusion lists" in str(exc_value): + # keep df the same instead of filtering. + LOGGER.info(exc_value) + else: + raise Exception(exc_value) + elif kwargs.get('exclude'): + # could be a list or a string + if type(kwargs['exclude']) is not list: + kwargs['exclude'] = [kwargs['exclude']] + try: + sketchy_probe_list = methylcheck.list_problem_probes(array_type, criteria=kwargs['exclude']) + df = methylcheck.exclude_probes(df, sketchy_probe_list) + except: + exc_type, exc_value, exc_traceback = sys.exc_info() + if "probe list" in str(exc_value) or "probe exclusion lists" in str(exc_value): + LOGGER.info(exc_value) + else: + raise Exception(exc_value) + + # apply some more filters + if kwargs.get('exclude_sex') and kwargs.get('exclude_control'): + df = methylcheck.exclude_sex_control_probes(df, array_type, verbose=kwargs.get('verbose')) + elif kwargs.get('exclude_sex'): + df = methylcheck.exclude_sex_control_probes(df, array_type, no_sex=True, no_control=False, verbose=kwargs.get('verbose')) + elif kwargs.get('exclude_control'): + df = methylcheck.exclude_sex_control_probes(df, array_type, no_sex=False, no_control=True, verbose=kwargs.get('verbose')) + + # plot stuff + # run calculations and plots + if 'all' in kwargs.get('plot'): + methylcheck.mean_beta_plot(df, verbose=kwargs['verbose'], save=kwargs['save_plots'], silent=kwargs['silent']) + methylcheck.beta_density_plot(df, verbose=kwargs['verbose'], save=kwargs['save_plots'], silent=kwargs['silent']) + wide_df = df.copy().transpose() + methylcheck.cumulative_sum_beta_distribution(wide_df, verbose=kwargs['verbose'], save=kwargs['save_plots'], silent=kwargs['silent']) + pre_mds = wide_df.shape[0] + df = methylcheck.beta_mds_plot(wide_df, verbose=kwargs['verbose'], save=kwargs['save_plots'], silent=kwargs['silent']) + LOGGER.info(f"MDS filtering dropped {pre_mds - df.shape[1]} samples from dataframe.") + else: + if 'mean_beta_plot' in args.plot: + methylcheck.mean_beta_plot(df, verbose=kwargs['verbose'], save=kwargs.get('save_plots'), silent=kwargs['silent']) + if 'beta_density_plot' in args.plot: + methylcheck.beta_density_plot(df, verbose=kwargs['verbose'], save=kwargs['save_plots'], silent=kwargs['silent']) + if 'cumulative_sum_beta_distribution' in args.plot: + wide_df = df.copy().transpose() + methylcheck.cumulative_sum_beta_distribution(wide_df, verbose=kwargs['verbose'], save=kwargs['save_plots'], silent=kwargs['silent']) + if 'beta_mds_plot' in args.plot: + wide_df = df.copy().transpose() + pre_mds = wide_df.shape[0] + df = methylcheck.beta_mds_plot(wide_df, verbose=kwargs['verbose'], save=kwargs['save_plots'], silent=kwargs['silent']) + LOGGER.info(f"MDS filtering dropped {pre_mds - df.shape[1]} samples from dataframe.") + # also has filter_stdev params to pass in. + if kwargs.get('export') == True: + outfile = 'beta_values_filtered.pkl' # in long format for faster loading + df.to_pickle(outfile) + LOGGER.info(f'Saved {outfile}') + return df + + +def detection_poobah(poobah_df, pval_cutoff): + """Given a dataframe of p-values with sample_ids in columns and probes in index, + calculates the percent failed probes per sample. Part of QC report.""" + out = {} + for sample_id in poobah_df.columns: + total = poobah_df.shape[0] + failed = poobah_df[sample_id][poobah_df[sample_id] >= pval_cutoff].count() + percent_failed = round(100*failed/total,1) + out[sample_id] = percent_failed + return out + +class ReportPDF: + """ReportPDF allows you to build custom QC reports. + +------- +To use: +------- + +- First, initialize the report and pass in kwargs, like ``myReport = ReportPDF(**kwargs)`` +- Next, run ```myReport.run_qc()`` to fill it in. +- Third, you must run ``myReport.close()`` after ``run_qc()`` to save the file to disk. +- You can supply kwargs to specify which QC plots to include + - and supply a list of chart names to control the order of objects in the report. + - if you pass in 'order' in kwargs, any page you omit in the order will be omitted from the final report. + - You may pass in a custom table to override one of the built-in pages. +- include 'path' with the path to your processed pickle files. +- include an optional 'outpath' for where to save the pdf report. + +------- +kwargs: +------- + +- processing params + - filename + - poobah_max_percent + - pval_cutoff + - outpath + - path +- front page text + - title + - author + - subject + - keywords +- if 'debug=True' is in kwargs, + - then it will return a report without any parts that failed. + +-------------- +custom tables: +-------------- + +pass in arbitrary data using kwarg ``custom_tables`` as list of dictionaries with this structure: + +```python +custom_tables=[ + { + 'title': "some title, optional", + 'col_names': [""], + 'row_names': [""], + 'data': [""], + 'order_after': ["string name of the plot this should come after. It cannot appear first in list."] + }, + {"<...second table here...>"} +] +``` + +------------------------ +Pre-processing pipeline: +------------------------ + + Probe-level (w/explanations of suggested exclusions) + - Links to recommended probe exclusion lists/files/papers + - Background subtraction and normalization ('noob') + - Detection p-value ('neg' vs 'oob') + - Dye-bias correction (from SeSAMe) + Sample-level (w/explanations of suggested exclusions) + Detection p-value (% failed probes) + - custom detection (% failed, of those in a user-defined-list supplied to function) + MDS + Suggested for customer to do on their own + - Sex check + - Age check + - SNP check + """ + # larger font + # based on 16pt with 0.1 (10% of page) margins around it: use 80, 26, 16 + # MAXWIDTH = 80 # based on 16pt with 0.1 (10% of page) margins around it + # MAXLINES = 26 + # FONTSIZE = 16 + # ORIGIN = (0.1, 0.1) # achored on page in lower left + # + # normal font -- for 12pt font: use 100 x 44 lines + MAXWIDTH = 100 + MAXLINES = 44 + FONTSIZE = 12 + ORIGIN = (0.1, 0.05) # achored on page in lower left + + def __init__(self, **kwargs): + # https://stackoverflow.com/questions/8187082/how-can-you-set-class-attributes-from-variable-arguments-kwargs-in-python + self.__dict__.update(kwargs) + self.debug = True if self.__dict__.get('debug') == True else False + self.__dict__.pop('debug',None) + self.__dict__['poobah_max_percent'] = self.__dict__.get('poobah_max_percent', 5) + self.__dict__['pval_cutoff'] = self.__dict__.get('pval_cutoff', 0.05) + self.errors = self.open_error_buffer() + + #SHELVING the PDF_PART, since it worked but not neeeded right now + from matplotlib.backends.backend_pdf import PdfPages + self.outfile = Path(self.__dict__.get('outpath','.'), self.__dict__.get('filename', 'multipage_pdf.pdf')) + self.pdf = PdfPages(self.outfile) + import matplotlib.pyplot as plt + self.plt = plt + import textwrap + self.textwrap = textwrap + import datetime + self.today = str(datetime.date.today()) + self.on_lambda = self.__dict__.get('on_lambda', False) + d = self.pdf.infodict() + if any(kwarg in ('title','author','subject','keywords') for kwarg in kwargs): + # set the file's metadata via the PdfPages object: + d['Title'] = self.__dict__.get('title','') + d['Author'] = self.__dict__.get('author','') + d['Subject'] = self.__dict__.get('subject','') + d['Keywords'] = self.__dict__.get('keywords','') + d['CreationDate'] = datetime.datetime.today() + d['ModDate'] = datetime.datetime.today() + + if 'order' in self.__dict__: + self.order = self.__dict__['order'] + else: + self.order = ['beta_density_plot', 'detection_poobah', 'mds', 'auto_qc', + 'M_vs_U', 'qc_signal_intensity', 'controls', 'probe_types'] + + self.tests = { + 'detection_poobah': self.__dict__.get('poobah',True), + 'mds': self.__dict__.get('mds',True), + 'auto_qc': self.__dict__.get('auto_qc',True), # NOT IMPLEMENTED YET # + } + self.plots = { + 'beta_density_plot': self.__dict__.get('beta_density_plot',True), + 'M_vs_U': self.__dict__.get('M_vs_U',True), + 'qc_signal_intensity': self.__dict__.get('qc_signal_intensity',True), # not sure Brian wanted this, but it is available + 'controls': self.__dict__.get('controls',True), # genome studio plots + 'probe_types': self.__dict__.get('probe_types',True), + # FUTURE lower priority: bis-conversion completeness, or GCT score --- https://rdrr.io/bioc/sesame/src/R/sesame.R + } + + self.custom = {} + if 'custom_tables' in self.__dict__: + self.parse_custom_tables(self.__dict__['custom_tables']) + LOGGER.info(f"Found custom_tables and inserted into order: {self.order}") + LOGGER.info(self.custom) + + def parse_custom_tables(self, tables): + """tables is a list of { + 'title': "some title, optional", + 'col_names': [list of strings], + 'row_names': [list of strings, optional], + 'data': [list of lists, with order matching col_names], + 'order_after': [string name of the plot this should come after. It cannot appear first in list.] + }""" + for table in tables: + required_attributes = {'title', 'data', 'order_after', 'col_names'} + for i in required_attributes: + if i not in table: + raise KeyError("Your custom table must contain these keys: {required_attributes} (row_names is optional)") + #1 place order -- refer to this later in self.custom + try: + _index = self.order.index(table['order_after']) + self.order.insert(_index, table['title']) + self.custom[table['title']] = table + except ValueError: + raise ValueError(f"Your custom table's 'order_after' label is not in this list of chart objects, so could not be ordered: {self.order}") + if not isinstance(table['col_names'], list): + raise TypeError(f"Your custom table 'col_names' must be a list.") + if table.get('row_names') and not isinstance(table['row_names'], list): + raise TypeError(f"Your custom table 'row_names' must be a list.") + if not isinstance(table['data'], list): + raise TypeError(f"Your custom table 'data' must be a list of lists, matching the number of columns listed in col_names.") + if not (isinstance(table['data'][0],list) and len(table['data'][0]) == len(table['col_names'])): + raise TypeError(f"Your custom table 'data' must be a list of lists, matching the number of columns listed in col_names.") + # passes! later, the table will be looked-up by title name and fed into chart in order. + + def open_error_buffer(self): + """ preparing a stream of log messages to add to report appendix. """ + appendix = logging.getLogger() + appendix.setLevel(logging.INFO) + errors = StringIO() + error_handler = logging.StreamHandler(errors) + # %(module)s.%(funcName)s() ... %Y-%m-%d + formatter = logging.Formatter('^^^%(asctime)s - %(levelname)s - %(message)s', "%H:%M:%S") + error_handler.setFormatter(formatter) + appendix.addHandler(error_handler) + return errors + + def run_qc(self): + # load all the data from self.path; make S3-compatible too. + path = self.__dict__.get('path','') + if self.tests['detection_poobah'] is True and 'detection_poobah' in self.order: + try: + poobah_df = pd.read_pickle(Path(path,'poobah_values.pkl')) # off by default, process with --export_poobah + except FileNotFoundError: + raise FileNotFoundError(f"Could not load pickle file: 'poobah_values.pkl'. Add 'poobah=False' to inputs to turn this off.") + try: + beta_df = pd.read_pickle(Path(path,'beta_values.pkl')) + meth_df = pd.read_pickle(Path(path,'meth_values.pkl')) + unmeth_df = pd.read_pickle(Path(path,'unmeth_values.pkl')) + control_dict_of_dfs = pd.read_pickle(Path(path,'control_probes.pkl')) + LOGGER.info("Data loaded") + except FileNotFoundError: + raise FileNotFoundError("Could not load pickle files") + + ''' + self.functions = { # NOT USED -- needed to provide different conditions for each function below. # + 'detection_poobah': detection_poobah, + 'mds': methylcheck.beta_mds_plot, + 'auto_qc': None, + 'beta_density_plot': methylcheck.beta_density_plot, + 'M_vs_U': methylcheck.plot_M_vs_U, + 'controls': methylcheck.plot_controls, + 'qc_signal_intensity': methylcheck.qc_signal_intensity, + } + ''' + + for part in self.order: + if part in self.tests and self.tests[part] == True: + try: + if part == 'detection_poobah': + max_allowed = self.__dict__.get('poobah_max_percent') + sample_percent_failed_probes_dict = detection_poobah(poobah_df, pval_cutoff=self.__dict__['pval_cutoff']) + sample_poobah_failures = {sample_id: ("pass" if percent < max_allowed else "fail") for sample_id,percent in sample_percent_failed_probes_dict.items()} + #LOGGER.info(f'detection_poobah: {sample_percent_failed_probes_dict}') + LOGGER.info(f"Poobah: {len([k for k in sample_poobah_failures.values() if k =='fail'])} failure(s) out of {len(sample_poobah_failures)} samples.") + + list_of_lists = [] + for sample_id,percent in sample_percent_failed_probes_dict.items(): + row = [sample_id, percent, sample_poobah_failures[sample_id]] + list_of_lists.append(row) + self.to_table(list_of_lists, col_names=['Sample_ID', 'Percent', 'Pass/Fail'], + row_names=None, add_title='Detection Poobah') + + if part == 'mds': + LOGGER.info("Beta MDS Plot") + # ax and df_to_retain are not used, but could go into a qc chart + fig, ax, df_indexes_to_retain = methylcheck.beta_mds_plot(beta_df, silent=True, multi_params={'return_plot_obj':True, 'draw_box':True}) + self.pdf.savefig(fig) + self.plt.close() + #pretty_table = Table(titles=['Sample_ID', 'MDS Pass/Fail']) + #for sample_id in df_indexes_to_retain: + except Exception as e: + if self.debug: + LOGGER.error(f"Could not process {part}; {e}") + continue + else: + raise Exception(f"Could not process {part}; {e}") + + elif part in self.plots and self.plots[part] == True: + try: + if part == 'beta_density_plot': + LOGGER.info("Beta Density Plot") + fig = methylcheck.beta_density_plot(beta_df, save=False, silent=True, verbose=False, reduce=0.1, plot_title=None, ymax=None, return_fig=True) + self.pdf.savefig(fig) + self.plt.close() + elif part == 'M_vs_U': + LOGGER.info(f"M_vs_U plot") + fig = methylcheck.plot_M_vs_U(meth=meth_df, unmeth=unmeth_df, noob=True, silent=True, verbose=False, plot=True, compare=False, return_fig=True) + self.pdf.savefig(fig) + self.plt.close() + # if not plotting, it will return dict with meth median and unmeth median. + elif part == 'qc_signal_intensity': + LOGGER.info(f"QC signal intensity plot") + fig = methylcheck.qc_signal_intensity(meth=meth_df, unmeth=unmeth_df, silent=True, return_fig=True) + self.pdf.savefig(fig) + self.plt.close() + elif part == 'controls': + LOGGER.info(f"Control probes") + list_of_figs = methylcheck.plot_controls(control_dict_of_dfs, 'all', return_fig=True) + for fig in list_of_figs: + self.pdf.savefig(figure=fig, bbox_inches='tight') + self.plt.close('all') + elif part == 'probe_types': + LOGGER.info(f"Betas by probe type") + list_of_figs = methylcheck.plot_beta_by_type(beta_df, 'all', return_fig=True, silent=True, on_lambda=self.on_lambda) + for fig in list_of_figs: + self.pdf.savefig(figure=fig, bbox_inches='tight') + self.plt.close('all') + except Exception as e: + if self.debug: + LOGGER.error(f"Could not process {part}; {e}") + continue + else: + raise Exception(f"Could not process {part}; {e}") + + elif part in self.custom: + table = self.custom[part] + self.to_table(table['data'], col_names=table['col_names'], + row_names=table.get('row_names'), add_title=table['title']) + + + # and finally, appendix of log messages + appendix_msgs = self.errors.getvalue() + appendix_msgs = appendix_msgs.split('^^^') + # drop the trailing \n at end of each message, if present, but preserve within-line \n line breaks + appendix_msgs = [(msg[:-2] if msg[-2:] == '\n' else msg) for msg in appendix_msgs] + appendix_msgs.insert(0, 'APPENDIX I: PROCESSING MESSAGES') + total_rows = len(appendix_msgs) + last_row = 0 + while last_row <= total_rows: + rows_per_page = 26 + # pretest whether length will fit on a pgae + while True: + para_list = appendix_msgs[last_row : (last_row + rows_per_page)] + para_lengths = [len(i.split('\n')) for i in para_list] + extra_line_wraps = [max(len(self.textwrap.wrap(para, width=self.MAXWIDTH)) -1, 0) for para in para_list] + #print((sum(para_lengths) + len(para_lengths) + sum(extra_line_wraps))) + if (sum(para_lengths) + len(para_lengths) + sum(extra_line_wraps)) > self.MAXLINES: + rows_per_page -= 2 + #print('---',rows_per_page) + else: + break + if rows_per_page <= 0: + break + if rows_per_page <= 0: + LOGGER.error("couldn't write log messages to appendix") + break + self.page_of_paragraphs(para_list, self.pdf, line_height='single') + last_row += rows_per_page + self.errors.close() + + + def exec_summary(self): + """QC exec summary + sample_name/ID + probe % failures + probe_failure pass + auto-qc result (only if present in kwargs passed in, otherwise omitted) + MDS pass + signal intensity pass + if any fails, fail it (so overall pass) + table 2: meta + array type (detect from data) + number of samples (from data) + processing pipeline version number (passed in) + date processed (passed in) + avg probe failure rate + percent of samples that failed + any failures from 'control probes' + reqs a way to capture warnings of data-off-chart + """ + exec_summary_1 = [] + exec_summary_2 = [] # list of lists + exec_summary_samples = [] # temp storage lookup + pass + + def page_of_text(self, text, pdf): + """text is a single big string of text, with whitespace for line breaks. + https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.text.html (0,0) is lower left; (1,1) is upper right """ + print([len(i.split('\n')) for i in [text]]) + firstPage = self.plt.figure(figsize=(11,8.5)) + firstPage.clf() + wrapped_txt = self.textwrap.fill(text, width=self.MAXWIDTH) + #wrapped_txt_list = textwrap.wrap(txt, width=80) + # next, identify paragraph breaks here as strings of writespace, and wrap each part separately? then move onto page. + #firstPage.text(0.5,0.5,txt, size=12, ha="left") # transform=firstPage.transFigure + firstPage.text(self.ORIGIN[0], self.ORIGIN[1], wrapped_txt, size=self.FONTSIZE) + pdf.savefig() + self.plt.close() + + + def page_of_paragraphs(self, para_list, pdf, line_height='double'): + """ https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.text.html (0,0) is lower left; (1,1) is upper right. + this version estimates the size of each paragraph and moves the origin downward accordingly. + tricky because the anchors are lower left, not upper left. + + ok if a paragraph contains whitespace line breaks, OR each para is one long line to be wrapped here. + also - if a paragraph wraps, this accounts for it in total lines count""" + #1 - finding the start points for each paragraph in page, counting backwards, so first paragraph is at top of page. + para_lengths = [len(i.split('\n')) for i in para_list] + extra_line_wraps = [max(len(self.textwrap.wrap(para, width=self.MAXWIDTH)) -1, 0) for para in para_list] + if (sum(para_lengths) + len(para_lengths) + sum(extra_line_wraps)) > self.MAXLINES: + raise ValueError(f"Text lines {(sum(para_lengths) + len(para_lengths) + sum(extra_line_wraps))} > {self.MAXLINES}, the max lines per PDF page allowed.") + #print(para_lengths) -- ok if a paragraph contains whitespace line breaks, OR each para is one long line to be wrapped here. + # assume each line height is 0.1/26 fraction of total page height + + # paragraph spacing + if line_height == 'double': + line_height = round((1 - 2*self.ORIGIN[1])/self.MAXLINES,3) + elif line_height == 'single': + line_height = round(0.5*(1 - 2*self.ORIGIN[1])/self.MAXLINES,3) + else: + pass + # else, line_height is whatever int/float you pass in, for custom spacing. (as fraction of page, so use 0.01 to 0.03) + + paragraph_spacing = line_height # 1 line + + firstPage = self.plt.figure(figsize=(11,8.5)) + firstPage.clf() + current_y_position = (1.0 - self.ORIGIN[1]) # working down page by subtracting + extra_lines = [] # if something doesn't fit on page, include this in error message + for nth, para in enumerate(para_list): + # each para is assumed to be one paragraph of text with no whitespace formatting. + wrapped_txt = self.textwrap.fill(para, width=self.MAXWIDTH) + wrapped_addtl_line_count = max(len(self.textwrap.wrap(para, width=self.MAXWIDTH)) -1, 0) + x_margin = self.ORIGIN[0] + current_y_position -= (line_height * len(para.split('\n'))) + current_y_position -= (line_height * wrapped_addtl_line_count) + if nth > 0: + current_y_position -= paragraph_spacing + if current_y_position < self.ORIGIN[1]: + extra_lines.append(wrapped_txt) + #print(current_y_position, wrapped_addtl_line_count, wrapped_txt) + else: + firstPage.text(x_margin, current_y_position, wrapped_txt, size=self.FONTSIZE) + if extra_lines != []: + print("WARNING: DID NOT FIT") + for extra_line in extra_lines: + print(extra_line) + print("") + pdf.savefig() + self.plt.close() + + def to_table(self, list_of_lists, col_names, row_names=None, add_title=''): + """ + - embeds a table in a PDF page. + - attempts to split long tables into multiple pages. + - should warn if table is too wide to fit. """ + + # stringify numbers; replace None + for idx, sub in enumerate(list_of_lists): + list_of_lists[idx] = [('' if isinstance(i,type(None)) else str(i)) for i in sub] + + rows_per_page = 42 # appears to work for standard default PDF page size and font size. + pages = math.ceil(len(list_of_lists)/rows_per_page) + #paginate table + for page in range(pages): + #LOGGER.debug(f'page {page+1} -- {(page * rows_per_page)}:{(page + 1) * rows_per_page}') + page_data = list_of_lists[(page * rows_per_page) : (page + 1) * rows_per_page] + fig, ax = self.plt.subplots(1, figsize=(10,8)) + #ax.axis('tight') + ax.axis('off') + matplotlib_table = ax.table( + cellText=page_data, + colLabels=col_names, + loc='center', # if len(page_data) >= rows_per_page else 'top', + edges='open', + colLoc='right', + ) + matplotlib_table.auto_set_font_size(False) + matplotlib_table.set_fontsize(12) + if page == 0: + self.plt.title(add_title, y=1.1) #pad=20) # -- placement is off + self.pdf.savefig(fig) + self.plt.close() diff --git a/methylcheck/rawQC.py b/methylcheck/rawQC.py new file mode 100644 index 0000000..3f7e01d --- /dev/null +++ b/methylcheck/rawQC.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +import pkg_resources +import pandas as pd + + +def _import_probe_filter_list(array): + """Function to identify array type and import the + appropriate probe exclusion dataframe""" + + if array == 'IlluminaHumanMethylation450k': + path = 'data_files/450k_polymorphic_crossRxtve_probes.csv.gz' + filepath = pkg_resources.resource_filename(__name__, path) + filter_options = pd.read_csv(filepath) + elif array == 'IlluminaHumanMethylationEPIC': + path = 'data_files/EPIC_polymorphic_crossRxtve_probes.csv.gz' + filepath = pkg_resources.resource_filename(__name__, path) + filter_options = pd.read_csv(filepath) + else: + raise ValueError( + "Did not recognize array type. Please specify 'IlluminaHumanMethylation450k' or 'IlluminaHumanMethylationEPIC'.") + return + return filter_options + + +def createProbeExclusionList(array, pubs=None, criteria=None, custom_list=None): + """Function to create list of probes to exclude from downstream processes. + By default, all probes that have been noted in the literature to have + polymorphisms, cross-hybridization, repeat sequence elements and base color + changes are included in the exclusion list. Setting any of the args for these + reasons or publications (described below) to False will result in these probes + NOT being included in the final exclusion list.to User also has ability to + add custom list of probes to include in final returned list. + + Parameters + ---------- + array: dataframe + Dataframe containing beta values + + pubs: list + List of the publications to use when excluding probes. + If the array is 450K the publications may include: + 'Chen2013' + 'Price2013' + 'Zhou2016' + 'Naeem2014' + 'DacaRoszak2015' + If the array is EPIC the publications may include: + 'Zhou2016' + 'McCarthey2016' + If no publication list is specified, probes from + all publications will be added to the exclusion list. + If more than one publication is specified, all probes + from all publications in the list will be added to the + exclusion list. + + criteria: list + List of the criteria to use when excluding probes. + List may contain the following exculsion criteria: + 'Polymorphism' + 'CrossHybridizing' + 'BaseColorChange' + 'RepeatSequenceElements' + If no criteria list is specified, all critera will be + excluded. If more than one criteria is specified, + all probes meeting any of the listed criteria will be + added to the exclusion list. + + custom_list: list, default None + User provided list of probes to add to probe + exclusion list + + Returns + ------- + probe_exclusion_list: list + List containing probe identifiers to be excluded + + """ + probe_dataframe = _import_probe_filter_list(array) + args = [Polymorphism, CrossHybridization, + BaseColorChange, RepeatSequenceElements, + Chen2013, Price2013, Zhou2016, Naeem2014, + DacaRoszak2015, McCartney2016] + if custom_list is None: + custom_list = [] + if False not in args: + probe_exclusion_list = list(set(probe_dataframe['Probe'].values)) + probe_exclusion_list = list(set(probe_exclusion_list + custom_list)) + else: + probe_exclusion_list = [] + if Polymorphism is True: + df = probe_dataframe[probe_dataframe['Reason'] == 'Polymorphism'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if CrossHybridization is True: + df = probe_dataframe[probe_dataframe['Reason'] + == 'CrossHybridization'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if BaseColorChange is True: + df = probe_dataframe[probe_dataframe['Reason'] + == 'BaseColorChange'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if RepeatSequenceElements is True: + df = probe_dataframe[probe_dataframe['Reason'] + == 'RepeatSequenceElements'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if Chen2013 is True: + if array == 'IlluminaHumanMethylationEPIC': + raise ValueError( + "Citation Chen2013 does not exist for 'IlluminaHumanMethylationEPIC'.") + return + else: + df = probe_dataframe[probe_dataframe['ShortCitation'] + == 'Chen2013'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if Price2013 is True: + if array == 'IlluminaHumanMethylationEPIC': + raise ValueError( + "Citation Price2013 does not exist for 'IlluminaHumanMethylationEPIC'.") + return + else: + df = probe_dataframe[probe_dataframe['ShortCitation'] + == 'Price2013'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if Naeem2014 is True: + if array == 'IlluminaHumanMethylationEPIC': + raise ValueError( + "Citation Naeem2014 does not exist for 'IlluminaHumanMethylationEPIC'.") + return + else: + df = probe_dataframe[probe_dataframe['ShortCitation'] + == 'Naeem2014'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if DacaRoszak2015 is True: + if array == 'IlluminaHumanMethylationEPIC': + raise ValueError( + "Citation DacaRoszak2015 does not exist for 'IlluminaHumanMethylationEPIC'.") + return + else: + df = probe_dataframe[probe_dataframe['ShortCitation'] + == 'DacaRoszak2015'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if Zhou2016 is True: + df = probe_dataframe[probe_dataframe['ShortCitation'] + == 'Zhou2016'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + if McCartney2016 is True: + if array == 'IlluminaHumanMethylation450k': + raise ValueError( + "Citation McCartney2016 does not exist for 'IlluminaHumanMethylationEPIC'.") + return + else: + df = probe_dataframe[probe_dataframe['ShortCitation'] + == 'McCartney2016'] + probe_exclusion_list = list( + set(df['Probe'].values)) + probe_exclusion_list + probe_exclusion_list = list(set(probe_exclusion_list + custom_list)) + return probe_exclusion_list diff --git a/methylcheck/reports/bead_array.py b/methylcheck/reports/bead_array.py index a81c3ed..8c2c35d 100644 --- a/methylcheck/reports/bead_array.py +++ b/methylcheck/reports/bead_array.py @@ -103,7 +103,7 @@ class ControlsReporter(): 'Predicted Sex'] def __init__(self, filepath, outfilepath=None, bg_offset=3000, cutoff_adjust=1.0, colorblind=False, - roundoff=2, legacy=False, pval=True, pval_sig=0.05, passing=0.7, project_name=None): + roundoff=2, legacy=False, pval=True, pval_sig=0.05, passing=0.7, project_name=None, array_type=None): self.filepath = filepath # folder with methyprep processed data self.bg_offset = bg_offset self.cut = cutoff_adjust # for adjusting minimum passing per test @@ -113,6 +113,7 @@ def __init__(self, filepath, outfilepath=None, bg_offset=3000, cutoff_adjust=1.0 self.pval_sig = pval_sig # significance level to define a failed probe self.passing = passing # fraction of tests that all need to pass for sample to pass self.project_name = project_name # used to name the QC report, if defined. + self.array_type = array_type # used to determine which manifest is used, specially for epicv2 # if outfilepath is not provided, saves to the same folder where the pickled dataframes are located. if not outfilepath: self.outfilepath = filepath @@ -665,7 +666,7 @@ def process(self): LOGGER.info("Predicting Sex...") try: #print(self.noob_meth.shape, self.noob_unmeth.shape) - sex_df = methylcheck.get_sex((self.noob_meth, self.noob_unmeth), array_type=None, verbose=False, plot=False, on_lambda=False, median_cutoff= -2, include_probe_failure_percent=False) + sex_df = methylcheck.get_sex((self.noob_meth, self.noob_unmeth), array_type=self.array_type, verbose=False, plot=False, on_lambda=False, median_cutoff= -2, include_probe_failure_percent=False) except ValueError as e: if str(e).startswith('Unsupported Illumina array type'): # happens with some mouse array versions, but not fatal to the report @@ -875,7 +876,7 @@ def c(col): # converts to an EXCEL COLUMN name, like A or AE worksheet.set_column(this_box, col_width) col += 1 worksheet.set_column("A:A", 24) # samples - writer.save() + writer.close() def controls_report(*args, **kwargs): @@ -926,7 +927,10 @@ def controls_report(*args, **kwargs): if len(args) == 1: kwargs['filepath'] = args[0] LOGGER.warning(f"Assigned argument 0 `{kwargs['filepath']}` to `filepath` kwarg. This function takes 0 arguments.") - elif len(args) > 1: + elif len(args) == 2: + kwargs['filepath'] = args[0] + kwargs['array_type'] = args[1] + elif len(args) > 2: raise AttributeError("This function takes 0 arguments, but {len(args)} arguments found. Specify the filepath using filepath=.") if 'filepath' not in kwargs: raise FileNotFoundError("No control probes file location specified.") diff --git a/methylcheck/reports/qc_report.py b/methylcheck/reports/qc_report.py index c29208e..f19444b 100644 --- a/methylcheck/reports/qc_report.py +++ b/methylcheck/reports/qc_report.py @@ -1,4 +1,4 @@ -import pandas as pd +(import pandas as pd from pathlib import Path from io import StringIO import re diff --git a/methylcheck/samples/assign.py b/methylcheck/samples/assign.py new file mode 100644 index 0000000..67b04af --- /dev/null +++ b/methylcheck/samples/assign.py @@ -0,0 +1,185 @@ +import pandas as pd +import numpy as np +import seaborn as sns +import matplotlib.pyplot as plt +from collections import Counter +import methylcheck + +## TODO: assign() and plot_assigned_groups() has no unit tests + +def assign(df, two_pass=False): + """Manually and interactively assign each sample to a group, based on beta-value distribution shape. + +how: + sorts samples by the position of their peak intensity in beta dist, then lets the human assign a number to + each. + assumes that peaks that differ by > 0.1 of the 0 to 1 range are different clusters. fills in expected cluster #. + +options: + if two_pass==True: it lets user go through every cluster a second time and split larger clusters further. + sometimes a cluster isn't obviously two groups until it is separated from the larger dataset. + """ + # calculate the highest bin of the sample beta histogram for each sample + def calc_max_bin_of_hist(nparray): + hist_vals, bin_edges = np.histogram(nparray, bins=16) + # want the bin_edge corresponding to the max hist_val + bin_of_max_val = np.where(hist_vals == np.amax(hist_vals)) + return bin_of_max_val[0][0] # it could occur in two bins; if so, return the first bin only + colors = {-1:"xkcd:scarlet", 2:'xkcd:brick red', 1:"xkcd:blue", 2:"xkcd:green", 3:'xkcd:gold', 4:'xkcd:purple', 5:'xkcd:grey blue', + 6:'xkcd:brown', 7:'xkcd:bubblegum', 8:'xkcd:tangerine', 9:'xkcd:poop', 10:"xkcd:baby blue", 11:"xkcd:violet", 12:"xkcd:apple green", + 13:"xkcd:neon pink", 14:"xkcd:deep green", 15:"xkcd:blush", 16:"xkcd:lemon"} + def sample_plot_color_clusters(df, colormap=None, verbose=False, save=False, silent=False, reduce=0.01, ymax=5, figsize=(14,8)): + """ colormap: dict of sample_ids --> group number (some int). Sample_ids must match df columns""" + #qualitative_colors = sns.color_palette("Set3", 10) + #sns.set_color_codes() + # ensure sample ids are unique + if df.shape[0] > df.shape[1]: + df = df.transpose() + # must have samples in rows/index to reindex. you can't "recolumn". + if list(df.index) != list(set(df.index)): + LOGGER.info("Your sample ids contain duplicates.") + # rename these for this plot only + df['ids'] = df.index.map(lambda x: x + '_' + str(int(1000000*np.random.rand()))) + df = df.set_index('ids', drop=True) + df = df.transpose() + + if df.shape[0] < df.shape[1]: + ## ensure probes in rows and samples in cols + df = df.transpose() + if reduce != None and reduce < 1.0: + if not isinstance(reduce, (int, float)): + try: + reduce = float(reduce) + except Exception as e: + raise ValueError(f"{reduce} must be a floating point number between 0 and 1.0") + probes = np.random.choice(df.shape[0], int(reduce*df.shape[0])) + fig, ax = plt.subplots(figsize=figsize) #was (12, 9) + for idx, sample_id in enumerate(df.columns): # samples + if sample_id != 'Name': # probe name + if reduce: + values = df[sample_id].values[probes] + else: + values = df[sample_id].values + if len(values.shape) > 1: + raise ValueError("Your df probaby contains duplicate sample names.") + + this_color = colors[-1] if colormap is None else colors.get(colormap.get(sample_id,-1),'k') + if idx+1 == len(df.columns): + kde_kws = {'linestyle':'--', 'linewidth':2} + else: + kde_kws = {'linewidth':1} + + sns.distplot( + values, hist=False, rug=False, kde=True, + ax=ax, axlabel='beta', color=this_color, kde_kws=kde_kws) + (data_ymin,data_ymax) = ax.get_ylim() + if data_ymax > ymax: + ax.set_ylim(0,ymax) + plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) + plt.show() + + # orient so samples in columns + if len(df.columns) > df.shape[0]: + df = df.transpose() # now more rows(probes) than cols(samples) + + def color_guide(user_defined_groups): + color_names = {k: v.replace('xkcd:','') for k,v in colors.items()} + color_count = Counter(user_defined_groups.values()) + guide = [] + for group,count in color_count.most_common(): + guide.append(f"{group} {color_names[group]}") + return ' | '.join(guide) + + sample_predicted_groups = {} # sample_name --> bin where peak occurs | as a 0-10 number for clustering + for sample_id in df.columns: # columns + #betas[sample] = vectorized_func(meth, unmeth) + sample_predicted_groups[sample_id] = calc_max_bin_of_hist(df[sample_id].values) + print('Predicted sample groups, based on beta-peak position') + prediction_note = " | ".join([f"{k}: {v}" for k,v in Counter(sample_predicted_groups.values()).most_common()]) + print(prediction_note) + # sort by cluster frequency + sample_predicted_groups_counts = Counter(sample_predicted_groups.values()) + sample_predicted_groups = dict(sorted(sample_predicted_groups.items(), key=lambda kv: sample_predicted_groups_counts[kv[1]], reverse=True)) + + # go through each sample, plotting it, and letting user assign to one of the groups + user_defined_groups = {} + colormap = {} + past_samples = [] + for sample_id,predicted_group in sample_predicted_groups.items(): + past_samples.append(sample_id) + sub_sample_df = pd.DataFrame(data = df[past_samples], index = df.index).transpose() + sample_plot_color_clusters(sub_sample_df, colormap=colormap, reduce=0.01) + print(color_guide(user_defined_groups)) + while True: + g = input(f"Group ({predicted_group}): ") + if g in (""," "): + g = predicted_group + try: + g = int(g) + except: + print('Only use numbers between -1 and 16!') + g = input(f"Group ({predicted_group}): ") + if g not in colors: + print('Only use numbers between -1 and 16!') + g = input(f"Group ({predicted_group}): ") + else: + break + user_defined_groups[sample_id] = g + if g == -1: + g = 10 + colormap[sample_id] = g + + # finally, produce a table and plot of each cluster: + clusters = list(set(user_defined_groups.values())) + cluster_samples = {} + for cluster in clusters: + samples = [sample_id for sample_id in df.columns if user_defined_groups.get(sample_id) == cluster] + sub_sample_df = pd.DataFrame(data = df[samples], index = df.index) + print(f"Group ({cluster}) {len(samples)} samples: {samples}") + methylcheck.sample_plot(sub_sample_df) + if two_pass: + yesno = input(f"Rework Group ({cluster}) (y/n)?") + if yesno in ('y','Y','yes'): + past_samples = [] + for sample_id in samples: + past_samples.append(sample_id) + sub_sample_df = pd.DataFrame(data = df[past_samples], index = df.index).transpose() + sample_plot_color_clusters(sub_sample_df, colormap=colormap, reduce=0.01) + print(color_guide(user_defined_groups)) + while True: + g = input(f"Group ({cluster}): ") + if g in (""," "): + g = cluster + try: + g = int(g) + except: + print('Only use numbers between -1 and 16!') + g = input(f"Group ({cluster}): ") + if g not in colors: + print('Only use numbers between -1 and 16!') + g = input(f"Group ({cluster}): ") + else: + break + user_defined_groups[sample_id] = g + if g == -1: + g = 10 + samples = [sample_id for sample_id in df.columns if user_defined_groups.get(sample_id) == cluster] + sub_sample_df = pd.DataFrame(data = df[samples], index = df.index) + print(f"Group ({cluster}) {len(samples)} samples: {samples} REVISED") + methylcheck.sample_plot(sub_sample_df) + cluster_samples[cluster] = samples + return user_defined_groups + +def plot_assigned_groups(df, user_defined_groups): + """ takes the 'sample: group' dictionary and plots each sub-set. + returns a lookup dict of each cluster --> [list of samples].""" + # finally, produce a table and plot of each cluster: + clusters = list(set(user_defined_groups.values())) + cluster_samples = {} + for cluster in clusters: + samples = [sample_id for sample_id in df.columns if user_defined_groups.get(sample_id) == cluster] + sub_sample_df = pd.DataFrame(data = df[samples], index = df.index) + plot_title = f"Group ({cluster}) {len(samples)} samples" + methylcheck.beta_density_plot(sub_sample_df, plot_title=plot_title) + cluster_samples[cluster] = samples + return cluster_samples From 37424e4192fc106702d46f5ee2f3e135b3ded406 Mon Sep 17 00:00:00 2001 From: aregano Date: Tue, 18 Nov 2025 15:58:04 +0100 Subject: [PATCH 2/2] methylcheck integrating EPICv2 data types on pipeline --- methylcheck/reports/qc_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/methylcheck/reports/qc_report.py b/methylcheck/reports/qc_report.py index f19444b..c29208e 100644 --- a/methylcheck/reports/qc_report.py +++ b/methylcheck/reports/qc_report.py @@ -1,4 +1,4 @@ -(import pandas as pd +import pandas as pd from pathlib import Path from io import StringIO import re