#' @title
#' Mean and standard deviation of dissimilarities between pairs of randomly altered sequences.
#'
#' @description
#' For each pair of sequences, returns the mean and standard deviation (MCSE) of the dissimilarities between all combinations of MC-replicated sequences, where sequences are replicated with random timing changes.
#'
#' @details
#' Let \eqn{B_x} be the set of \code{R} sequences derived from a sequence \eqn{x} by randomly altering the timing of the transitions (state changes) in \eqn{x}. The MC standard error of the dissimilarity \eqn{d(x,y)} between two sequences \eqn{x} and \eqn{y} is the empirical standard deviation of the dissimilarities between the sequences of \eqn{B_x} and those of \eqn{B_y}. There are \code{R^2} such MC-simulated dissimilarities for each pair of observed sequences.
#'
#' By default, MC standard errors are computed for distances between unique sequences and results are then expanded to all sequences. In addition, results for pairs of identical sequences are expanded to all such pairs in \code{seqdata}. With \code{unique=FALSE}, the computation is redone for each identical pairs and, therefore, results can vary across such identical pairs. Setting \code{unique=TRUE} (default) can save much computation time when same sequences occur multiple times.
#'
#' A progress bar is displayed when \code{verbose=TRUE}. However, the progress bar works only with option \code{snow=TRUE} for parallel computing.
#'
#' \code{seqdistMCSE} is much slower than \code{\link{MCseqdistSE}}, which considers only distances within sets of replicated sequences (generated with \code{\link{MCseqReplicate}}) instead of all combinations of replicated sequences.
#'
#' @param seqdata A state sequence \code{stslist} object as generated by \code{\link[TraMineR]{seqdef}}.
#' @param method Character string. Dissimilarity measure to compute distances. Default is \code{"LCS"}. See \code{\link[TraMineR]{seqdist}}.
#' @param J Integer or vector of positive numbers. If an integer, maximal timing error (number of unit periods around first state of new spell. Default is \code{J=1}.) If a vector, weights of the timing errors \code{k = -K, -(K-1), ..., K-1, K}, where \code{2K + 1} is the length of \code{J}. The vector length must be odd.
#' @param R Integer. Number of random replications of each sequence. Default is \code{R=50}.
#' @param replic Character string. One of \code{"by.pair"} (default) and \code{"once"}. When \code{"by.pair"} a fresh set of replications of the sequences is generated for each distance. When "once", replications of each sequence are generated once and reused for each distance involving the sequence.
#' @param jfixed Logical. Should same error j be applied to all transitions in a sequence? Default is \code{FALSE}.
#' @param kchanges Integer, string, or \code{NULL}. If integer, number of transitions whose time can potentially be altered. If \code{"rand"}, the number of potential changes is randomly selected for each sequence. If \code{NULL} (default), all transitions can potentially be altered.
#' @param verbose Logical. Should waiting and timing messages be printed?
#' @param core Integer. Number of cores to use for parallel computation.
#' @param unique Logical. Should simulations for distances between identical pairs of sequences be run only once? Default is \code{TRUE}.
#' @param model String. Time alteration model. One of \code{"keep.dss"} (default), \code{"indep"} (suppress spells erased by move of transition), and \code{"relative"} (keep time until next transitions unchanged).
#' @param ratios Logical. Should standardized ratios and the standard error of mean simulated distances be returned? Default is \code{TRUE}.
#' @param snow Logical. If \code{TRUE}, \code{doSNOW} is used for parallel computing, otherwise \code{doParallel} is used.
#' @param ... Further arguments passed to \code{\link[TraMineR]{seqdist}}.
#'
#' @return A list of class \code{distMC} with for each pairwise distance: \cr - \code{MC.mean} (\code{dist} object) MC means of distances between MC-replicated sequences,\cr - \code{MC.se} (\code{dist} object) MC standard deviations of distances between MC-replicated sequences, \cr - \code{args.dist} list of arguments  passed to \code{seqdist}, \cr - \code{diss.o} (\code{dist} object) observed distances between sequences, \cr and when \code{ratios = TRUE}: \cr - \code{diss.z} (\code{dist} object) ratios \code{diss.u/MC.se}, \cr - \code{MC.mean.z} (\code{dist} object) ratios  \code{MC.mean/mean.se}, \cr - \code{mean.se} (\code{dist} object) standard errors of \code{MC.mean}.
#'
#' @references
#' Liao, T.F. and G. Ritschard (2023). Evaluating uncertainty of dissimilarity measures between state sequences.
#' Manuscript in preparation.
#'
#'
#' @author Gilbert Ritschard
#'
#' @export
#'
## @exportS3Method print distMC
## @exportS3Method summary distMC
#'
#' @import TraMineR
#' @importFrom WeightedCluster wcAggregateCases
#' @importFrom doParallel registerDoParallel
#' @importFrom parallel makePSOCKcluster stopCluster makeCluster detectCores
#' @importFrom doSNOW registerDoSNOW
#' @importFrom foreach foreach %dopar% %do% %:%
#' @importFrom stats as.dist runif sd
#' @importFrom utils packageVersion txtProgressBar setTxtProgressBar
#' @importFrom iterators icount
#'
#' @seealso \code{\link{MCseqdistSE}}, \code{\link{print.distMC}}, \code{\link{summary.distMC}}, and \code{\link{MCratios}}
#'
#' @examples
#' ## mini test data, 6 sequences of length 4, 4 unique sequences
#' exdata <- read.table(text="
#'                 a a b b
#'                 a a b b
#'                 b b a a
#'                 a c c b
#'                 b b a c
#'                 b b a c
#'                 ")
#' weights=rep(1, nrow(exdata))
#' s.exdata <- seqdef(exdata, weights = weights, id=paste("id",1:nrow(exdata), sep=""))
#'
#' ## Here we call function seqdistMCSE
#' MCd <- seqdistMCSE(s.exdata, method="LCS", J=1, R=50, core=1, verbose=TRUE)
#'
#' ## Results for distances between first sequences
#' MCd
#'
#' ## Summary statistics refer to all distances between original sequences
#' summary(MCd)


seqdistMCSE <- function(seqdata, method="LCS", J=1, R=50, replic="by.pair", verbose=TRUE, core=1, unique=TRUE, model="keep.dss", jfixed=FALSE, kchanges=NULL, ratios=TRUE, snow=TRUE, ...){

  Tver <- packageVersion("TraMineR")
  if (! Tver > "2.2.8")
    cat("!!! You have TraMineR v", paste(Tver), ", some MC.means can be zero because they cannot be computed with v <= 2.2.8!!\n")

  ## requires TraMineR and WeightedCluster

  ## seqdata: an stslist object
  ## method: the metric to use (see seqdist)
  ## core: number of cores for parallel processing
  ## ...: further parameters passed to seqdist

  indel <- list(...)[["indel"]]
  sm <- list(...)[["sm"]]
  #print(length(indel))
  #print(dim(sm))

  if (model=="keep.dss")
    ch.meth <- 1
  else if (model=="indep")
    ch.meth <- 2
  else if (model=="relative")
    ch.meth <- 3
  else
    stop("Unkown model value")

  if (is.character(kchanges) ){
    if (kchanges=="rand")
      kchanges <- -1
    else
      stop("Invalid kchanges value!")
  }

  if(length(J) == 1) {
    JJ <- 2*J + 1
    Jprob <- J
  }
  else {
    JJ <- length(J)
    if (! JJ %% 2)
      stop("Length of J must be odd!")
    if (any(J<0))
      stop("Negative values in J")

    Jprob <- J/sum(J)
    J <- (JJ - 1)/2
  }


  gc(FALSE)
  if (verbose) {
      cat("Computing MC standard errors using ",core," core(s). Please wait ...")
  #   ptime.begin <- proc.time()
  }

  if(!inherits(seqdata,"stslist"))
    stop("argument seqdata must be a stslist object!")


  ## extract unique sequences (we do not need weights here)

  if(unique) {
    aggCases <- wcAggregateCases(seqdata, weights=attr(seqdata,"weights"))
    ## u.seqdata is set of unique sequences
    u.seqdata <- seqdata[aggCases[["aggIndex"]],]
    sdx <- aggCases[["disaggIndex"]]
    names(sdx) <- rownames(seqdata)
  } else {
    aggCases <- NULL
    u.seqdata <- seqdata
    sdx <- 1:nrow(seqdata)
  }
  ## Transform into numeric to avoid issues with unwanted character in state labels
  #DataU <- seqasnum.one(u.seqdata) ## returns numeric for missing
  DataU <- seqnum(u.seqdata) ## returns a stslist
  #print(DataU)
  L <- ncol(DataU)  ## sequence length if all sequences are of equal length
  NU <- nrow(DataU)

  if (NU < 2) {
    uniq <- ifelse (unique, " unique ", " ")
    stop("Only one",uniq,"sequence, should be at least two!")
  }
  #print(dim(DataU))

  sDataU <- DataU ## DataU is stslist
  sdss <- seqdss(sDataU)
  sdur <- seqdur(sDataU)
  if (replic=="once"){
    replset <- MClistrepset(dss=sdss, sdur=sdur, Jprob=Jprob, R=R, ch.meth=ch.meth, jfixed=jfixed, kchanges=kchanges)
  } else {replset <- NULL}

  syst <- system.time(MC.res <- MC.mean.se(sdss, sdur, sDataU,
                                           Jprob=Jprob, R=R, ch.meth=ch.meth,
                                           jfixed = jfixed, kchanges=kchanges,
                                           replset=replset,
                                           core=core, snow=snow, verbose=verbose,
                                           method=method, ...))

  MC.res.o <- MCexpand(MC.res[["MC.mean"]],MC.res[["MC.se"]],sdx=sdx)
  MC.mean <- MC.res.o[["MC.mean"]]
  MC.se <- MC.res.o[["MC.se"]]

  if (verbose) {
    cat(" OK\n")
    message("Computation time:")
    print(syst)
  #
  #   ptime.end <- proc.time()
  #   time.begin <- as.POSIXct(sum(ptime.begin[1:2]), origin = "1960-01-01")
  #   time.end <- as.POSIXct(sum(ptime.end[1:2]), origin = "1960-01-01")
  #   time.elapsed <- format(round(difftime(time.end, time.begin), 3))
  #
  #   if (core>1) message("!! Unreliable elapsed time because of parallel computing !!")
  #   message("elapsed time:", time.elapsed)
  }

  ## MCse for dissimilarities between identical sequences (unique sequences with freq > 1)

  if (unique) {
    um <- which(table(sdx)>1)
    if (!is.null(um) & length(um)>1){
      if (verbose) {
        cat("Computing MC standard errors for dissimilarities between identical sequences ...")
        #   ptime.begin <- proc.time()
      }

      syst <- system.time(MC.res.u <- MC.mean.se.u(sdss, sdur, sDataU, um = um,
                                               Jprob=Jprob, R=R, ch.meth=ch.meth,
                                               jfixed = jfixed, kchanges=kchanges,
                                               replset=replset,
                                               method=method, ...))

      MC.mean <- as.matrix(MC.mean)
      MC.se <- as.matrix(MC.se)
      for (ii in 1:length(um)){
        iii <- which(sdx==um[ii])
        iii
        il <- length(iii)
        for (i in 1:(il-1)){
          for (j in i:il){
            MC.mean[iii[i],iii[j]] <- MC.mean[iii[j],iii[i]] <- MC.res.u[["MC.mean"]][ii]
            MC.se[iii[i],iii[j]] <- MC.se[iii[j],iii[i]] <- MC.res.u[["MC.se"]][ii]
          }
        }
      }
      MC.mean <- as.dist(MC.mean)
      MC.se <- as.dist(MC.se)

      if (verbose) {
        cat(" OK\n")
        #message("Computation time:")
        print(syst)
      }


    }
  } #else MC.res.u <- NULL


  args.dist <- list(...)
  args.dist <- c(list(seqdata = seqdata, full.matrix=FALSE), args.dist)
  args.dist[["method"]] <- method

  suppressMessages(diss.o <- do.call(seqdist, args.dist ))

  # ret <- list(MC.mean = MC.res[["MC.mean"]], MC.se = MC.res[["MC.se"]], R = R,
  #           sdx = sdx, aggCases=aggCases,
  #           u.seq = u.seqdata, args.dist = args.dist,
  #           diss.u = diss.u, MC.res.u = MC.res.u
  #            )

  ret <- list(MC.mean = MC.mean, MC.se = MC.se, R = R,
              #sdx = sdx, aggCases=aggCases,
              weights = attr(seqdata,"weights"),
              args.dist = args.dist,
              diss.o = diss.o
  )

  class(ret) <- c(class(ret),"distMC")

  if (ratios){
    ret <- c(ret, MCratios(ret))
    class(ret) <- c(class(ret),"distMC")
  }

  return(ret)

}


seqMCset <- function(dss,sdur,Jprob,R=10,ch.meth,
                     jfixed, kchanges){
  mdss <- as.matrix(dss)
  ncs <- ncol(mdss)
  set1 <- set2 <- matrix(nrow=R,ncol=ncs)
  #dur1NA <- is.na(sdur[1,])
  #dur2NA <- is.na(sdur[2,])
  for (i in 1:R){
    if (ch.meth==1)
      dur <- t(apply(sdur,1,ch.dur,Jprob=Jprob, jfixed = jfixed, k=kchanges))
    else if (ch.meth==2)
      dur <- t(apply(sdur,1,ch.dur.indep,Jprob=Jprob, jfixed = jfixed, k=kchanges))
    else if (ch.meth==3)
      dur <- t(apply(sdur,1,ch.dur.relat,Jprob=Jprob, jfixed = jfixed, k=kchanges))

    if (nrow(dur)==1) dur <- t(dur)
    wdur1 <- which(dur[1,]>0)
    wdur2 <- which(dur[2,]>0)
    set1[i,wdur1] <- paste0(mdss[1,wdur1],"/",dur[1,wdur1])
    set2[i,wdur2] <- paste0(mdss[2,wdur2],"/",dur[2,wdur2])
    #set1[i,dur1NA] <- NA
    #set2[i,dur2NA] <- NA
    #set1[i,dur[1,]<=0] <- NA
    #set2[i,dur[2,]<=0] <- NA
  }
  #print(set1[1:3,])
  #print(set2[1:3,])
  sts1 <- seqformat(set1, from="SPS", to="STS", SPS.in=list(xfix="", sdsep="/"), stsep="-")
  sts2 <- seqformat(set2, from="SPS", to="STS", SPS.in=list(xfix="", sdsep="/"), stsep="-")
  rownames(sts1) <- paste0(1:R,"B1")
  rownames(sts2) <- paste0(1:R,"B2")

  #print(length(alphabet(dss)))
  seq2sets <- suppressMessages(
    seqdef(rbind(sts1,sts2), alphabet=alphabet(dss))
  )
  #print(length(alphabet(seq2sets)))
  #print("seqdef done!")
  return(seq2sets)
}

seqdistsple <- function(seq2sets, method, what="distMC", ...){

  #indel <- list(...)[["indel"]]
  #sm <- list(...)[["sm"]]
  #print(length(indel))
  #print(dim(sm))
  #print(length(alphabet(seq2sets)))

  MCdi <- suppressMessages(seqdist(seq2sets,
                                    refseq=list(1:(nrow(seq2sets)/2),(nrow(seq2sets)/2+1):nrow(seq2sets)),
                                    method=method,
                                    ...))
  distMC <- list(mean = mean(MCdi), std = sd(MCdi), distMC = MCdi)
  class(distMC) <- c(class(distMC),"distMC")
  if (what=="distMC") return(distMC)
  else return(MCdi)
}


MC.mean.se <- function(dss, sdur, sDataU, k=nrow(dss),
                       jfixed = FALSE, kchanges=NULL,
                       Jprob, R=50, ch.meth=1, replset=NULL,
                       core=1, snow=FALSE, verbose=TRUE,
                       method, ...){
  meth.with.issues <- method %in% c("SVRspell","NMSMST","OMstran","OMspell") & !packageVersion("TraMineR") > "2.2.8"
  if (verbose & (core==1 | snow)) {
    cat("\n")
    progress <- function(n) setTxtProgressBar(pb, n)
    opts <- list(progress = progress)
    pb <- txtProgressBar(min=1, max=k*(k-1)/2, initial=1, style=3)
  }
  else opts <- list()
  kk <- k*(k-1)/2
  ijtab <- getijtable(k)
  if (!is.null(replset))
    idbase <- seq(0,(R-1)*(nrow(dss)), by=nrow(dss))

  if (core==1) {
    MC.mean <- MC.se <- double(kk)
    for (i in 1:(k-1)) {
      for (j in (i+1):k) {
        if (verbose) setTxtProgressBar(pb, didx(i,j,k))
        if (all(seqlength(dss[c(i,j),,drop=FALSE])==1)){ ## SE is zero
          if (!meth.with.issues){
            ##cat("dss of length 1, (i,j)= (",i,",",j,")\n")
            MC.mean[didx(i,j,k)] <- suppressMessages(seqdist(sDataU[c(i,j),],method=method,...)[1,2])
            ##cat("MC.mean = ", MC.mean[didx(i,j,k)])
          } else {
            cat("\n !!! Special case (",i,",",j,") requires TraMineR > 2.2.8, MC.mean set as zero \n")
            MC.mean[didx(i,j,k)] <- 0
          }
          MC.se[didx(i,j,k)] <- 0
        } else {
          if (!is.null(replset)){
            seq2sets <- replset[c(idbase+i,idbase+j),]
          } else {
            seq2sets <- seqMCset(dss[c(i,j),,drop=FALSE],sdur[c(i,j),,drop=FALSE],
                                 Jprob=Jprob, R=R, ch.meth=ch.meth,
                                 jfixed = jfixed, kchanges=kchanges)

          }
          distMC <- seqdistsple(seq2sets, method=method, what="distMC", ...)
          MC.mean[didx(i,j,k)] <- distMC[["mean"]]
          MC.se[didx(i,j,k)] <- distMC[["std"]]
        }
      }
    }
    if (verbose) close(pb)
  } else { ## parallel computing
    #pb <- txtProgressBar(min=1, max=k-1, initial=1, style=3)
    #cl <- makePSOCKcluster(core)
    cl <- makeCluster(core, type="SOCK")
    if (snow)
      registerDoSNOW(cl)
    else
      registerDoParallel(cl)

    #mat.d <- foreach (i = icount(k-1), .combine=rbind) %:%
    #  foreach (j = icount(k-1), .combine=rbind, .packages=c("TraMineR"), .options.snow=opts) %dopar% {
    #  if (j>k-i)
    #    return(NULL)
    #  else {...
    #  }

    pij <- integer(1)

    mat.d <- foreach (pij = icount(kk), .combine=rbind, .packages=c("TraMineR"), .options.snow=opts) %dopar% {
      i <- ijtab[pij,1]
      jj <- ijtab[pij,2]
      #jj <- j + i
      if (all(seqlength(dss[c(i,jj),,drop=FALSE])==1)){ ## SE is zero
        if (!meth.with.issues){
          mean <- suppressMessages(seqdist(sDataU[c(i,jj),],method=method,...)[1,2])
        } else {
          mean <- 0
        }
        distMC <- list(mean = mean, std = 0)
      } else {
        if (!is.null(replset)){
          seq2sets <- replset[c(idbase+i,idbase+jj),]
        } else {
          seq2sets <- seqMCset(dss[c(i,jj),,drop=FALSE],sdur[c(i,jj),,drop=FALSE],
                               Jprob=Jprob, R=R, ch.meth=ch.meth,
                               jfixed = jfixed, kchanges=kchanges)

        }
        distMC <- seqdistsple(seq2sets, method=method, ...)
      }
      return(c(distMC[["mean"]],distMC[["std"]]))
    }

    stopCluster(cl)
    if(verbose & snow) {
      close(pb)
    }

    mat.d <- as.matrix(mat.d)
    if(ncol(mat.d)<2) mat.d <- t(mat.d)
    #print(dim(mat.d))
    MC.mean <- mat.d[,1,drop=FALSE]
    MC.se <- mat.d[,2,drop=FALSE]
  }

  ## Making MC.mean a dist object
  class(MC.mean) <- "dist"
  attr(MC.mean, "Size") <- k
  attr(MC.mean, "Labels") <- rownames(dss)
  attr(MC.mean, "Diag") <- FALSE
  attr(MC.mean, "Upper") <- FALSE

  ## Making MC.se a dist object
  class(MC.se) <- "dist"
  attr(MC.se, "Size") <- k
  attr(MC.se, "Labels") <- rownames(dss)
  attr(MC.se, "Diag") <- FALSE
  attr(MC.se, "Upper") <- FALSE

  return(list(MC.mean=MC.mean, MC.se=MC.se, R=R, J=Jprob))
}

## for dissimilarities between identical sequences
MC.mean.se.u <- function(dss, sdur, sDataU, um,
                         Jprob, R=50, ch.meth, replset=NULL,
                         jfixed = FALSE, kchanges=NULL,
                         method, ...){
  #meth.with.issues <- method %in% c("SVRspell","NMSMST","OMstran","OMspell") & !packageVersion("TraMineR") > "2.2.8"

  k <- length(as.vector(um))
  if (!is.null(replset))
    idbase <- seq(0,(R-1)*(nrow(dss)), by=nrow(dss))

  # if (verbose & (core==1 | snow)) {
  #   cat("\n")
  #   progress <- function(n) setTxtProgressBar(pbb, n)
  #   opts <- list(progress = progress)
  #   pbb <- txtProgressBar(min=1, max=k, initial=1, style=3)
  # }
  # else
  #opts <- list()

  #if (core==1) {
    MC.mean <- MC.se <- double(k)
    for (i in 1:k) {
      #if (verbose) setTxtProgressBar(pbb, i)
      if (all(seqlength(dss[um[i],,drop=FALSE])==1)){ ## Mean and SE is zero
        MC.mean[i] <- 0
        MC.se[i] <- 0
      } else {
        if (!is.null(replset)){
          seq2sets <- replset[c(idbase+um[i],idbase+um[i]),,drop=FALSE]
        } else {
          seq2sets <- seqMCset(dss[c(um[i],um[i]),,drop=FALSE],sdur[c(um[i],um[i]),,drop=FALSE],
                             Jprob=Jprob, R=R, ch.meth=ch.meth,
                             jfixed = jfixed, kchanges=kchanges)
        }
        distMC <- seqdistsple(seq2sets, method=method, what="distMC", ...)
        MC.mean[i] <- distMC[["mean"]]
        MC.se[i] <- distMC[["std"]]
      }
    }
    #if (verbose) close(pbb)
  # } else { ## parallel computing
  #   #cl <- makePSOCKcluster(core)
  #   cl <- makeCluster(core, type="SOCK")
  #   if (snow)
  #     registerDoSNOW(cl)
  #   else
  #     registerDoParallel(cl)
  #
  #   mat.d <- foreach (i = icount(k), .combine=rbind, .packages=c("TraMineR"), .options.snow=opts) %dopar% {
  #
  #       if (seqlength(dss[um[i],,drop=FALSE])==1){ ## mean and SE is zero
  #         distMC <- list(mean = 0, std = 0)
  #       } else {
  #         seq2sets <- seqMCset(dss[c(um[i],um[i]),,drop=FALSE],sdur[c(um[i],um[i]),,drop=FALSE], Jprob=Jprob, R=R)
  #         distMC <- seqdistsple(seq2sets, method=method, ...)
  #       }
  #       c(distMC[["mean"]],distMC[["std"]])
  #     }
  #   stopCluster(cl)
  #   if(verbose & snow) {
  #     close(pbb)
  #   }
  #
  #     mat.d <- as.matrix(mat.d)
  #     if(ncol(mat.d)<2) mat.d <- t(mat.d)
  #     #print(dim(mat.d))
  #     MC.mean <- mat.d[,1,drop=FALSE]
  #     MC.se <- mat.d[,2,drop=FALSE]
  #}

  return(list(MC.mean=MC.mean, MC.se=MC.se, R=R, J=Jprob))
}



MCexpand <- function(MC.mean, MC.se, sdx){
  MCdiss.ori <- as.matrix(MC.mean)[sdx,sdx]
  sd.ori <- as.matrix(MC.se)[sdx,sdx]
  dimnames(MCdiss.ori) <-  dimnames(sd.ori) <- list(names(sdx),names(sdx))
  res <- list(MC.mean = as.dist(MCdiss.ori), MC.se = as.dist(sd.ori))
  return(res)
}



MCdistrib <- function(dss,dur,id2=1:2, Jprob, R=100, model="keep.dss",
                      jfixed=FALSE, kchanges=NULL,
                      method="LCS", ...){
  Jprob <- Jprob/sum(Jprob)
  if (model=="keep.dss")
    ch.meth <- 1
  else if (model=="indep")
    ch.meth <- 2
  else if (model=="relative")
    ch.meth <- 3
  else
    stop("Unkown model value")

  #seq2sets <- seqdistMCSE:::seqMCset(dss[id2,],dur[id2,], Jprob=Jprob, R=R)
  #MC.dist <- seqdistMCSE:::seqdistsple(seq2sets, method=method, what="MC distances", ...)
  seq2sets <- seqMCset(dss[id2,],dur[id2,], Jprob=Jprob, R=R, ch.meth=ch.meth,
                       jfixed=jfixed, kchanges=kchanges)
  MC.dist <- seqdistsple(seq2sets, method=method, what="MC distances", ...)
  return(MC.dist)
}

