@@ -279,6 +279,25 @@ CalPhenoParam <- function(
279279}
280280
281281
282+ # ' Find point to line distance
283+ # '
284+ # ' @param x1,y1,x2,y2 The coordinates of the two points that define the line.
285+ # ' @param x0,y0 The point coordinates to calculate the distance.
286+ # '
287+ # ' @return Distance from the point to the line.
288+ # ' @noRd
289+ CalPointToLineDistance <- function (x1 , y1 , x2 , y2 , x0 , y0 ) {
290+ m <- (y2 - y1 ) / (x2 - x1 )
291+ A <- - m
292+ B <- 1
293+ C <- m * x1 - y1
294+
295+ distance <- abs(A * x0 + B * y0 + C ) / sqrt(A ^ 2 + B ^ 2 )
296+
297+ return (distance )
298+ }
299+
300+
282301# ' Calculate phenometrics using the threshold-based method
283302# '
284303# ' @param p_li A list containing the model parameters.
@@ -295,16 +314,20 @@ CalPhenoParam <- function(
295314# ' The default level is 0.9, generating `90%` credible intervals. The end
296315# ' points of these intervals define the upper and lower bounds for the estimated
297316# ' phenometrics.
317+ # ' @param greendown_aware Default is `FALSE`. If `TRUE`, Senescence will be
318+ # ' retrieved as the end of summer greendown date, and MidGreendown as the
319+ # ' transition point of the first derivative of the autumn EVI2 curve.
298320# '
299- # ' #' @return An "BlspFit" object filled with retrieved phenology and parameters.
321+ # ' @return An "BlspFit" object filled with retrieved phenology and parameters.
300322# '
301323# ' @import data.table
302324# ' @noRd
303325CalPhenoThresh <- function (
304326 p_li , mod ,
305327 years , numYears ,
306328 date_vec , vi_vec , weights_vec ,
307- cred_int_level
329+ cred_int_level ,
330+ greendown_aware = FALSE
308331) {
309332 # Format MCD12Q2-like phenometrics
310333 blsp_fit <- EmptyBlspOutput(
@@ -332,14 +355,7 @@ CalPhenoThresh <- function(
332355 # Spring amp
333356 spring_min <- min(p [1 : peakdate ])
334357 spring_amp <- peak - spring_min
335- # Autumn amp
336- autumn_min <- min(p [peakdate : length(p )])
337- autumn_amp <- peak - autumn_min
338-
339- if (spring_amp < 0.2 | autumn_amp < 0.2 ) {
340- return (rep(NA , 7 ))
341- }
342-
358+
343359 gup <- which(
344360 p [1 : peakdate ] > (spring_amp * 0.15 + min(p [1 : peakdate ]))
345361 )[1 ]
@@ -349,16 +365,60 @@ CalPhenoThresh <- function(
349365 mat <- which(
350366 p [1 : peakdate ] > (spring_amp * 0.90 + min(p [1 : peakdate ]))
351367 )[1 ]
352-
353- sens <- which(
354- p [peakdate : length(p )] < autumn_amp * 0.90 + autumn_min
355- )[1 ] + peakdate
356- midgdown <- which(
357- p [peakdate : length(p )] < autumn_amp * 0.5 + autumn_min
358- )[1 ] + peakdate
359- dorm <- which(
360- p [peakdate : length(p )] < autumn_amp * 0.15 + autumn_min
361- )[1 ] + peakdate
368+
369+ if (isTRUE(greendown_aware )) {
370+ # If greendown aware, autumn amp is calculated as the EVI2
371+ # between the EVI2 of the end of greendown to the EVI2 of
372+ # dormancy
373+
374+ # Draw a line between peak and min, find the point w/ the max
375+ # distance to the line, which is senescence
376+ autumn_p <- p [peakdate : length(p )]
377+ autumn_min <- min(autumn_p )
378+ autumn_amp <- peak - autumn_min
379+ autumn_min_doy <- which(
380+ autumn_p < autumn_amp * 0.1 + autumn_min
381+ )[1 ] + peakdate
382+
383+ dis <- sapply(peakdate + seq_along(autumn_p ) - 1 , function (x0 ) {
384+ CalPointToLineDistance(
385+ peakdate , peak ,
386+ autumn_min_doy , autumn_min ,
387+ x0 , autumn_p [x0 - peakdate + 1 ]
388+ )
389+ })
390+ sens <- peakdate + which(diff(sign(diff(dis ))) == - 2 ) + 2
391+
392+ # Now, the autumn amplitude is from sens to min
393+ autumn_amp <- p [sens ] - autumn_min
394+
395+ # MidGreendown is from the first derivative
396+ midgdown <- which.min(
397+ diff(autumn_p [(sens - peakdate + 1 ): length(autumn_p )])
398+ ) + sens
399+ dorm <- which(
400+ autumn_p [(sens - peakdate + 1 ): length(autumn_p )] <
401+ autumn_amp * 0.15 + autumn_min
402+ )[1 ] + sens
403+ } else {
404+ # Autumn amp
405+ autumn_min <- min(p [peakdate : length(p )])
406+ autumn_amp <- peak - autumn_min
407+
408+ if (spring_amp < 0.2 | autumn_amp < 0.2 ) {
409+ return (rep(NA , 7 ))
410+ }
411+
412+ sens <- which(
413+ p [peakdate : length(p )] < autumn_amp * 0.90 + autumn_min
414+ )[1 ] + peakdate
415+ midgdown <- which(
416+ p [peakdate : length(p )] < autumn_amp * 0.5 + autumn_min
417+ )[1 ] + peakdate
418+ dorm <- which(
419+ p [peakdate : length(p )] < autumn_amp * 0.15 + autumn_min
420+ )[1 ] + peakdate
421+ }
362422
363423 return (c(gup , midgup , mat , peakdate , sens , midgdown , dorm ))
364424 })
0 commit comments