(args: argparse.Namespace)
| 38 | |
| 39 | |
| 40 | def validate_inputs(args: argparse.Namespace) -> tuple[dict[str, Any], list[dict[str, str]]]: |
| 41 | sample_sheet = args.sample_sheet.expanduser().resolve() |
| 42 | errors: list[str] = [] |
| 43 | warnings: list[str] = [] |
| 44 | rows: list[dict[str, str]] = [] |
| 45 | columns: list[str] = [] |
| 46 | samples: list[dict[str, str]] = [] |
| 47 | if not sample_sheet.exists(): |
| 48 | errors.append(f"sample sheet does not exist: {sample_sheet}") |
| 49 | else: |
| 50 | rows, columns = read_table(sample_sheet) |
| 51 | if not args.primer_forward or not args.primer_reverse: |
| 52 | errors.append( |
| 53 | "both --primer-forward and --primer-reverse are required for full amplicon backend execution" |
| 54 | ) |
| 55 | if args.taxonomy_classifier: |
| 56 | classifier = args.taxonomy_classifier.expanduser().resolve() |
| 57 | if not classifier.exists(): |
| 58 | errors.append(f"taxonomy classifier/database does not exist: {classifier}") |
| 59 | else: |
| 60 | warnings.append( |
| 61 | "no --taxonomy-classifier was provided; ASV generation can be planned but taxonomy assignment is blocked" |
| 62 | ) |
| 63 | if args.metadata: |
| 64 | metadata = args.metadata.expanduser().resolve() |
| 65 | if not metadata.exists(): |
| 66 | errors.append(f"metadata file does not exist: {metadata}") |
| 67 | else: |
| 68 | warnings.append( |
| 69 | "no sample metadata was provided; PERMANOVA and metadata-colored diversity plots will be limited" |
| 70 | ) |
| 71 | for row_index, row in enumerate(rows, start=2): |
| 72 | sample = normalize_sample_name( |
| 73 | first_present(row, ["sample", "sample_id", "sampleID"]), f"row_{row_index}" |
| 74 | ) |
| 75 | r1 = resolve_path( |
| 76 | first_present(row, ["r1", "fastq_1", "forwardReads", "read1"]), sample_sheet.parent |
| 77 | ) |
| 78 | r2 = resolve_path( |
| 79 | first_present(row, ["r2", "fastq_2", "reverseReads", "read2"]), sample_sheet.parent |
| 80 | ) |
| 81 | if not r1: |
| 82 | errors.append(f"row {row_index}: r1/fastq_1/forwardReads is required") |
| 83 | continue |
| 84 | if not r1.exists(): |
| 85 | errors.append(f"row {row_index}: R1 FASTQ does not exist: {r1}") |
| 86 | if r2 and not r2.exists(): |
| 87 | errors.append(f"row {row_index}: R2 FASTQ does not exist: {r2}") |
| 88 | samples.append( |
| 89 | { |
| 90 | "sample": sample, |
| 91 | "r1": str(r1), |
| 92 | "r2": str(r2) if r2 else "", |
| 93 | "row_index": str(row_index), |
| 94 | } |
| 95 | ) |
| 96 | if not samples: |
| 97 | errors.append("no usable amplicon samples found") |
no test coverage detected