phc-ingestion 0.10.1__py3-none-any.whl → 0.10.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,26 +1,53 @@
1
1
  import os
2
2
 
3
- from ingestion.nebula.util.json import process_nebula_json
4
- from ingestion.nebula.util.vcf import process_nebula_vcf
3
+ from ingestion.vcf_standardization.standardize import standardize_vcf
5
4
  from lifeomic_logging import scoped_logger
6
5
 
7
6
 
8
- def process(infile, outpath, file_name, source_file_id):
7
+ def process(vcf_file, out_path, file_name, source_file_id):
9
8
 
10
9
  with scoped_logger(__name__) as log:
11
- log.info(f"Beginning Nebula ingestion for file: {file_name}")
12
- os.makedirs(f"{outpath}", exist_ok=True)
13
- result, file_genome_references, json_data = process_nebula_json(
14
- infile, outpath, file_name, source_file_id, log
10
+ log.info(
11
+ f"Beginning Nebula ingestion for vcf_file: {vcf_file}, file_name: {file_name}, out_path: {out_path}, source_file_id: {source_file_id}"
15
12
  )
16
- somatic_vcf_line_count = process_nebula_vcf(
17
- result["somatic_vcf"], json_data, outpath, file_name, log
13
+
14
+ manifest = {}
15
+ case_id = file_name
16
+ base_vcf_file = os.path.basename(vcf_file)
17
+ vcf_out = base_vcf_file.replace(".vcf", ".modified.vcf")
18
+ vcf_final = base_vcf_file.replace(".vcf", ".modified.nrm.filtered.vcf")
19
+ if not vcf_final.endswith(".gz"):
20
+ vcf_final = vcf_final + ".gz"
21
+
22
+ # All Nebula VCF ingestions are germline, so ensure the
23
+ # sample name is prefixed with "germline_". This matches
24
+ # the downstream logic in genomic-manifest
25
+ sample_name = f"germline_{case_id}"
26
+ vcf_line_count = standardize_vcf(
27
+ vcf_file, vcf_out, out_path, sample_name, log, compression=True
18
28
  )
29
+
30
+ # Add to manifest
31
+ manifest["testType"] = "WGS-30x"
32
+ manifest["reportID"] = case_id
33
+ manifest["sourceFileId"] = source_file_id
34
+ manifest["resources"] = [{"fileName": f".lifeomic/vcf-ingest/{case_id}/{base_vcf_file}"}]
35
+ manifest["files"] = [
36
+ {
37
+ "fileName": f".lifeomic/vcf-ingest/{case_id}/{vcf_final}",
38
+ "sequenceType": "germline",
39
+ "type": "shortVariant",
40
+ }
41
+ ]
42
+
43
+ # Hard-code genome reference for Nebula VCFs
44
+ genome_reference = "GRCh38"
45
+
19
46
  case_metadata = {
20
- "somatic_vcf_line_count": somatic_vcf_line_count,
47
+ "test_type": manifest["testType"],
48
+ "vcf_line_count": vcf_line_count,
49
+ "germline_case_id": manifest["reportID"],
50
+ "germline_genome_reference": genome_reference,
21
51
  }
22
52
 
23
- if file_genome_references != {}:
24
- case_metadata.update(file_genome_references)
25
-
26
- return case_metadata
53
+ return case_metadata, manifest
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: phc-ingestion
3
- Version: 0.10.1
3
+ Version: 0.10.3
4
4
  Summary: Functions for LifeOmic PHC genomic ingestions
5
5
  License: MIT
6
6
  Author-email: LifeOmic Development <development@lifeomic.com>
@@ -27,9 +27,7 @@ ingestion/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
27
27
  ingestion/generic/process.py,sha256=ZaVnZ_gx9faDUsuresI1A0oCegTa-dPQT7DBFMeZGyY,1777
28
28
  ingestion/generic/utils.py,sha256=1MEIru7uq38IjUdL8lcHqDH0oTki9uWrz1f2e-pmRoU,2814
29
29
  ingestion/nebula/__init__.py,sha256=VauK-rup_N8ZXVohx3HYqHX_PE_WoPyMUhdv2R7al4o,45
30
- ingestion/nebula/process.py,sha256=r4zKxVRPzl0pI-OInGIy8V_Z2K4UW_iIf9ggUvGZZlk,893
31
- ingestion/nebula/util/json.py,sha256=ChThuJjF7o4xMQ4gkX7s2w9wgZ5_k528XxiSI3-gOCU,2230
32
- ingestion/nebula/util/vcf.py,sha256=83JWG6ndPxHYZNXVj6-Gon9AY9JnGeR1JMivUQoSHjM,3311
30
+ ingestion/nebula/process.py,sha256=x0nip0-99iYIOMItaaduAsx-b0EXStdwm50EtFNdJLo,1942
33
31
  ingestion/nextgen/__init__.py,sha256=7LQ-h_Bvc5P1QcHMdzsqi1Qm4fTJn04-ozar2ty9wSc,59
34
32
  ingestion/nextgen/process.py,sha256=5Z0RfclwTAYZruGDiLPutjPCYFh1DJpoWY9dnttghT4,3993
35
33
  ingestion/nextgen/util/alteration_table.py,sha256=JTWBL1Fqj_pGsH5vwuVEnCUJle2wOBk6VYImHYCF9vg,6129
@@ -58,6 +56,6 @@ ingestion/vcf_standardization/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
58
56
  ingestion/vcf_standardization/util/af_helpers.py,sha256=dpTzoeIQVeBRt0ETF3a9rp5ojZqznHg4x_hCZ8OPcOg,1061
59
57
  ingestion/vcf_standardization/util/dp_helpers.py,sha256=Nq8oLOLObu4_pv16qwwgpALRlUoJVCULrd9cFOD-eoI,823
60
58
  ingestion/vcf_standardization/util/read_write.py,sha256=x3Pf6Dq8tmolblbCS5CrNmrcHS3FGfqBSFpFgvFGC4g,2526
61
- phc_ingestion-0.10.1.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
62
- phc_ingestion-0.10.1.dist-info/METADATA,sha256=TKRNABWds66BCmH2r2QoLxqcqNEZzUsom92zWJdx2aw,573
63
- phc_ingestion-0.10.1.dist-info/RECORD,,
59
+ phc_ingestion-0.10.3.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
60
+ phc_ingestion-0.10.3.dist-info/METADATA,sha256=BbHHrV-H3nYEQ1XGyYlonO2KRtUWkrGRgSTbtrlsnC4,573
61
+ phc_ingestion-0.10.3.dist-info/RECORD,,
@@ -1,72 +0,0 @@
1
- import glob
2
- import gzip
3
- import os
4
- import shutil
5
-
6
- from ingestion.shared_util.tar import unpack
7
- from ingestion.nebula.util.vcf import extract_sv
8
- from ingestion.shared_util.ga4gh import create_yaml
9
- from logging import Logger
10
-
11
-
12
- def handle_tsv(file: str, file_list: list[str]) -> dict[str, str]:
13
- multiple_tsv = len([file for file in file_list if file.endswith("tsv")]) > 1
14
-
15
- if not multiple_tsv or "Transformed" in file:
16
- return {
17
- "tsv": file,
18
- }
19
- return {}
20
-
21
-
22
- def process_nebula_json(
23
- infile: str, outpath: str, file_name: str, source_file_id: str, log: Logger
24
- ):
25
- # Unpack tarball and go into the new directory
26
- unpack(infile, outpath)
27
- os.chdir(outpath)
28
-
29
- file_list = glob.glob("*")
30
- files: dict[str, str] = {}
31
-
32
- for file in file_list:
33
- extension = ".".join(file.split(".")[1:])
34
- if file.endswith("vcf"):
35
- files["somatic.vcf"] = file
36
- else:
37
- # There should only be the vcf file
38
- files[extension] = file
39
-
40
- log.info(f"Files in tarball input: {file_list}")
41
-
42
- somatic_filename = None
43
- data = {}
44
- metadata = {}
45
-
46
- # Sometimes they don't come in gzipped
47
- for key in files.keys():
48
- if "somatic.vcf" in key:
49
- somatic_filename = files["somatic.vcf"].replace(".vcf", ".somatic.vcf") + ".gz"
50
- with open(files["somatic.vcf"], "rb") as f_in:
51
- with gzip.open(somatic_filename, "wb") as f_out:
52
- shutil.copyfileobj(f_in, f_out)
53
-
54
- vcf_results = extract_sv(file_name, bool(somatic_filename), False, False)
55
-
56
- # We might not have any of these files but we need an empty json object here.
57
- file_genome_references = {}
58
- if vcf_results:
59
- metadata["files"] = metadata["files"] + vcf_results
60
- for vcf in vcf_results:
61
- seq_type = vcf.get("sequenceType")
62
- file_genome_references[f"{seq_type}_genome_reference"] = vcf["reference"]
63
-
64
- create_yaml(metadata, file_name)
65
-
66
- # Return VCF files for immediate processing, and JSON data for adding vendsig
67
- result = {}
68
-
69
- if somatic_filename is not None:
70
- result["somatic_vcf"] = f"{outpath}/{somatic_filename}"
71
-
72
- return (result, file_genome_references, data)
@@ -1,100 +0,0 @@
1
- import datetime
2
- import gzip
3
-
4
- from logging import Logger
5
-
6
- from ingestion.vcf_standardization.standardize import standardize_vcf
7
-
8
-
9
- def create_empty_vcf_zip(prefix):
10
- vcf_gzip_path = f"{prefix}.modified.somatic.vcf.gz"
11
- content = (
12
- """##fileformat=VCFv4.1
13
- ##filedate="""
14
- + datetime.datetime.now().isoformat()
15
- + """
16
- ##FILTER=<ID=PASS,Description="All filters passed">
17
- ##FILTER=<ID=R8,Description="IndelRepeatLength is greater than 8">
18
- ##FILTER=<ID=R8.1,Description="IndelRepeatLength of a monomer is greater than 8">
19
- ##FILTER=<ID=R8.2,Description="IndelRepeatLength of a dimer is greater than 8">
20
- ##FILTER=<ID=sb,Description="Variant strand bias high">
21
- ##FILTER=<ID=sb.s,Description="Variant strand bias significantly high (only for SNV)">
22
- ##FILTER=<ID=rs,Description="Variant with rs (dbSNP) number in a non-core gene">
23
- ##FILTER=<ID=FP,Description="Possibly false positives due to high similarity to off-target regions">
24
- ##FILTER=<ID=NC,Description="Noncoding INDELs on non-core genes">
25
- ##FILTER=<ID=lowDP,Description="low depth variant">
26
- ##FILTER=<ID=Benign,Description="Benign variant">
27
- ##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
28
- ##FORMAT=<ID=AF,Number=1,Type=String,Description="Variant Allele Frequency">
29
- #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT """
30
- + prefix
31
- + """
32
- """
33
- )
34
-
35
- with gzip.open(vcf_gzip_path, "wb") as f:
36
- f.write(content.encode("utf-8"))
37
-
38
-
39
- # This is done in next step, we are just adding to yaml
40
- def extract_sv(prefix, include_somatic: bool):
41
- vcfs = []
42
-
43
- # Hard-code genome reference for Nebula VCFs
44
- genome_reference = "GRCh38"
45
-
46
- if include_somatic:
47
- vcfs.append(
48
- {
49
- "fileName": f".lifeomic/nebula/{prefix}/{prefix}.modified.somatic.nrm.filtered.vcf.gz",
50
- "sequenceType": "somatic",
51
- "type": "shortVariant", # todo: Is this always going to be shortVariant?
52
- "reference": genome_reference,
53
- }
54
- )
55
-
56
- return vcfs
57
-
58
-
59
- def get_vendsig_dict(json_data, log: Logger):
60
- # Return a dicitionary of {'chr:star_pos:ref:alt' : 'vendsig'}
61
- vendsig_dict = {"vendor": "nebula"}
62
-
63
- return vendsig_dict
64
-
65
-
66
- def map_vendsig(ci: str) -> str:
67
- if ci in ["Pathogenic Variant", "Pathogenic"]:
68
- return "Pathogenic"
69
- elif ci in ["Likely Pathogenic Variant", "Likely Pathogenic"]:
70
- return "Likely pathogenic"
71
- elif ci in ["Benign Variant", "Benign"]:
72
- return "Benign"
73
- elif ci in ["Likely Benign Variant", "Likely Benign"]:
74
- return "Likely benign"
75
- elif ci in ["Variant of Uncertain Significance", "VUS"]:
76
- return "Uncertain significance"
77
- else:
78
- return "Unknown"
79
-
80
-
81
- def process_nebula_vcf(infile, json_data, outpath, file_name, log: Logger):
82
- line_count = 0
83
- vendsig_dict = {"vendor": "nebula"}
84
-
85
- outfile = f"{file_name}.modified.somatic.vcf"
86
- sample_name = file_name
87
- # Read in a dictionary of variants with VENDSIG from the JSON file for somatic only
88
- vendsig_dict = get_vendsig_dict(json_data, log)
89
-
90
- line_count = standardize_vcf(
91
- infile=infile,
92
- outfile=outfile,
93
- out_path=outpath,
94
- case_id=sample_name,
95
- log=log,
96
- vendsig_dict=vendsig_dict,
97
- compression=True,
98
- )
99
-
100
- return line_count