Project: s41467-024-51011-7 | Function: mapTransToPCA (r)

system: You are an expert R programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow R best practices and maintain consistent code style.
Return **only** the complete R function code.

user: Complete this R function:

**DESCRIPTION:** Maps transition points to PCA coordinates for cell cycle phase assignment. Assigns temporal phase labels based on position relative to detected transition boundaries.

**KEY TERMS:** {
  "x": "PCA coordinate",
  "y": "transition boundaries",
  "z": "phase assignments",
  "p": "phase labels"
}

**CONTEXT CODE:**   peak.locs <- mu.scale %>% dplyr::select(GeneID, peak.ord) %>% distinct()
  spline.fit.peaks <- smooth.spline(x = 1:nrow(peak.locs), y = sort(peak.locs$peak.ord), lambda = lam)
  
  s.0 <- predict(spline.fit.peaks, seq(1, nrow(peak.locs), by = 0.1), deriv=0)
  s.1 <- predict(spline.fit.peaks, seq(1, nrow(peak.locs), by = 0.1), deriv=1)
  s.2 <- predict(spline.fit.peaks, seq(1, nrow(peak.locs), by = 0.1), deriv=2)
  
  spline.fit.peaks.smooth <- data.frame(x = seq(1, nrow(peak.locs), by = 0.1), 
                                        s0=s.0$y, s1=s.1$y, s2 = s.2$y)
  
  ## Get locations of peaks and valies
  max.loc <- getCurvePeakLoc(spline.fit.peaks.smooth$x, spline.fit.peaks.smooth$s1, prob = prob)
  min.loc <- getCurvePeakLoc(spline.fit.peaks.smooth$x, -spline.fit.peaks.smooth$s1, prob = prob)
  
  transition.points <- predict(spline.fit.peaks, sort(c(max.loc, min.loc)))
  
  L <- list(peak.locs = peak.locs, spline.fit.peaks.smooth = spline.fit.peaks.smooth, 
            transition.points = transition.points)
  
  return(L)
  
}



## ATAC transition points
L.trans.atac <- tans.points(sc.atac.mu.scale, lam = 0.005, prob = 0.0)

## set transition to be between 0 and 6 hrs
L.trans.atac$transition.points$y[L.trans.atac$transition.points$y < 0] <- 0
L.trans.atac$transition.points$y[L.trans.atac$transition.points$y > 6] <- 6


## Removing noisy transition 
L.trans.atac$transition.points$y <- L.trans.atac$transition.points$y[-c(3,5,7)]
L.trans.atac$transition.points$x <- L.trans.atac$transition.points$x[-c(3,5,7)]


## RNA transition points
L.trans.rna <- tans.points(sc.rna.mu.scale, lam = 0.005, prob = 0.0)
L.trans.rna$transition.points$y[L.trans.rna$transition.points$y < 0] <- 0
L.trans.rna$transition.points$y[L.trans.rna$transition.points$y > 6] <- 6

## Removing nosy transition 
L.trans.rna$transition.points$y <- L.trans.rna$transition.points$y[-2]
L.trans.rna$transition.points$x <- L.trans.rna$transition.points$x[-2]


## Add transition time  to the meta data (according to transition time and cell cycle phase)

mapTransToPCA <- function(x, y, p){
  stop("Function implementation has been masked")
  # Validate inputs
  if (!is.numeric(x) || !is.numeric(y)) {
    stop("x and y must be numeric vectors.")
  }
  if (length(x) != length(y)) {
    stop("x and y must have the same length.")
  }
  if (!(is.data.frame(p) || is.matrix(p))) {
    stop("p must be a data.frame or matrix of coordinates.")
  }

  p <- as.data.frame(p)
  # select first two numeric columns as PCA coordinates (flexible to various input formats)
  num_cols <- vapply(p, is.numeric, logical(1))
  if (sum(num_cols) < 2) {
    stop("p must contain at least two numeric columns for coordinates.")
  }
  coord_cols <- which(num_cols)[1:2]
  colnames(p)[coord_cols] <- c("PC1", "PC2")

  n <- nrow(p)
  # Ensure x positions are within the index range [1, n]
  # We'll allow fractional x for interpolation, but clamp to [1, n]
  xi <- pmin(pmax(x, 1), n)

  # Integer and fractional parts
  i1 <- floor(xi)
  i2 <- ceiling(xi)
  # If floor and ceiling are same (xi integer), weight will be 0
  w <- xi - i1

  # Handle edge case when i1==0 due to xi<1 (clamped) or i2>n (clamped)
  i1[i1 < 1] <- 1
  i2[i2 < 1] <- 1
  i1[i1 > n] <- n
  i2[i2 > n] <- n

  pc1_vals <- (1 - w) * p$PC1[i1] + w * p$PC1[i2]
  pc2_vals <- (1 - w) * p$PC2[i1] + w * p$PC2[i2]

  result <- data.frame(x = x, y = y, PC1 = pc1_vals, PC2 = pc2_vals, 
                       row.names = NULL, stringsAsFactors = FALSE)
  return(result)
}


## 0 and 6 are the start of the cell cycle 

L.trans.rna$transition.points$y <- c(0, L.trans.rna$transition.points$y[-4])

t.atac.over.rna <- mapTransToPCA(rna_sub@meta.data$pt.shifted.scaled, L.trans.atac$transition.points$y, rna_sub@meta.data$phase)
rna_sub@meta.data$transition.atac <- factor(t.atac.over.rna, levels = sort(unique(t.atac.over.rna)))

t.rna.over.rna <- mapTransToPCA(rna_sub@meta.data$pt.shifted.scaled, L.trans.rna$transition.points$y, rna_sub@meta.data$phase)
rna_sub@meta.data$transition.rna <- factor(t.rna.over.rna, levels = sort(unique(t.rna.over.rna)))

t.atac.over.atac <- mapTransToPCA(atac_sub@meta.data$pt.shifted.scaled, L.trans.atac$transition.points$y, atac_sub@meta.data$phase)
atac_sub@meta.data$transition.atac <- factor(t.atac.over.atac, levels = sort(unique(t.atac.over.atac)))







Complete the function implementation replacing "stop("Not implemented")".