Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: BIGpopA
Title: Pedigree Validation Genetic Composition of Diploids & Polyploids
Version: 2.1.0
Version: 2.2.0
Authors@R: c(person(given='Josue',
family='Chinchilla-Vargas',
email='josue.chinchilla@ufl.edu',
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Generated by roxygen2: do not edit by hand

export(allele_freq_poly)
export(assign_composition_line)
export(check_ped)
export(find_parentage)
export(ped_to_dosage)
Expand Down
15 changes: 15 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# BIGpopA 2.2.0
- `validate_pedigree()` and `find_parentage()`: `founders_file` now also accepts a character vector of ids or a data.frame (first column), in addition to a file path. All inputs can now be supplied from memory.
- `validate_pedigree()`: removed the suggested replacement parents (`best_male_candidate`, `best_male_candidate_error_pct`, `best_female_candidate`, `best_female_candidate_error_pct`) from `full_results` and the per-status tables. Use `find_parentage(method = "fill_pedigree")` on `corrected_pedigree` to fill in missing parents.
- `validate_pedigree()`: new `marker_summary` element in the returned list gives, for every marker, the number of trios tested, the number with a Mendelian mismatch and the mismatch percentage, sorted worst first. It covers all trios with both parents known and genotyped, and helps spot markers (e.g. paralogous or miscalled) that cause many failures.
- `find_parentage()`: new `method = "fill_pedigree"` fills in missing parents of a pedigree. `progeny_file` must have `id`, `male_parent` and `female_parent` columns (e.g. `validate_pedigree()$corrected_pedigree`); parents coded `0`/`NA`/empty are unknown. A known male searches only females, a known female only males, and rows with both unknown get the full pair search (skip founders with the new `founders_file`). Rows with both parents known are skipped. Results gain `search_mode` and `known_parent_error_pct`, and a known parent without genotypes gets `status = "known_parent_no_genotype"`.
- `find_parentage()`: new `top_n` argument reports the best `top_n` candidates per progeny, ranked by Mendelian error (ties broken by markers tested). Rank 1 stays in the base columns and ranks 2 to `top_n` are added as suffix columns (`male_parent_2`, `female_parent_2`, `mendelian_error_pct_2`, `markers_tested_2` for `best_pair`; `best_match_2` and the same error/marker columns for the other methods). The default `top_n = 1` keeps the previous output, including `show_ties`.
- `find_parentage()`: new `tied_candidates` column gives the number of candidates (pairs for `best_pair`) that share each progeny's lowest error. Values above 1 mean the best assignment is ambiguous, including for the single-parent methods, which previously did not report ties.
- `validate_pedigree()`: fixed `corrected_pedigree` for `low_markers_remove_female_parent`, which also set the male parent to `0`. Low-marker trios now remove only the identified parent(s).
- New `assign_composition_line()` turns the output of `solve_composition_poly()` into the composition table used by Familia: percentages per reference population and a `Predicted line`, labelled `Undetermined` when the highest proportion is below `assign_threshold` (default 50). `solve_composition_poly()` is unchanged.
- `validate_pedigree()`: new `marker_trio_table = FALSE` argument. When TRUE the result includes `marker_trio_table`, a marker-by-trio table with one column per trio (`id_male_parent_female_parent`) giving each marker's status: `match`, `mismatch_male`, `mismatch_female`, `mismatch_both`, `mismatch_combination` (each parent compatible alone but not the pair), `untestable` (odd ploidy) or `missing_*` named after the individuals without a call (e.g. `missing_male`, `missing_male_female`, `missing_progeny`).

# BIGpopA 2.1.1
- `validate_pedigree()`: a trio that fails the Mendelian error threshold while neither parent fails the single-parent homozygous check now gets `recommended_correction = "unresolved"` instead of `"keep_both"`. This happens, for example, with a recorded self whose offspring carries alleles the parent lacks: the pedigree is wrong, but the faulty parent cannot be identified. These trios are left unchanged in `corrected_pedigree` for manual review.
- `validate_pedigree()` plot: bars are coloured by trio error first, so no trio above the threshold is shown as Pass. Unresolved trios are shown in grey ("Fail - Parents Unresolved"), and the legend wraps onto two rows so all labels are visible.

# BIGpopA 2.1.0
- New `vcf_to_dosage()` converts a VCF (`.vcf` / `.vcf.gz`) or `vcfR` object into allele-B dosages for any ploidy, as an `id` + markers table or an individuals x markers matrix.
- New `ped_to_dosage()` converts a PLINK `.ped` file (diploid) into allele dosages. A `.map` file is optional and only supplies marker names. The counted allele is the alphabetically/numerically last allele at each marker, or can be supplied to code a second file like a first one.
Expand Down
Binary file removed R/.DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion R/allele_freq_poly.R
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ allele_freq_poly <- function(geno, populations, ploidy = 2) {

# Accept text files, VCFs, PLINK .ped, and in-memory tables (individuals x SNPs)
geno <- .read_genotypes(geno, ploidy = ploidy, format = "matrix")
counted <- base::attr(geno, "counted_allele") # set only for .ped input
counted <- attr(geno, "counted_allele") # set only for .ped input

# Initialize returned df
X <- matrix(NA, nrow = ncol(geno), ncol = length(populations))
Expand Down
52 changes: 52 additions & 0 deletions R/assign_composition_line.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#' Assign Each Sample to a Reference Line
#'
#' Builds the composition table shown in the Familia BreedTools tab from the
#' output of [solve_composition_poly()]: one row per sample with the estimated
#' percentage of each reference population and the predicted line. A sample is
#' assigned to the population with its highest proportion only if that
#' proportion is at least `assign_threshold`; otherwise it is labelled
#' `"Undetermined"`.
#'
#' @param composition Matrix or data.frame returned by
#' [solve_composition_poly()]: samples in rows, reference populations in
#' columns (proportions summing to 1). An `R2` column, if present, is dropped.
#' @param assign_threshold Numeric between 0 and 100. Minimum percentage the
#' highest population must reach for the sample to be assigned to it
#' (default: 50). Use 0 to always assign the highest population.
#'
#' @return A data.frame with an `ID` column, one column per reference
#' population holding the estimated percentage (0 to 100, rounded to one
#' decimal) and a `Predicted line` column. Ties between populations go to the
#' first column.
#'
#' @examples
#' comp <- rbind(
#' Sample01 = c(Duroc = 0.998, Hampshire = 0.000, Landrace = 0.002, R2 = 0.991),
#' Sample02 = c(Duroc = 0.529, Hampshire = 0.471, Landrace = 0.000, R2 = 0.973),
#' Sample03 = c(Duroc = 0.340, Hampshire = 0.330, Landrace = 0.330, R2 = 0.952)
#' )
#' assign_composition_line(comp)
#' assign_composition_line(comp, assign_threshold = 0)
#'
#' @export
assign_composition_line <- function(composition, assign_threshold = 50) {
if (!is.numeric(assign_threshold) || length(assign_threshold) != 1 ||
is.na(assign_threshold) || assign_threshold < 0 || assign_threshold > 100)
stop("assign_threshold must be a single number between 0 and 100.")

comp <- as.data.frame(composition, check.names = FALSE)
comp <- comp[, !colnames(comp) %in% "R2", drop = FALSE]
if (ncol(comp) == 0) stop("composition has no population columns.")
comp[] <- lapply(comp, as.numeric)
mat <- as.matrix(comp)

top_value <- apply(mat, 1, max, na.rm = TRUE)
top_line <- colnames(mat)[max.col(mat, ties.method = "first")]
predicted <- ifelse(top_value * 100 >= assign_threshold, top_line, "Undetermined")

out <- data.frame(ID = rownames(mat), round(mat * 100, 1),
check.names = FALSE, stringsAsFactors = FALSE,
row.names = NULL)
out[["Predicted line"]] <- predicted
out
}
Loading
Loading