R/RDML.types.R

Defines functions step experimenter lidTemperature documentation description id initialize lidOpen pause loop gradient temperature description nr initialize lowTemperature highTemperature initialize temperature initialize ramp measure durationChange temperatureChange duration initialize repeat.n goto initialize temperature initialize initialize run documentation description id GetFData initialize react runDate pcrFormat thermalCyclingConditions cqDetectionMethod backgroundDeterminationMethod dataCollectionSoftware instrument experimenter documentation description id UpdateReactsPosition GetFData initialize columnLabel rowLabel columns rows initialize version name initialize position data sample id .recalcPosition GetFData initialize quantFluor bgFluorSlp bgFluor endPt mdp adp excl cq tar as.character.reactIdType as.character.idType checkDateTime list.names

Documented in as.character.idType as.character.reactIdType GetFData

# rlist::list.names with correct .data=NULL
list.names <- function(data, ...) {
  tryCatch(
    rlist::list.names(data, ...),
    error = function(e) {
      NULL
    }
  )
}

checkDateTime <- function(dateTime){
  if (is.null(dateTime))
    return(TRUE)
  if (!is.na(ymd_hms(dateTime, quiet = TRUE)) ||
     !is.na(ymd(dateTime, quiet = TRUE))) {
    return(TRUE)
  }
  return("Must pass lubridate ymd_hms() or ymd() conversion")
}

# rdmlBaseType ------------------------------------------------------------

#' Base R6 class for RDML package.
#'
#' Most classes from RDML package inherit this class. It is designed for internal
#' usage and should not be directly accessed.
#'
#' @section Initialization: \preformatted{rdmlBaseType$new()}
#'
#' @section Methods: \describe{
#' \item{\code{.asXMLnodes(node.name)}}{Represents
#'   object as XML nodes. Should not be called directly. \code{node.name} --
#'   name of the root node for the generated XML
#'   tree.}
#' \item{\code{print(...)}}{prints object}}
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
rdmlBaseType <-
  R6Class("rdmlBaseType",
          # class = FALSE,
          public = list(
            .asXMLnodes = function(node.name) {
              subnodes <- names(private)[grepl("^\\..*$",
                                               names(private))] # %>>% rev()
              sprintf("<%s%s>%s</%s>",
                      node.name, #node name
                      # attribute
                      {
                        attrs <- NULL
                        for (subnode in subnodes) {
                          if (class(private[[subnode]])[1] == "idType" ||
                              class(private[[subnode]])[1] == "reactIdType") {
                            attrs <- c(attrs, subnode)
                          }
                        }
                        if (length(attrs) == 0) {
                          ""
                        } else {
                          subnodes <-
                            setdiff(subnodes, attrs)
                          sprintf(" id = '%s'", private[[attrs[1]]]$id)
                        }
                        # "'attr'"
                      },
                      # value
                      {
                        sapply(
                          subnodes,
                          function(name) {
                            subnode.name <- gsub("^\\.(.*)$",
                                                 "\\1", name)
                            switch(
                              typeof(private[[name]]),
                              closure = NULL,
                              list =
                                sapply(private[[name]],
                                       function(sublist)
                                         sublist$.asXMLnodes(subnode.name)) %>>%
                                # .[!sapply(., is.null)] %>>%
                                paste0(collapse = "\n")
                              ,
                              environment = {
                                private[[name]]$.asXMLnodes(subnode.name)
                              },
                              {
                                if (is.null(private[[name]]) ||
                                    is.na(private[[name]])) {
                                  NULL
                                } else {
                                  sprintf("<%s>%s</%s>\n",
                                          subnode.name,
                                          switch(
                                            typeof(private[[name]]),
                                            logical =
                                              ifelse(private[[name]],
                                                     "true",
                                                     "false"
                                              ),
                                            private[[name]]
                                          ),
                                          subnode.name
                                  )
                                }
                              })
                          }) %>>%
                          (vals ~ vals[!sapply(vals, is.null)]) %>>%
                          paste0(collapse = "")
                      },
                      node.name)
            },
            copy = function() {
              self$clone(deep = TRUE)
            },
            print = function(...) {
              elements <- names(private)[-which(names(private) ==
                                                  "deep_clone")] %>>% rev
              sapply(elements,
                     function(name) {
                       sprintf(
                         "%s: %s",
                         gsub("^\\.(.*)$",
                              "\\1", name),
                         switch(
                           typeof(private[[name]]),
                           closure = NULL,
                           list = sprintf("[%s]",
                                          names(private[[name]]) %>>%
                                            paste(collapse = ", ")),
                           environment = {
                             sprintf("~ %s",
                                     class(private[[name]])[1])
                           },
                           NULL = "",
                           {
                             if (class(private[[name]]) == "matrix")
                               sprintf("%s fluorescence data points",
                                       nrow(private[[name]]))
                             else
                               sprintf("%s", private[[name]])
                           }))
                     }) %>>%
                paste(sep = "\n", collapse = "\n") %>>%
                cat
              cat("\n")
            }
          ),
          private = list(
            deep_clone = function(name, value) {
              if (is.null(value))
                return(NULL)
              if (tail(class(value), 1) != "R6") {
                if (is.list(value) && !is.data.table(value)) {
                  list.map(value,
                        el ~ {
                          if (tail(class(el), 1) == "R6")
                            el$copy()
                          else
                            el
                        })
                } else {
                  value
                }
              } else {
                value$copy()
              }
            }
          )
  )

# rdmlIdType ------------------------------------------------------------

#' rdmlIdType R6 class.
#'
#' This element can be used to assign a publisher and id to the RDML file.\cr
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{rdmlIdType$new(publisher, serialNumber,
#'   MD5Hash = NULL)}
#'
#' @section Fields: \describe{
#'   \item{\code{publisher}}{\link[checkmate]{checkString}. RDML file publisher.}
#'   \item{\code{serialNumber}}{\link[checkmate]{checkString}. Serial number.}
#'   \item{\code{MD5Hash}}{\link[checkmate]{checkString}. An MD5Hash calculated
#'   over the complete file after removing all rdmlIDTypes and all whitespaces
#'   between elements.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
rdmlIdType <-
  R6Class("rdmlIdType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(publisher,
                                  serialNumber,
                                  MD5Hash = NULL) {
              self$publisher <- publisher
              self$serialNumber <- serialNumber
              self$MD5Hash <- MD5Hash
              
            }
          ),
          private = list(
            .publisher = NULL,
            .serialNumber = NULL,
            .MD5Hash = NULL
          ),
          active = list(
            publisher = function(publisher) {
              if (missing(publisher))
                return(private$.publisher)
              assertString(publisher)
              private$.publisher <- publisher
            },
            serialNumber = function(serialNumber) {
              if (missing(serialNumber))
                return(private$.serialNumber)
              assertString(serialNumber)
              private$.serialNumber <- serialNumber
            },
            MD5Hash = function(MD5Hash) {
              if (missing(MD5Hash))
                return(private$.MD5Hash)
              assertString(MD5Hash, null.ok = TRUE)
              private$.MD5Hash <- MD5Hash
            }
          ))

# idType ------------------------------------------------------------

#' idType R6 class.
#'
#' Contains identificator for varius RDML types. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{idType$new(id)}
#'
#'   @section Fields: \describe{
#' \item{\code{id}}{\link[checkmate]{checkString}. Identificator.}
#' }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
idType <-
  R6Class("idType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id) {
              self$id <- id
            },
            .asXMLnodes = function(node.name) {
              sprintf("<%s id = '%s'/>",
                      node.name,
                      private$.id)
            }
            #                         print = function(...) {
            #                           cat(private$.id)
            #                         }
          ),
          private = list(
            .id = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertString(id)
              private$.id <- id
            }
          ))

#' Convert \code{idType} object to \code{character}
#' 
#' Function to convert \code{idType} object to \code{character}.
#' 
#' @param x \code{idType} object.
#' @param ... Further arguments to be passed.
#' 
#' @docType methods
#' @keywords manip
#' @name as.character.idType
#' @rdname ascharacteridType-method
#' @export
as.character.idType <- function(x, ...) x$id

# reactIdType ------------------------------------------------------------

#' reactIdType R6 class.
#'
#' Contains identificator for reactType. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{reactIdType$new(id)}
#'
#'   @section Fields: \describe{
#' \item{\code{id}}{\link[checkmate]{checkCount}. Identificator.}
#' }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
reactIdType <-
  R6Class("reactIdType",
          # class = FALSE,
          inherit = idType,
          public = list(
            initialize = function(id) {
              self$id <- id
            }#,
            #             print = function(...) {
            #               cat(private$.id)
            #             }
          ),
          private = list(
            .id = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertCount(id)
              private$.id <- id
            }
          ))

#' Convert \code{reactIdType} object to \code{character}
#' 
#' Function to convert \code{reactIdType} object to \code{character}.
#' 
#' @param x \code{reactIdType} object.
#' @param ... Further arguments to be passed.
#' 
#' @docType methods
#' @keywords manip
#' @name as.character.reactIdType
#' @rdname ascharacterreactIdType-method
#' @export
as.character.reactIdType <- function(x, ...) as.character(x$id)

# idReferencesType ------------------------------------------------------------

#' idReferencesType R6 class.
#'
#' Contains id of another RDML object. Inherits: \link{idType}.
#'
#' @section Initialization: \preformatted{idReferencesType$new(id)}
#'
#' @section Fields: \describe{
#' \item{\code{id}}{\link[checkmate]{checkString}. Identificator.}
#' }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
idReferencesType <-
  R6Class("idReferencesType",
          # class = FALSE,
          inherit = idType)

# experimenterType ------------------------------------------------------------

#' experimenterType R6 class.
#'
#' Contact details of the experimenter. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{experimenterType$new(id, firstName, lastName,
#'   email = NULL, labName = NULL, labAddress = NULL)}
#'
#'   @section Fields: \describe{
#' \item{\code{id}}{\link{idType}. Identificator.}
#' \item{\code{firstName}}{\link[checkmate]{checkString}. First name.}
#' \item{\code{lastName}}{\link[checkmate]{checkString}. Last name.}
#' \item{\code{email}}{\link[checkmate]{checkString}. Email.}
#' \item{\code{labName}}{\link[checkmate]{checkString}. Lab name.}
#' \item{\code{labAddress}}{\link[checkmate]{checkString}. Lab address.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
experimenterType <-
  R6Class("experimenterType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  firstName,
                                  lastName,
                                  email = NULL,
                                  labName = NULL,
                                  labAddress = NULL) {
              self$id <- id
              self$firstName <- firstName
              self$lastName <- lastName
              self$email <- email
              self$labName <- labName
              self$labAddress <- labAddress
            }
          ),
          private = list(
            .id = NULL,
            .firstName = NULL,
            .lastName = NULL,
            .email = NULL,
            .labName = NULL,
            .labAddress = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            firstName = function(firstName) {
              if (missing(firstName))
                return(private$.firstName)
              assertString(firstName)
              private$.firstName <- firstName
            },
            lastName = function(lastName) {
              if (missing(lastName))
                return(private$.lastName)
              assertString(lastName)
              private$.lastName <- lastName
            },
            email = function(email) {
              if (missing(email))
                return(private$.email)
              assertString(email, null.ok = TRUE)
              private$.email <- email
            },
            labName = function(labName) {
              if (missing(labName))
                return(private$.labName)
              assertString(labName, null.ok = TRUE)
              private$.labName <- labName
            },
            labAddress = function(labAddress) {
              if (missing(labAddress))
                return(private$.labAddress)
              assertString(labAddress, null.ok = TRUE)
              private$.labAddress <- labAddress
            }
          ))

# documentationType ------------------------------------------------------------

#' documentationType R6 class.
#'
#' These elements should be used if the same description applies to many
#' samples, targets or experiments. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{documentationType$new(id, text = NULL)}
#'
#'   @section Fields: \describe{
#' \item{\code{id}}{\link{idType}. Identificator.}
#' \item{\code{text}}{\link[checkmate]{checkString}. Text.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
documentationType <-
  R6Class("documentationType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  text = NULL) {
              self$id <- id
              self$text <- text
            }
          ),
          private = list(
            .id = NULL,
            .text = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            text = function(text) {
              if (missing(text))
                return(private$.text)
              assertString(text, null.ok = TRUE)
              private$.text <- text
            }
          ))

# dyeType ------------------------------------------------------------

#' dyeType R6 class.
#'
#' Detailed information about the dye. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{dyeType$new(id, description = NULL)}
#'
#'   @section Fields: \describe{
#' \item{\code{id}}{\link{idType}. Identificator.}
#' \item{\code{description}}{ \link[checkmate]{checkString}. Description.
#'   }}
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
dyeType <-
  R6Class("dyeType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  description = NULL) {
              self$id <- id
              self$description <- description
            }
          ),
          private = list(
            .id = NULL,
            .description = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            description = function(description) {
              if (missing(description))
                return(private$.description)
              assertString(description, null.ok = TRUE)
              private$.description <- description
            }
          ))

# xRefType ------------------------------------------------------------

#' xRefType R6 class.
#'
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{xRefType$new(name = NULL, id = NULL)}
#'
#'   @section Fields: \describe{
#'   \item{\code{name}}{\link[checkmate]{checkString}. Reference to an external
#'   database, } for example "GenBank".
#'   \item{\code{id}}{\link[checkmate]{checkString}. The ID of the entry within
#'   the external database, for example "AJ832138".}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
xRefType <-
  R6Class("xRefType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(name = NULL,
                                  id = NULL) {
              self$name <- name
              self$id <- id
            }
          ),
          private = list(
            .name = NULL,
            .id = NULL
          ),
          active = list(
            name = function(name) {
              if (missing(name))
                return(private$.name)
              assertString(name, null.ok = TRUE)
              private$.name <- name
            },
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertString(id, null.ok = TRUE)
              private$.id <- id
            }
          ))

# annotationType ------------------------------------------------------------

#' annotationType R6 class.
#'
#' Annotate samples by setting a property and its value. For example,
#' sex could be a property with the possible values M or F. Inherits:
#' \link{rdmlBaseType}.
#'
#' @section Fields: \describe{ \item{property}{\link[checkmate]{checkString}.
#'   Property name} \item{value}{\link[checkmate]{checkString}. Value} }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
#' @examples
#' #set sex property
#' annotationType$new(property = "sex", value = "M")
annotationType <-
  R6Class("annotationType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(property,
                                  value) {
              self$property <- property
              self$value <- value
            }
          ),
          private = list(
            .property = NULL,
            .value = NULL
          ),
          active = list(
            property = function(property) {
              if (missing(property))
                return(private$.property)
              assertString(property)
              private$.property <- property
            },
            value = function(value) {
              if (missing(value))
                return(private$.value)
              assertString(value)
              private$.value <- value
            }
          ))

# quantityType ------------------------------------------------------------

#' quantityType R6 class.
#'
#' A quantity is always defined by its value and its unit. Inherits:
#' \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{quantityType$new(value, unit)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkNumber}. Value.}
#' \item{\code{unit}}{\link{quantityUnitType}. Unit.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
quantityType <-
  R6Class("quantityType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(value,
                                  unit) {
              self$value <- value
              self$unit <- unit
            }
          ),
          private = list(
            .value = NULL,
            .unit = NULL
          ),
          active = list(
            value = function(value) {
              if (missing(value))
                return(private$.value)
              assertNumber(value)
              private$.value <- value
            },
            unit = function(unit) {
              if (missing(unit))
                return(private$.unit)
              assertR6(unit, "quantityUnitType")
              private$.unit <- unit
            }
          ))

# cdnaSynthesisMethodType ------------------------------------------------------------

#' cdnaSynthesisMethodType R6 class.
#'
#' Description of the cDNA synthesis method. Inherits: \link{rdmlBaseType}.
#'
#' @section
#' Initialization: \preformatted{cdnaSynthesisMethodType$new(enzyme = NULL,
#'   primingMethod = NULL, dnaseTreatment = NULL, thermalCyclingConditions =
#'   NULL)}
#'
#'   @section Fields: \describe{
#'   \item{\code{enzyme}}{\link[checkmate]{checkString}. Name of the enzyme used for
#'   reverse transcription.}
#'   \item{\code{primingMethod}}{\link{primingMethodType}.}
#'   \item{\code{dnaseTreatment}}{\link[checkmate]{checkFlag} if \code{TRUE}RNA was
#'   DNAse treated prior cDNA synthesis.}
#'   \item{\code{thermalCyclingConditions}}{\link{idReferencesType}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
cdnaSynthesisMethodType <-
  R6Class("cdnaSynthesisMethodType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(enzyme = NULL,
                                  primingMethod = NULL,
                                  dnaseTreatment = NULL,
                                  thermalCyclingConditions = NULL) {
              self$enzyme <- enzyme
              self$primingMethod <- primingMethod
              self$dnaseTreatment <- dnaseTreatment
              self$thermalCyclingConditions <- thermalCyclingConditions
            }
          ),
          private = list(
            .enzyme = NULL,
            .primingMethod = NULL,
            .dnaseTreatment = NULL,
            .thermalCyclingConditions = NULL
          ),
          active = list(
            enzyme = function(enzyme) {
              if (missing(enzyme))
                return(private$.enzyme)
              assertString(enzyme, null.ok = TRUE)
              private$.enzyme <- enzyme
            },
            primingMethod = function(primingMethod) {
              if (missing(primingMethod))
                return(private$.primingMethod)
              assertR6(primingMethod, "primingMethodType", null.ok = TRUE)
              private$.primingMethod <- primingMethod
            },
            dnaseTreatment = function(dnaseTreatment) {
              if (missing(dnaseTreatment))
                return(private$.dnaseTreatment)
              assertFlag(dnaseTreatment, null.ok = TRUE)
              private$.dnaseTreatment <- dnaseTreatment
            },
            thermalCyclingConditions = function(thermalCyclingConditions) {
              if (missing(thermalCyclingConditions))
                return(private$.thermalCyclingConditions)
              assertR6(thermalCyclingConditions, "idType", null.ok = TRUE)
              private$.thermalCyclingConditions <- thermalCyclingConditions
            }
          ))

# templateQuantityType ------------------------------------------------------------

#' templateQuantityType R6 class.
#'
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{templateQuantityType$new(conc, nucleotide)}
#'
#'   @section Fields: \describe{
#' \item{\code{conc}}{\link[checkmate]{checkNumber}. Concentration of the template in nanogram}
#'   per microliter in the final reaction mix.
#' \item{\code{nucleotide}}{\link{nucleotideType}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
templateQuantityType <-
  R6Class("templateQuantityType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(conc,
                                  nucleotide) {
              self$conc <- conc
              self$nucleotide <- nucleotide
            }
          ),
          private = list(
            .conc = NULL,
            .nucleotide = NULL
          ),
          active = list(
            conc = function(conc) {
              if (missing(conc))
                return(private$.conc)
              assertNumber(conc)
              private$.conc <- conc
            },
            nucleotide = function(nucleotide) {
              if (missing(nucleotide))
                return(private$.nucleotide)
              assertR6(nucleotide, "nucleotideType")
              private$.nucleotide <- nucleotide
            }
          ))

# enumType ------------------------------------------------------------

#' enumType R6 class.
#'
#' Generic class for creating objects thet can take limited list of values. \cr
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{enumType$new(value)}
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}. Value.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
enumType <-
  R6Class("enumType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(value) {
              self$value <- value
            },
            print = function(...) {
              cat(private$.value)
            },
            .asXMLnodes = function(node.name) {
              if (is.null(private$.value) ||
                  is.na(private$.value))
                NULL
              else
                sprintf("<%s>%s</%s>",
                        node.name,
                        private$.value,
                        node.name)
            }
          ),
          private = list(
            .value = NULL
          ),
          active = list(
            value = function(value) {
              if (missing(value))
                return(private$.value)
              assertChoice(value, c(private$.levels), null.ok = TRUE)
              private$.value <- value
            }
          ))

# sampleTypeType ------------------------------------------------------------

#' sampleTypeType R6 class.
#'
#' Can take values:
#' \describe{
#' \item{unkn}{unknown sample}
#' \item{ntc}{non template control}
#' \item{nac}{no amplification control}
#' \item{std}{standard sample}
#' \item{ntp}{no target present}
#' \item{nrt}{minusRT}
#' \item{pos}{positive control}
#' \item{opt}{optical calibrator sample}}
#'
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{sampleTypeType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}. Value.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
sampleTypeType <-
  R6Class("sampleTypeType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("unkn", "ntc", "nac",
                        "std", "ntp", "nrt",
                        "pos", "opt")
          )
  )

# quantityUnitType ------------------------------------------------------------

#' quantityUnitType R6 class.
#'
#' The unit the quantity. Can take values:
#' \describe{
#' \item{cop}{copies per microliter  }
#' \item{fold}{fold change  }
#' \item{dil}{dilution (10 would mean 1:10 dilution)  }
#' \item{nMol}{nanomol per microliter }
#' \item{ng}{nanogram per microliter }
#' \item{other}{other unit (must be linear, no exponents or logarithms allowed) }
#' }
#'
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{quantityUnitType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}. Value.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
quantityUnitType <-
  R6Class("quantityUnitType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("cop", "fold", "dil", "ng", "nMol", "other")
          )
  )

# primingMethodType ------------------------------------------------------------

#' primingMethodType R6 class.
#'
#' The primers used in the reverse transcription. Can take values:
#' \describe{
#' \item{oligo-dt}{}
#' \item{random}{}
#' \item{target-specific}{}
#' \item{oligo-dt and random}{}
#' \item{other}{}
#' }
#'
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{primingMethodType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}. Value.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
primingMethodType <-
  R6Class("primingMethodType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("oligo-dt",
                        "random",
                        "target-specific",
                        "oligo-dt and random",
                        "other")
          )
  )

# nucleotideType ------------------------------------------------------------

#' nucleotideType R6 class.
#'
#' Type of nucleic acid used as a template in the experiment. May have following values:
#' \describe{
#' \item{DNA}{}
#' \item{genomic DNA}{}
#' \item{cDNA}{}
#' \item{RNA}{}
#' }
#'
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{nucleotideType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}. Value.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
nucleotideType <-
  R6Class("nucleotideType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("DNA",
                        "genomic DNA",
                        "cDNA",
                        "RNA")
          )
  )

# sampleType ------------------------------------------------------------

#'sampleType R6 class.
#'
#' A sample is a template solution with defined concentation. Since dilutions
#' of the same material differ in concentration, they are considered different
#' samples. A technical replicate samples should contain the same name (reactions
#' are performed on the same material), and biological replicates should contain
#' different names (the template derived from the different biological replicates
#' is are divergent). Serial dilutions in a standard curve must have different
#' names (preferably stating their dillution).
#' Inherits: \link{rdmlBaseType}.
#'
#'@section Initialization: \preformatted{sampleType$new(id, description = NULL,
#'  documentation = NULL, xRef =  NULL, annotation = NULL, type =
#'  sampleTypeType$new("unkn"), interRunCalibrator = FALSE, quantity = NULL,
#'  calibratorSample = FALSE, cdnaSynthesisMethod = NULL, templateQuantity =
#'  NULL)}
#'
#'  @section Fields: \describe{
#'  \item{\code{id}}{\link{idType}. Concentration of the template in nanogram
#'  per microliter in the final reaction mix. }
#'  \item{\code{description}}{\link[checkmate]{checkString}.}
#'  \item{\code{documentation}}{\code{list} of \link{idReferencesType}.}
#'  \item{\code{xRef}}{\code{list} of \link{xRefType}.}
#'  \item{\code{annotation}}{\code{list} of \link{annotationType}.}
#'  \item{\code{type}}{\link{sampleTypeType}.}
#'  \item{\code{interRunCalibrator}}{\link[checkmate]{checkFlag}. \code{TRUE}
#'  if this sample is used as inter run calibrator. }
#'  \item{\code{quantity}}{\link{quantityType}. Quantity - The reference
#'  quantity of this sample. It should be only used if the sample is part of a
#'  standard curve. The provided value will be used to quantify unknown samples
#'  in absolute quantification assays. Only the use of positive integers (like 1,
#'  10, 100, 1000) and fractions (e.g. 1, 0.1, 0.01, 0.001) is acceptable.
#'  The use of exponents (1, 2, 3, 4 or -1, -2, -3, -4) if forbidden,
#'  because it will not be interpreted as 10E1, 10E2, 10E3, 10E4 or 10E-1, 10E-2,
#'  10E-3, 10E-4. }
#'  \item{\code{calibratorSample}}{\link[checkmate]{checkFlag}. \code{TRUE} if this
#'  sample is used as calibrator sample. }
#'  \item{\code{cdnaSynthesisMethod}}{\link{cdnaSynthesisMethodType}.}
#'  \item{\code{templateQuantity}}{\link{templateQuantityType}.}
#'  }
#'
#'@docType class
#'@format An \code{\link{R6Class}} generator object.
#'@export
sampleType <-
  R6Class("sampleType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  description = NULL,
                                  documentation = NULL,
                                  xRef = NULL,
                                  annotation = NULL,
                                  type = sampleTypeType$new("unkn"),
                                  interRunCalibrator = FALSE,
                                  quantity = NULL,
                                  calibratorSample = FALSE,
                                  cdnaSynthesisMethod = NULL,
                                  templateQuantity = NULL) {
              self$id <- id
              self$description <- description
              self$documentation <- documentation
              self$xRef <- xRef
              self$annotation <- list.names(annotation,
                                                .$property)
              self$type <- type
              self$interRunCalibrator <- interRunCalibrator
              self$quantity <- quantity
              self$calibratorSample <- calibratorSample
              self$cdnaSynthesisMethod <- cdnaSynthesisMethod
              self$templateQuantity <- templateQuantity
            }
          ),
          private = list(
            .id = NULL,
            .description = NULL,
            .documentation = NULL,
            .xRef = NULL,
            .annotation = NULL,
            .type = NULL,
            .interRunCalibrator = NULL,
            .quantity = NULL,
            .calibratorSample = NULL,
            .cdnaSynthesisMethod = NULL,
            .templateQuantity = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            description = function(description) {
              if (missing(description))
                return(private$.description)
              assertString(description, null.ok = TRUE)
              private$.description <- description
            },
            documentation = function(documentation) {
              if (missing(documentation))
                return(private$.documentation)
              assertList(documentation, "idReferencesType", unique = TRUE,
                         null.ok = TRUE)
              private$.documentation <- documentation
            },
            xRef = function(xRef) {
              if (missing(xRef))
                return(private$.xRef)
              assertList(xRef, "xRefType", unique = TRUE, null.ok = TRUE)
              private$.xRef <- xRef
            },
            annotation = function(annotation) {
              if (missing(annotation))
                return(private$.annotation)
              assertList(annotation, "annotationType", unique = TRUE, null.ok = TRUE)
              private$.annotation <- list.names(annotation,
                                                .$property)
            },
            type = function(type) {
              if (missing(type))
                return(private$.type)
              assertR6(type, "sampleTypeType")
              private$.type <- type
            },
            interRunCalibrator = function(interRunCalibrator) {
              if (missing(interRunCalibrator))
                return(private$.interRunCalibrator)
              assertFlag(interRunCalibrator, null.ok = TRUE)
              private$.interRunCalibrator <- interRunCalibrator
            },
            quantity = function(quantity) {
              if (missing(quantity))
                return(private$.quantity)
              assertR6(quantity, "quantityType", null.ok = TRUE)
              private$.quantity <- quantity
            },
            calibratorSample = function(calibratorSample) {
              if (missing(calibratorSample))
                return(private$.calibratorSample)
              assertFlag(calibratorSample, null.ok = TRUE)
              private$.calibratorSample <- calibratorSample
            },
            cdnaSynthesisMethod = function(cdnaSynthesisMethod) {
              if (missing(cdnaSynthesisMethod))
                return(private$.cdnaSynthesisMethod)
              assertR6(cdnaSynthesisMethod, "cdnaSynthesisMethodType", null.ok = TRUE)
              private$.cdnaSynthesisMethod <- cdnaSynthesisMethod
            },
            templateQuantity = function(templateQuantity) {
              if (missing(templateQuantity))
                return(private$.templateQuantity)
              assertR6(templateQuantity, "templateQuantityType", null.ok = TRUE)
              private$.templateQuantity <- templateQuantity
            }
          ))

# oligoType ------------------------------------------------------------

#' oligoType R6 class.
#'
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{oligoType$new(threePrimeTag = NULL,
#'   fivePrimeTag = NULL, sequence)}
#'
#'   @section Fields: \describe{
#'   \item{\code{threePrimeTag}}{\link[checkmate]{checkString}. Description of
#'   three prime modification (if present). }
#'   \item{\code{fivePrimeTag}}{\link[checkmate]{checkString}. Description of
#'   five prime modification (if present).}
#'   \item{\code{sequence}}{\link[checkmate]{checkString}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
oligoType <-
  R6Class("oligoType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(threePrimeTag = NULL,
                                  fivePrimeTag = NULL,
                                  sequence) {
              self$threePrimeTag <- threePrimeTag
              self$fivePrimeTag <- fivePrimeTag
              self$sequence <- sequence
            }
          ),
          private = list(
            .threePrimeTag = NULL,
            .fivePrimeTag = NULL,
            .sequence = NULL
          ),
          active = list(
            threePrimeTag = function(threePrimeTag) {
              if (missing(threePrimeTag))
                return(private$.threePrimeTag)
              assertString(threePrimeTag, null.ok = TRUE)
              private$.threePrimeTag <- threePrimeTag
            },
            fivePrimeTag = function(fivePrimeTag) {
              if (missing(fivePrimeTag))
                return(private$.fivePrimeTag)
              assertString(fivePrimeTag, null.ok = TRUE)
              private$.fivePrimeTag <- fivePrimeTag
            },
            sequence = function(sequence) {
              if (missing(sequence))
                return(private$.sequence)
              assertString(sequence)
              private$.sequence <- sequence
            }
          ))

# sequencesType ------------------------------------------------------------

#' sequencesType R6 class.
#'
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{sequencesType$new(forwardPrimer = NULL,
#' reversePrimer = NULL, probe1 = NULL, probe2 = NULL, amplicon = NULL)}
#'
#'   @section Fields: \describe{
#' \item{\code{forwardPrimer}}{\link{oligoType}.}
#' \item{\code{reversePrimer}}{\link{oligoType}.}
#' \item{\code{probe1}}{\link{oligoType}.}
#' \item{\code{probe2}}{\link{oligoType}.}
#' \item{\code{amplicon}}{\link{oligoType}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
sequencesType <-
  R6Class("sequencesType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(forwardPrimer = NULL,
                                  reversePrimer = NULL,
                                  probe1 = NULL,
                                  probe2 = NULL,
                                  amplicon = NULL) {
              self$forwardPrimer <- forwardPrimer
              self$reversePrimer <- reversePrimer
              self$probe1 <- probe1
              self$probe2 <- probe2
              self$amplicon <- amplicon
            }
          ),
          private = list(
            .forwardPrimer = NULL,
            .reversePrimer = NULL,
            .probe1 = NULL,
            .probe2 = NULL,
            .amplicon = NULL
          ),
          active = list(
            forwardPrimer = function(forwardPrimer) {
              if (missing(forwardPrimer))
                return(private$.forwardPrimer)
              assertR6(forwardPrimer, "oligoType", null.ok = TRUE)
              private$.forwardPrimer <- forwardPrimer
            },
            reversePrimer = function(reversePrimer) {
              if (missing(reversePrimer))
                return(private$.reversePrimer)
              assertR6(reversePrimer, "oligoType", null.ok = TRUE)
              private$.reversePrimer <- reversePrimer
            },
            probe1 = function(probe1) {
              if (missing(probe1))
                return(private$.probe1)
              assertR6(probe1, "oligoType", null.ok = TRUE)
              private$.probe1 <- probe1
            },
            probe2 = function(probe2) {
              if (missing(probe2))
                return(private$.probe2)
              assertR6(probe2, "oligoType", null.ok = TRUE)
              private$.probe2 <- probe2
            },
            amplicon = function(amplicon) {
              if (missing(amplicon))
                return(private$.amplicon)
              assertR6(amplicon, "oligoType", null.ok = TRUE)
              private$.amplicon <- amplicon
            }
          ))

# commercialAssayType ------------------------------------------------------------

#' commercialAssayType R6 class.
#'
#' For some commercial assays, the primer sequences may be unknown. This element
#' allows to describe commercial assays. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{commercialAssayType$new(company, orderNumber)}
#'
#'   @section Fields: \describe{
#' \item{\code{company}}{\link[checkmate]{checkString}.}
#' \item{\code{orderNumber}}{\link[checkmate]{checkString}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
commercialAssayType <-
  R6Class("commercialAssayType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(company,
                                  orderNumber) {
              self$company <- company
              self$orderNumber <- orderNumber
            }
          ),
          private = list(
            .company = NULL,
            .orderNumber = NULL
          ),
          active = list(
            company = function(company) {
              if (missing(company))
                return(private$.company)
              assertString(company)
              private$.company <- company
            },
            orderNumber = function(orderNumber) {
              if (missing(orderNumber))
                return(private$.orderNumber)
              assertString(orderNumber)
              private$.orderNumber <- orderNumber
            }
          ))

# targetTypeType ------------------------------------------------------------

#' targetTypeType R6 class.
#'
#' Can take values:
#' \describe{
#' \item{ref}{reference target}
#' \item{toi}{target of interest}
#' }
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{targetTypeType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}.}
#' }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
targetTypeType <-
  R6Class("targetTypeType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("ref",
                        "toi")
          )
  )

# targetType ------------------------------------------------------------

#' targetType R6 class.
#'
#' A target is a PCR reaction with defined set of primers. PCR reactions
#' for the same gene with distinct primer sequences are considered different
#' targets. Inherits:
#' \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{targetType$new(id, description = NULL,
#'   documentation = NULL, xRef = NULL, type, amplificationEfficiencyMethod =
#'   NULL, amplificationEfficiency = NULL, amplificationEfficiencySE = NULL,
#'   detectionLimit = NULL, dyeId, sequences = NULL, commercialAssay = NULL)}
#'
#' @section Fields: \describe{ \item{\code{id}}{\link{idType}.}
#'   \item{\code{description}}{\link[checkmate]{checkString}.}
#'   \item{\code{documentation}}{\code{list} of \link{idReferencesType}.}
#'   \item{\code{xRef}}{\code{list} of \link{xRefType}.}
#'   \item{\code{type}}{\link{targetTypeType}.}
#'   \item{\code{amplificationEfficiencyMethod}}{\link[checkmate]{checkString}.}
#'   \item{\code{amplificationEfficiency}}{\link[checkmate]{checkNumber}.}
#'   \item{\code{amplificationEfficiencySE}}{\link[checkmate]{checkNumber}.}
#'   \item{\code{detectionLimit}}{\link[checkmate]{checkNumber}.}
#'   \item{\code{dyeId}}{\link{idReferencesType}.}
#'   \item{\code{sequences}}{\link{sequencesType}.}
#'   \item{\code{commercialAssay}}{\link{commercialAssayType}.} }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
targetType <-
  R6Class("targetType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  description = NULL,
                                  documentation = NULL,
                                  xRef = NULL,
                                  type,
                                  amplificationEfficiencyMethod = NULL,
                                  amplificationEfficiency = NULL,
                                  amplificationEfficiencySE = NULL,
                                  detectionLimit = NULL,
                                  dyeId,
                                  sequences = NULL,
                                  commercialAssay = NULL) {
              self$id <- id
              self$description <- description
              self$documentation <- documentation
              self$xRef <- xRef
              self$type <- type
              self$amplificationEfficiencyMethod <- amplificationEfficiencyMethod
              self$amplificationEfficiency <- amplificationEfficiency
              self$amplificationEfficiencySE <- amplificationEfficiencySE
              self$detectionLimit <- detectionLimit
              self$dyeId <- dyeId
              self$sequences <- sequences
              self$commercialAssay <- commercialAssay
            }
          ),
          private = list(
            .id = NULL,
            .description = NULL,
            .documentation = NULL,
            .xRef = NULL,
            .type = NULL,
            .amplificationEfficiencyMethod = NULL,
            .amplificationEfficiency = NULL,
            .amplificationEfficiencySE = NULL,
            .detectionLimit = NULL,
            .dyeId = NULL,
            .sequences = NULL,
            .commercialAssay = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            description = function(description) {
              if (missing(description))
                return(private$.description)
              assertString(description, null.ok = TRUE)
              private$.description <- description
            },
            documentation = function(documentation) {
              if (missing(documentation))
                return(private$.documentation)
              assertList(documentation, "idReferencesType", unique = TRUE, null.ok = TRUE)
              private$.documentation <- documentation
            },
            xRef = function(xRef) {
              if (missing(xRef))
                return(private$.xRef)
              assertList(xRef, "xRefType", unique = TRUE, null.ok = TRUE)
              private$.xRef <- xRef
            },
            type = function(type) {
              if (missing(type))
                return(private$.type)
              assertR6(type, "targetTypeType")
              private$.type <- type
            },
            amplificationEfficiencyMethod =
              function(amplificationEfficiencyMethod) {
                if (missing(amplificationEfficiencyMethod))
                  return(private$.amplificationEfficiencyMethod)
                assertString(amplificationEfficiencyMethod, null.ok = TRUE)
                private$.amplificationEfficiencyMethod <- amplificationEfficiencyMethod
              },
            amplificationEfficiency = function(amplificationEfficiency) {
              if (missing(amplificationEfficiency))
                return(private$.amplificationEfficiency)
              assertNumber(amplificationEfficiency, null.ok = TRUE)
              private$.amplificationEfficiency <- amplificationEfficiency
            },
            amplificationEfficiencySE = function(amplificationEfficiencySE) {
              if (missing(amplificationEfficiencySE))
                return(private$.amplificationEfficiencySE)
              assertNumber(amplificationEfficiencySE, null.ok = TRUE)
              private$.amplificationEfficiencySE <- amplificationEfficiencySE
            },
            detectionLimit = function(detectionLimit) {
              if (missing(detectionLimit))
                return(private$.detectionLimit)
              assertNumber(detectionLimit, null.ok = TRUE)
              private$.detectionLimit <- detectionLimit
            },
            dyeId = function(dyeId) {
              if (missing(dyeId))
                return(private$.dyeId)
              assertR6(dyeId, "idReferencesType")
              private$.dyeId <- dyeId
            },
            sequences = function(sequences) {
              if (missing(sequences))
                return(private$.sequences)
              assertR6(sequences, "sequencesType", null.ok = TRUE)
              private$.sequences <- sequences
            },
            commercialAssay = function(commercialAssay) {
              if (missing(commercialAssay))
                return(private$.commercialAssay)
              assertR6(commercialAssay, "commercialAssayType", null.ok = TRUE)
              private$.commercialAssay <- commercialAssay
            }
          ))

# adpsType ------------------------------------------------------------

#' adpsType R6 class.
#'
#' @details
#' Contains \code{matrix} of amplification data. Must have three columns: \describe{
#' \item{cyc}{PCR cycle at which data
#' point was collected (every cycle must have unique number).}
#' \item{tmp}{temperature in degrees Celsius at the time of measurement (optional).}
#' \item{fluor}{raw fluorescence intensity measured.}} Inherits:
#' \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{adpsType$new(fpoints)}
#'
#' @section Fields: \describe{
#'   \item{\code{fpoints}}{\link[checkmate]{assertMatrix}. Matrix with amplification data
#'   points.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
#' @examples
#' #cycles
#' cyc <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
#' 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
#' 34, 35, 36, 37, 38, 39, 40)
#' #fluorescence
#' fluo <- c(2.0172, 2.0131, 2.0035, 2, 2.0024, 2.0056, 2.0105, 2.0179,
#' 2.0272, 2.0488, 2.0922, 2.1925, 2.3937, 2.7499, 3.3072, 4.0966,
#' 5.0637, 6.0621, 7.0239, 7.8457, 8.5449, 9.1282, 9.6022, 9.9995,
#' 10.2657, 10.4989, 10.6813, 10.8209, 10.9158, 10.9668, 11.0053,
#' 11.0318, 11.0446, 11.044, 11.0052, 10.9671, 10.9365, 10.9199,
#' 10.897, 10.8316)
#' #temperature
#' temp <- c(55, 55, 55, 55, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55,
#' 55, 55, 55, 55, 55, 55, 55, 55, 56, 55, 55, 55, 55, 55, 55, 55,
#' 55, 55, 55, 55, 55, 55, 55, 55, 55)
#'
#' #combine all variables into a proper object
#' data <- data.frame(cyc = cyc, tmp = temp, fluor = fluo)
#'
#' #create adps object
#' adpsType$new(data)
#'
#' #create adps object without temperature data
#' adpsType$new(data[, -2])
adpsType <-
  R6Class("adpsType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(fpoints) {
              self$fpoints <- fpoints
            },
            .asXMLnodes = function(node.name) {
              ifelse("tmp" %in% colnames(private$.fpoints),
                     return(
                       private$.fpoints[, sprintf("<adp><cyc>%s</cyc><tmp>%s</tmp><fluor>%s</fluor></adp>",
                                                  cyc, tmp, fluor)] %>>%
                         paste0(collapse = "")
                     ),
                     return(
                       private$.fpoints[, sprintf("<adp><cyc>%s</cyc><fluor>%s</fluor></adp>",
                                                  cyc, fluor)] %>>%
                         paste0(collapse = "")
                     ))
            }
          ),
          private = list(
            .fpoints = NULL
          ),
          active = list(
            fpoints = function(fpoints) {
              if (missing(fpoints))
                return(private$.fpoints)
              assert(checkDataFrame(fpoints, types = c("numeric")))
              assert(
                length(setdiff(colnames(fpoints), c("cyc", "tmp", "fluor"))) == 0 ||
                  length(setdiff(colnames(fpoints), c("cyc", "fluor"))) == 0)
              if (!testDataTable(fpoints))
                fpoints <- data.table(fpoints)
              # # check for duplicate cycles. Occures in StepOne RDML files.
              # if (base::anyDuplicated(fpoints$cyc)) {
              #   fpoints <- fpoints[-base::duplicated(fpoints$cyc)]
              #   warning("Duplicate cycles removed")
              # }
              # check for duplicate cycles
              if (base::anyDuplicated(fpoints$cyc)) {
                warning("fpoints table contains duplicate cycles!")
              }
              setkey(fpoints, cyc)
              private$.fpoints <- fpoints
            }
          ))

# mdpsType ------------------------------------------------------------

#' mdpsType R6 class.
#'
#' Contains \code{matrix} of melting data points (single data points measured
#' during amplification).
#'
#' Columns: \describe{
#' \item{tmp}{(temperature in degrees Celsius at the time of measurement.
#' Every point must have unique value.}
#' \item{fluor}{fluorescence intensity measured without any correction
#' (including baselining).}}
#'
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{mdpsType$new(fpoints)}
#'
#'   @section Fields: \describe{
#' \item{\code{fpoints}}{\link[checkmate]{assertMatrix}. Matrix with amplification data points.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
mdpsType <-
  R6Class("mdpsType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(fpoints) {
              self$fpoints <- fpoints
            },
            .asXMLnodes = function(node.name) {
              private$.fpoints[, sprintf("<mdp><tmp>%s</tmp><fluor>%s</fluor></mdp>",
                                         tmp, fluor)] %>>%
                paste0(collapse = "")
            }
          ),
          private = list(
            .fpoints = NULL
          ),
          active = list(
            fpoints = function(fpoints) {
              if (missing(fpoints))
                return(private$.fpoints)
              assert(checkDataFrame(fpoints, types = c("numeric")))
              assert(length(setdiff(colnames(fpoints), c("tmp", "fluor"))) == 0)
              if (!testDataTable(fpoints))
                fpoints <- data.table(fpoints)
              # check for duplicate temperatures. Occures in StepOne RDML files.
              # if (base::anyDuplicated(fpoints$tmp)) {
              #   fpoints <- fpoints[-base::duplicated(fpoints$tmp)]
              #   warning("Duplicate temperatures. removed")
              # }
              # check for duplicate temperatures.
              if (base::anyDuplicated(fpoints$cyc)) {
                warning("fpoints table contains duplicate temperatures!")
              }
              setkey(fpoints, tmp)
              private$.fpoints <- fpoints
            }
          ))

# dataType ------------------------------------------------------------

#' dataType R6 class.
#'
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{dataType$new(tar, cq = NULL, excl = NULL,
#' adp = NULL, mdp = NULL, endPt = NULL, bgFluor = NULL, bgFluorSlp = NULL,
#' quantFluor = NULL)}
#'
#' @section Fields: \describe{
#' \item{\code{tar}}{\link{idReferencesType}.
#'   TargetID - A reference to a target.}
#'   \item{\code{cq}}{\link[checkmate]{checkNumber}.
#'   Calculated fractional PCR cycle used for downstream quantification.
#'   Negative values express following condition: Not Available: -1.0 .
#'   (can be NaN for BioRad Maestro compatibility)}
#'   \item{\code{excl}}{\link[checkmate]{checkString}. Excluded. If \code{excl}
#'   is present, this entry should not be evaluated. Do not set this element
#'   to \code{FALSE} if the entry is valid. Instead, leave the entire \code{excl}
#'   element out instead. It may contain a string with a reason for the exclusion.
#'   Several reasons for exclusion should be
#'   seperated by semicolons ";".}
#'   \item{\code{adp}}{\link{adpsType}.}
#'   \item{\code{mdp}}{\link{mdpsType}.}
#'   \item{\code{endPt}}{\link[checkmate]{checkNumber}}. Value of the endpoint measurement.
#'   \item{\code{bgFluor}}{\link[checkmate]{checkNumber}. Background
#'   fluorescence (the y-intercept of the baseline trend based on the estimated
#'   background fluorescence). }
#'   \item{\code{bgFluorSlp}}{\link[checkmate]{checkNumber}.
#'   Background fluorescence slope - The slope of the baseline trend based on
#'   the estimated background fluorescence. The element should be absent to
#'   indicate a slope of 0.0; If this element is present without the \code{bgFluor}
#'   element it should be ignored. }
#'   \item{\code{quantFluor}}{\link[checkmate]{checkNumber}. Quantification flourescence -
#'   The fluorescence value corresponding to the treshold line.} }
#'
#' @section Methods: \describe{
#' \item{\code{AsDataFrame(dp.type = "adp")}}{Represents amplification
#' (\preformatted{dp.type = "adp"}) or melting (\code{dp.type = "mdp"}) data
#' points as \code{data.frame}}
#' }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
dataType <-
  R6Class("dataType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(tar,
                                  cq = NULL,
                                  excl = NULL,
                                  adp = NULL,
                                  mdp = NULL,
                                  endPt = NULL,
                                  bgFluor = NULL,
                                  bgFluorSlp = NULL,
                                  quantFluor = NULL) {
              self$tar <- tar
              self$cq <- cq
              self$excl <- excl
              self$adp <- adp
              self$mdp <- mdp
              self$endPt <- endPt
              self$bgFluor <- bgFluor
              self$bgFluorSlp <- bgFluorSlp
              self$quantFluor <- quantFluor
            },
            GetFData = function(dp.type = "adp") {
              checkChoice(dp.type, c("adp", "mdp"))
              out <- self[[dp.type]]
              assert(checkClass(out, "adpsType"),
                     checkClass(out, "mdpsType"))
              ifelse(testClass(out, "adpsType"),
                     return(out$fpoints[, .(cyc, fluor)]),
                     return(out$fpoints[, .(tmp, fluor)]))
            }
          ),
          private = list(
            .tar = NULL,
            .cq = NULL,
            .excl = NULL,
            .adp = NULL,
            .mdp = NULL,
            .endPt = NULL,
            .bgFluor = NULL,
            .bgFluorSlp = NULL,
            .quantFluor = NULL
          ),
          active = list(
            tar = function(tar) {
              if (missing(tar))
                return(private$.tar)
              assertR6(tar, "idReferencesType")
              private$.tar <- tar
            },
            cq = function(cq) {
              if (missing(cq))
                return(private$.cq)
              assertNumber(cq, null.ok = TRUE, na.ok = TRUE)
              private$.cq <- cq
            },
            excl = function(excl) {
              if (missing(excl))
                return(private$.excl)
              assertString(excl, null.ok = TRUE)
              private$.excl <- excl
            },
            adp = function(adp) {
              if (missing(adp))
                return(private$.adp)
              assertR6(adp, "adpsType", null.ok = TRUE)
              private$.adp <- adp
            },
            mdp = function(mdp) {
              if (missing(mdp))
                return(private$.mdp)
              assertR6(mdp, "mdpsType", null.ok = TRUE)
              private$.mdp <- mdp
            },
            endPt = function(endPt) {
              if (missing(endPt))
                return(private$.endPt)
              assertNumber(endPt, null.ok = TRUE)
              private$.endPt <- endPt
            },
            bgFluor = function(bgFluor) {
              if (missing(bgFluor))
                return(private$.bgFluor)
              assertNumber(bgFluor, null.ok = TRUE)
              private$.bgFluor <- bgFluor
            },
            bgFluorSlp = function(bgFluorSlp) {
              if (missing(bgFluorSlp))
                return(private$.bgFluorSlp)
              assertNumber(bgFluorSlp, null.ok = TRUE)
              private$.bgFluorSlp <- bgFluorSlp
            },
            quantFluor = function(quantFluor) {
              if (missing(quantFluor))
                return(private$.quantFluor)
              assertNumber(quantFluor, null.ok = TRUE)
              private$.quantFluor <- quantFluor
            }
          ))

# reactType ------------------------------------------------------------

#' reactType R6 class.
#'
#' A reaction is an independent chemical reaction corresponding for example to a
#' well in a 96 well plate, a capillary in a rotor, a through-hole on an array,
#' etc. Inherits: \link{rdmlBaseType}.
#'
#' The ID of this reaction
#'
#' Schemas : \itemize{ \item rotor : assign IDs according to the position of the
#' sample on the rotor (1 for the 1st sample, 2 for the 2nd, ...) \item plate
#' (96/384/1536 well) : the IDs are assigned in a row-first/column-second
#' manner. For each row, the samples are numbered according to the increasing
#' column number. At the end of a row, the numbering starts at the first column
#' of the next row. An example for this type of plate can be found below :
#' \tabular{lllll}{ \tab 1  \tab 2  \tab 3 \tab ... \cr A   \tab 1  \tab 2  \tab
#' 3 \tab     \cr B   \tab 13 \tab 14 \tab   \tab     \cr ... \tab    \tab \tab
#' \tab    } or \tabular{lllll}{ \tab 1  \tab 2  \tab 3 \tab ... \cr 1 \tab 1
#' \tab 2  \tab 3 \tab     \cr 2   \tab 13 \tab 14 \tab   \tab     \cr ... \tab
#' \tab    \tab   \tab    }
#'
#' \item multi-array plate (BioTrove) : the IDs are assigned in a
#' row-first/column-second manner, ignoring the organisation of sub-arrays. For
#' each row, the samples are numbered according to the increasing column number.
#' At the end of a row, the the next row. An example for this type of plate can
#' be found below : todo... }
#'
#' @section Initialization: \preformatted{reactType$new(id, sample, data = NULL, pcrFormat = pcrFormatType$new(8, 12, labelFormatType$new("123"), labelFormatType$new("ABC")))}
#'
#'   @section Fields: \describe{
#'   \item{\code{id}}{\link{reactIdType}. See 'Details'.}
#'   \item{\code{sample}}{\link{idReferencesType}. SampleID - A reference to a
#'   sample.}
#'   \item{\code{data}}{\code{list} of \link{dataType}.}
#'   \item{\code{position}}{Human readable form of the \code{react id} (i.e. '13' -> 'B1')..}
#'   }
#'
#' @section Methods: \describe{\item{\code{AsDataFrame(dp.type =
#'   "adp")}}{Represents amplification (\code{dp.type = "adp"}) or melting
#'   (\code{dp.type = "mdp"}) data points of all targets as one
#'   \code{data.frame}} \item{\code{.recalcPosition(pcrformat)}}{Converts \code{react
#'   id} to the human readable form (i.e. '13' -> 'B1'). This converted value can be
#'   accessed by \code{position} field. \code{pcrFormat} is
#'   \code{pcrFormatType}. Currently, only 'ABC' and '123' are supported as
#'   labels. For '123' '123' the \code{Position} will look like 'r01c01', for
#' 'ABC' '123' it will be 'A01' and for '123' 'ABC' it will be 01A. 'ABC' 'ABC'
#' is not currently supported. Note that 'ABC' will result in loss of
#' information if the experiment contains more than 26 rows!}}
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
reactType <-
  R6Class("reactType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  sample,
                                  data = NULL,
                                  pcrFormat =
                                    pcrFormatType$new(8, 12,
                                                      labelFormatType$new("ABC"),
                                                      labelFormatType$new("123"))) {
              self$id <- id
              self$sample <- sample
              self$data <- list.names(data,
                                          .$tar$id)
              self$.recalcPosition(pcrFormat)
            },
            GetFData = function(dp.type = "adp",
                                   long.table = FALSE) {
              assertString(dp.type)
              assertFlag(long.table)
              out <-
                list.map(private$.data,
                         data ~ {
                           fdata <- data$GetFData(dp.type)
                           set(fdata, ,
                               "tar", data$tar$id)
                           fdata
                           }) %>>%
                rbindlist()
              ifelse(long.table,
                     return(out),
                     return(dcast(out,
                                  as.formula(sprintf("%s ~ tar",
                                                     colnames(out)[1])),
                                  value.var = "fluor")))
            },
            .recalcPosition = function(pcrFormat) {
              assertR6(pcrFormat, "pcrFormatType")
              private$calced.position <-
                if (pcrFormat$rowLabel$value == "ABC" && pcrFormat$columnLabel$value == "123") {
                  if (pcrFormat$rows > length(LETTERS)) {
                    stop("Too many rows for 'ABC' format")
                  } else {
                    sprintf("%s%02i",
                            LETTERS[(private$.id$id - 1) %/% pcrFormat$columns + 1],
                            as.integer((private$.id$id - 1) %% pcrFormat$columns + 1))
                  }
                } else if (pcrFormat$columnLabel$value == "ABC" && pcrFormat$rowLabel$value == "123") {
                  if (pcrFormat$columns > length(LETTERS)) {
                    stop("Too many columns for 'ABC' format")
                  } else {
                    sprintf("%02i%s",
                            as.integer((private$.id$id - 1) %/% pcrFormat$columns + 1),
                            LETTERS[(private$.id$id - 1) %% pcrFormat$columns + 1])
                  }
                } else  if (pcrFormat$rowLabel$value == "123" && pcrFormat$columnLabel$value == "123") {
                  sprintf("r%02ic%02i",
                          as.integer((private$.id$id - 1) %/% pcrFormat$columns + 1),
                          as.integer((private$.id$id - 1) %% pcrFormat$columns + 1))
                } else {
                  stop("Unsupported PCR format.")
                }
            }
          ),
          private = list(
            .id = NULL,
            .sample = NULL,
            .data = NULL,
            calced.position = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "reactIdType")
              private$.id <- id
            },
            sample = function(sample) {
              if (missing(sample))
                return(private$.sample)
              assertR6(sample, "idReferencesType")
              private$.sample <- sample
            },
            data = function(data) {
              if (missing(data))
                return(private$.data)
              assertList(data, "dataType", unique = TRUE, null.ok = TRUE)
              private$.data <- list.names(data,
                                          .$tar$id)
            },
            position = function() {
              private$calced.position
            }
          ))

# dataCollectionSoftwareType ------------------------------------------------------------

#' dataCollectionSoftwareType R6 class.
#'
#' Software name and version used to collect and analyze the data. Inherits:
#' \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{dataCollectionSoftwareType$new(name, version)}
#'
#'   @section Fields: \describe{
#' \item{\code{name}}{\link[checkmate]{checkString}.}
#' \item{\code{version}}{\link[checkmate]{checkString}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
#' @examples
#' dataCollectionSoftwareType$new(name = "ExampleSoft",
#'                                version = "1.0")
dataCollectionSoftwareType <-
  R6Class("dataCollectionSoftwareType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(name,
                                  version) {
              self$name <- name
              self$version <- version
            }
          ),
          private = list(
            .name = NULL,
            .version = NULL
          ),
          active = list(
            name = function(name) {
              if (missing(name))
                return(private$.name)
              assertString(name)
              private$.name <- name
            },
            version = function(version) {
              if (missing(version))
                return(private$.version)
              assertString(version)
              private$.version <- version
            }
          ))

# cqDetectionMethodType ------------------------------------------------------------

#' cqDetectionMethodType R6 class.
#'
#' The method used to determine the Cq value.
#' Can take values:
#' \describe{
#' \item{"automated threshold and baseline settings"}{}
#' \item{"manual threshold and baseline settings"}{}
#' \item{"second derivative maximum"}{}
#' \item{"other"}{}
#' }
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{cqDetectionMethodType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
cqDetectionMethodType <-
  R6Class("cqDetectionMethodType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("automated threshold and baseline settings",
                        "manual threshold and baseline settings",
                        "second derivative maximum",
                        "other")
          )
  )

# labelFormatType ------------------------------------------------------------

#' labelFormatType R6 class.
#'
#' Label used for \link{pcrFormatType}.
#' Can take values:
#' \describe{
#' \item{ABC}{}
#' \item{123}{}
#' \item{A1a1}{}
#' }
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{labelFormatType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
labelFormatType <-
  R6Class("labelFormatType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("ABC",
                        "123",
                        "A1a1")
          )
  )

# pcrFormatType ------------------------------------------------------------

#' pcrFormatType R6 class.
#'
#' The display format of the PCR, analogous to the the qPCR instrument run format.
#' Inherits: \link{rdmlBaseType}.
#'
#' Rotor formats always have 1 column; rows correspond to the number of places
#' in the rotor. Values for common formats are: \tabular{lllll}{ Format \tab
#' rows \tab columns \tab rowLabel \tab columnLabel \cr single-well \tab 1
#' \tab 1       \tab 123      \tab 123         \cr 48-well plate \tab 6    \tab
#' 8       \tab ABC      \tab 123         \cr 96-well plate \tab 8    \tab 12
#' \tab ABC      \tab 123         \cr 384-well plate \tab 16   \tab 24      \tab
#' ABC      \tab 123         \cr 1536-well plate \tab 32   \tab 48      \tab ABC
#' \tab 123         \cr 3072-well array \tab 32   \tab 96      \tab A1a1
#' \tab A1a1        \cr 5184-well chip \tab 72   \tab 72      \tab ABC      \tab
#' 123         \cr 32-well rotor \tab 32   \tab 1       \tab 123      \tab 123
#' \cr 72-well rotor \tab 72   \tab 1       \tab 123      \tab 123         \cr
#' 100-well rotor \tab 100  \tab 1       \tab 123      \tab 123         \cr free
#' format \tab -1   \tab 1       \tab 123      \tab 123 } If rows field has value -1,
#' the function will not try to reconstruct a plate and just display all run
#' data in a single column. If the columns field has value 1 then the function will
#' not display a column label.
#'
#' @section Initialization: \preformatted{pcrFormatType$new(rows, columns, rowLabel, columnLabel)}
#'
#'   @section Fields: \describe{
#' \item{\code{rows}}{\link[checkmate]{checkCount}.}
#' \item{\code{columns}}{\link[checkmate]{checkCount}.}
#' \item{\code{rowLabel}}{\link{labelFormatType}.}
#' \item{\code{columnLabel}}{\link{labelFormatType}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
pcrFormatType <-
  R6Class("pcrFormatType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(rows,
                                  columns,
                                  rowLabel,
                                  columnLabel) {
              self$rows <- rows
              self$columns <- columns
              self$rowLabel <- rowLabel
              self$columnLabel <- columnLabel
            }
          ),
          private = list(
            .rows = NULL,
            .columns = NULL,
            .rowLabel = NULL,
            .columnLabel = NULL
          ),
          active = list(
            rows = function(rows) {
              if (missing(rows))
                return(private$.rows)
              assertCount(rows)
              private$.rows <- rows
            },
            columns = function(columns) {
              if (missing(columns))
                return(private$.columns)
              assertCount(columns)
              private$.columns <- columns
            },
            rowLabel = function(rowLabel) {
              if (missing(rowLabel))
                return(private$.rowLabel)
              assertR6(rowLabel, "labelFormatType")
              private$.rowLabel <- rowLabel
            },
            columnLabel = function(columnLabel) {
              if (missing(columnLabel))
                return(private$.columnLabel)
              assertR6(columnLabel, "labelFormatType")
              private$.columnLabel <- columnLabel
            }
          ))

# runType ------------------------------------------------------------

#' runType R6 class.
#'
#' A run is a set of reactions performed in one "run", for example one plate,
#' one rotor, one array, one chip. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{runType$new(id, description = NULL,
#'   documentation = NULL, experimenter = NULL, instrument = NULL,
#'   dataCollectionSoftware = NULL, backgroundDeterminationMethod = NULL,
#'   cqDetectionMethod = NULL, thermalCyclingConditions = NULL, pcrFormat,
#'   runDate = NULL, react = NULL)}
#'
#' @section Fields: \describe{
#'  \item{\code{id}}{\link{idType}.}
#'  \item{\code{description}}{\link[checkmate]{checkString}.}
#'  \item{\code{documentation}}{\code{list} of \link{idReferencesType}.}
#'  \item{\code{experimenter}}{\code{list} of \link{idReferencesType}.}
#'  \item{\code{instrument}}{\link[checkmate]{checkString}. Description of the
#'   instrument used to aquire the data.}
#'  \item{\code{dataCollectionSoftware}}{\link{dataCollectionSoftwareType}.
#'   Description of the software used to analyze/collect the data.}
#'  \item{\code{backgroundDeterminationMethod}}{\link[checkmate]{checkString}.
#'   Description of method used to determine the background. }
#'  \item{\code{cqDetectionMethod}}{\link{cqDetectionMethodType}. Description of method
#'   used to calculate the quantification cycle. }
#'  \item{\code{thermalCyclingConditions}}{\link{idReferencesType}. The program
#'   used to aquire the data.}
#'  \item{\code{pcrFormat}}{\link{adpsType}.}
#'  \item{\code{runDate}}{\link{adpsType}. Time stamp of data acquisition.}
#'  \item{\code{react}}{\code{list} of \link{adpsType}.} }
#'
#' @section Methods: \describe{
#'  \item{\code{AsDataFrame(dp.type = "adp")}}{Represents amplification
#'  (\code{dp.type = "adp"}) or melting (\code{dp.type = "mdp"}) data
#'  points as \code{data.frame}}}
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
runType <-
  R6Class("runType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  description = NULL,
                                  documentation = NULL,
                                  experimenter = NULL,
                                  instrument = NULL,
                                  dataCollectionSoftware = NULL,
                                  backgroundDeterminationMethod = NULL,
                                  cqDetectionMethod = NULL,
                                  thermalCyclingConditions = NULL,
                                  pcrFormat,
                                  runDate = NULL,
                                  react = NULL) {
              self$id <- id
              self$description <- description
              self$documentation <- documentation
              self$experimenter <- experimenter
              self$instrument <- instrument
              self$dataCollectionSoftware <- dataCollectionSoftware
              self$backgroundDeterminationMethod <- backgroundDeterminationMethod
              self$cqDetectionMethod <- cqDetectionMethod
              self$thermalCyclingConditions <- thermalCyclingConditions
              self$pcrFormat <- pcrFormat
              self$runDate <- runDate
              self$react <- list.names(react,
                                           .$id$id)
              self$UpdateReactsPosition()
            },
            GetFData = function(dp.type = "adp",
                                long.table = FALSE) {
              assertString(dp.type)
              assertFlag(long.table)

              out <-
                list.map(private$.react,
                         react ~ {
                           fdata <- react$GetFData(
                             dp.type = dp.type,
                             long.table = TRUE)
                           set(fdata, ,
                               c("react.id", "react.sample"),
                               list(react$id$id,
                                    react$sample$id))
                           fdata
                         }) %>>%
                rbindlist()

              ifelse(long.table == FALSE,
                     return(dcast(out,
                                  as.formula(sprintf("%s ~ react.id + react.sample + tar",
                                                     colnames(out)[1])),
                                  value.var = "fluor")),
                     return(out)
              )
            },
            UpdateReactsPosition = function() {
              list.iter(self$react,
                        react ~ react$.recalcPosition(self$pcrFormat))
            }
          ),
          private = list(
            .id = NULL,
            .description = NULL,
            .documentation = NULL,
            .experimenter = NULL,
            .instrument = NULL,
            .dataCollectionSoftware = NULL,
            .backgroundDeterminationMethod = NULL,
            .cqDetectionMethod = NULL,
            .thermalCyclingConditions = NULL,
            .pcrFormat = NULL,
            .runDate = NULL,
            .react = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            description = function(description) {
              if (missing(description))
                return(private$.description)
              assertString(description, null.ok = TRUE)
              private$.description <- description
            },
            documentation = function(documentation) {
              if (missing(documentation))
                return(private$.documentation)
              assertList(documentation, "idReferencesType", unique = TRUE, null.ok = TRUE)
              private$.documentation <- documentation
            },
            experimenter = function(experimenter) {
              if (missing(experimenter))
                return(private$.experimenter)
              assertList(experimenter, "idReferencesType", unique = TRUE, null.ok = TRUE)
              private$.experimenter <- experimenter
            },
            instrument = function(instrument) {
              if (missing(instrument))
                return(private$.instrument)
              assertString(instrument, null.ok = TRUE)
              private$.instrument <- instrument
            },
            dataCollectionSoftware = function(dataCollectionSoftware) {
              if (missing(dataCollectionSoftware))
                return(private$.dataCollectionSoftware)
              assertR6(dataCollectionSoftware, "dataCollectionSoftwareType", null.ok = TRUE)
              private$.dataCollectionSoftware <- dataCollectionSoftware
            },
            backgroundDeterminationMethod = function(backgroundDeterminationMethod) {
              if (missing(backgroundDeterminationMethod))
                return(private$.backgroundDeterminationMethod)
              assertString(backgroundDeterminationMethod, null.ok = TRUE)
              private$.backgroundDeterminationMethod <- backgroundDeterminationMethod
            },
            cqDetectionMethod = function(cqDetectionMethod) {
              if (missing(cqDetectionMethod))
                return(private$.cqDetectionMethod)
              assertR6(cqDetectionMethod, "cqDetectionMethodType", null.ok = TRUE)
              private$.cqDetectionMethod <- cqDetectionMethod
            },
            thermalCyclingConditions = function(thermalCyclingConditions) {
              if (missing(thermalCyclingConditions))
                return(private$.thermalCyclingConditions)
              assertR6(thermalCyclingConditions, "idReferencesType", null.ok = TRUE)
              private$.thermalCyclingConditions <- thermalCyclingConditions
            },
            pcrFormat = function(pcrFormat) {
              if (missing(pcrFormat))
                return(private$.pcrFormat)
              assertR6(pcrFormat, "pcrFormatType")
              private$.pcrFormat <- pcrFormat
              self$UpdateReactsPosition()
            },
            runDate = function(runDate) {
              if (missing(runDate))
                return(private$.runDate)
              assert(checkDateTime(runDate)) # date time
              private$.runDate <- runDate
            },
            react = function(react) {
              if (missing(react))
                return(private$.react)
              assert(checkNull(react),
                     checkList(react, "reactType", unique = TRUE))
              private$.react <- list.names(react,
                                           .$id$id)
              # check for duplicate reacts names. Occures in StepOne RDML files.
              if (anyDuplicated(names(private$.react)) != FALSE) {
                private$.react <- private$.react[unique(names(private$.react))]
                warning("Duplicate reacts removed")
              }
            }
          ))

# experimentType ------------------------------------------------------------

#' experimentType R6 class.
#'
#' A qPCR experiment. It may contain several runs (\link{runType}). Inherits:
#' \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{experimentType$new(id, description = NULL,
#'   documentation = NULL, run = NULL)}
#'
#'   @section Fields: \describe{
#' \item{\code{id}}{\link{idType}.}
#' \item{\code{description}}{\link[checkmate]{checkString}.}
#' \item{\code{documentation}}{\code{list} of \link{idReferencesType}.}
#' \item{\code{run}}{\code{list} of \link{runType}.}
#' }
#'
#' @section Methods: \describe{\item{\code{AsDataFrame(dp.type = "adp",
#'   long.table = FALSE)}}{Represents amplification (\code{dp.type = "adp"}) or
#'   melting (\code{dp.type = "mdp"}) data points as \code{data.frame}.
#'   \code{long.table = TRUE} means that fluorescence data for all runs and
#'   reacts will be at one collumn.}}
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
experimentType <-
  R6Class("experimentType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  description = NULL,
                                  documentation = NULL,
                                  run = NULL) {
              self$id <- id
              self$description <- description
              self$documentation <- documentation
              self$run <- list.names(run,
                                         .$id$id)
            },
            GetFData = function(dp.type = "adp",
                                long.table = FALSE) {
              assertString(dp.type)
              assertFlag(long.table)

              out <-
                list.map(private$.run,
                         run ~ {
                           fdata <- run$GetFData(
                             dp.type = dp.type,
                             long.table = TRUE)
                           set(fdata, ,
                               "run", run$id$id)
                           fdata
                         }) %>>%
                rbindlist()

              ifelse(long.table == FALSE,
                     return(dcast(out,
                                  as.formula(sprintf("%s ~ react.id + react.sample + tar + run",
                                                     colnames(out)[1])),
                                  value.var = "fluor")),
                     return(out)
              )
            }
          ),
          private = list(
            .id = NULL,
            .description = NULL,
            .documentation = NULL,
            .run = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            description = function(description) {
              if (missing(description))
                return(private$.description)
              assertString(description, null.ok = TRUE)
              private$.description <- description
            },
            documentation = function(documentation) {
              if (missing(documentation))
                return(private$.documentation)
              assertList(documentation, "idReferencesType", unique = TRUE, null.ok = TRUE)
              private$.documentation <- documentation
            },
            run = function(run) {
              if (missing(run))
                return(private$.run)
              assertList(run, "runType", unique = TRUE, null.ok = TRUE)
              private$.run <- list.names(run,
                                         .$id$id)
            }
          ))

# lidOpenType ------------------------------------------------------------

#' lidOpenType R6 class.
#'
#' This step waits for the user to open the lid and continues afterwards. It
#' allows to stop the program and to wait for the user to add for example
#' enzymes and continue the program afterwards. The temperature of the previous
#' step is maintained. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{lidOpenType$new()}
#'
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
lidOpenType <-
  R6Class("lidOpenType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function() {
            }
          ),
          private = list(
          ))

# pauseType ------------------------------------------------------------

#' pauseType R6 class.
#'
#' This step allows to pause at a certain temperature. It is typically the last
#' step in an amplification protocol. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{pauseType$new(temperature)}
#'
#' @section Fields: \describe{ \item{\code{temperature}}{\link[checkmate]{checkNumber}.
#'   The temperature in degrees Celsius maintained during the pause.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
pauseType <-
  R6Class("pauseType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(temperature) {
              self$temperature <- temperature
            }
          ),
          private = list(
            .temperature = NULL
          ),
          active = list(
            temperature = function(temperature) {
              if (missing(temperature))
                return(private$.temperature)
              assertNumber(temperature)
              private$.temperature <- temperature
            }
          ))


# loopType ------------------------------------------------------------

#' loopType R6 class.
#'
#' This step allows to form a loop or to exclude some steps. It allows to jump
#' to a certain "goto" step for "repeat" times. If the "goto" step is outside of
#' the loop range, it must have "repeat" value "0". Inherits:
#' \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{loopType$new(goto, repeat.n)}
#'
#' @section Fields: \describe{ \item{\code{goto}}{\link[checkmate]{assertCount}.  The
#'   step to go to to form the loop.}
#' \item{\code{repeat.n}}{\link[checkmate]{assertCount}. Determines how many times the loop is
#'   repeated. The first run through the loop is counted as 0, the last loop is
#'   "repeat" - 1.}}
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
loopType <-
  R6Class("loopType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(goto,
                                  repeat.n) {
              self$goto <- goto
              self$repeat.n <- repeat.n
            }
          ),
          private = list(
            .goto = NULL,
            .repeat = NULL
          ),
          active = list(
            goto = function(goto) {
              if (missing(goto))
                return(private$.goto)
              assertCount(goto)
              private$.goto <- goto
            },
            repeat.n = function(repeat.n) {
              if (missing(repeat.n))
                return(private$.repeat)
              assertCount(repeat.n)
              private$.repeat <- repeat.n
            }
          ))

# measureType ------------------------------------------------------------

#' measureType R6 class.
#'
#' Can take values:
#' \describe{
#' \item{real time}{}
#' \item{meltcurve}{}
#' }
#' Inherits: \link{enumType}.
#'
#' @section Initialization: \preformatted{measureType$new(value)}
#'
#'   @section Fields: \describe{
#' \item{\code{value}}{\link[checkmate]{checkString}.}
#' }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
measureType <-
  R6Class("measureType",
          # class = FALSE,
          inherit = enumType,
          private = list(
            .levels = c("real time",
                        "meltcurve")
          )
  )

# baseTemperatureType ------------------------------------------------------------

#' baseTemperatureType R6 class.
#'
#' Parent class for inner usage. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{baseTemperatureType$new(duration,
#'   temperatureChange = NULL, durationChange = NULL, measure = NULL, ramp =
#'   NULL)}
#'
#' @section Fields: \describe{
#'   \item{\code{duration}}{\link[checkmate]{checkCount}. Duration of this
#'   step in seconds.}
#'   \item{\code{temperatureChange}}{\link[checkmate]{checkNumber}. Change
#'   of the temperature between two consecutive cycles: actual temperature
#'   = temperature + (temperatureChange * cycle counter)}
#'   \item{\code{durationChange}}{\link[checkmate]{checkCount}. Change of the
#'   duration between two consecutive cycles: actual duration = duration +
#'   (durationChange * cycle counter)}
#'   \item{\code{measure}}{\link{measureType}. Indicates to make a measurement
#'   and store it as meltcurve or real-time data.}
#'   \item{\code{ramp}}{\link[checkmate]{checkNumber}. Allowed temperature
#'   change between two consecutive cycles in degrees Celsius per second. If unstated,
#'   the maximal change rate is assumed.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
baseTemperatureType <-
  R6Class("baseTemperatureType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(duration,
                                  temperatureChange = NULL,
                                  durationChange = NULL,
                                  measure = NULL,
                                  ramp = NULL) {
              self$duration <- duration
              self$temperatureChange <- temperatureChange
              self$durationChange <- durationChange
              self$measure <- measure
              self$ramp <- ramp
            }
          ),
          private = list(
            .duration = NULL,
            .temperatureChange = NULL,
            .durationChange = NULL,
            .measure = NULL,
            .ramp = NULL
          ),
          active = list(
            duration = function(duration) {
              if (missing(duration))
                return(private$.duration)
              assertCount(duration)
              private$.duration <- duration
            },
            temperatureChange = function(temperatureChange) {
              if (missing(temperatureChange))
                return(private$.temperatureChange)
              assertNumber(temperatureChange, null.ok = TRUE)
              private$.temperatureChange <- temperatureChange
            },
            durationChange = function(durationChange) {
              if (missing(durationChange))
                return(private$.durationChange)
              assertCount(durationChange, null.ok = TRUE)
              private$.durationChange <- durationChange
            },
            measure = function(measure) {
              if (missing(measure))
                return(private$.measure)
              assertR6(measure, "measureType", null.ok = TRUE)
              private$.measure <- measure
            },
            ramp = function(ramp) {
              if (missing(ramp))
                return(private$.ramp)
              assertNumber(ramp, null.ok = TRUE)
              private$.ramp <- ramp
            }
          ))

# temperatureType ------------------------------------------------------------

#' temperatureType R6 class.
#'
#' This step keeps a constant temperature on the heat block. Inherits:
#' \link{baseTemperatureType}.
#'
#' @section Initialization: \preformatted{temperatureType$new(temperature, ...)}
#'
#' @section Fields: \describe{ \item{\code{temperature}}{\link[checkmate]{checkNumber}.
#'   The temperature of the step in  degrees Celsius.}
#' \item{\code{...}}{ Params of parent class \link{baseTemperatureType}.}
#' }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
temperatureType <-
  R6Class("temperatureType",
          # class = FALSE,
          inherit = baseTemperatureType,
          public = list(
            initialize = function(temperature, ...) {
              self$temperature <- temperature
              super$initialize(...)
            }
          ),
          private = list(
            .temperature = NULL
          ),
          active = list(
            temperature = function(temperature) {
              if (missing(temperature))
                return(private$.temperature)
              assertNumber(temperature)
              private$.temperature <- temperature
            }
          ))

# gradientType ------------------------------------------------------------

#' gradientType R6 class.
#'
#' Details of the temperature gradient across the PCR block. Inherits:
#' \link{baseTemperatureType}.
#'
#' @section Initialization: \preformatted{gradientType$new(highTemperature,
#'   lowTemperature, ...)}
#'
#' @section Fields: \describe{
#'   \item{\code{highTemperature}}{\link[checkmate]{checkNumber}. The highest temperature of
#'   the gradient in degrees Celsius.}
#'   \item{\code{lowTemperature}}{\link[checkmate]{checkNumber}. The lowest temperature of
#'   the gradient in degrees Celsius.}
#' \item{\code{...}}{ Params of parent class \link{baseTemperatureType}. }}
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
gradientType <-
  R6Class("gradientType",
          # class = FALSE,
          inherit = baseTemperatureType,
          public = list(
            initialize = function(highTemperature,
                                  lowTemperature,
                                  ...) {
              self$highTemperature <- highTemperature
              self$lowTemperature <- lowTemperature
              super$initialize(...)
            }
          ),
          private = list(
            .highTemperature = NULL,
            .lowTemperature = NULL
          ),
          active = list(
            highTemperature = function(highTemperature) {
              if (missing(highTemperature))
                return(private$.highTemperature)
              assertNumber(highTemperature)
              private$.highTemperature <- highTemperature
            },
            lowTemperature = function(lowTemperature) {
              if (missing(lowTemperature))
                return(private$.lowTemperature)
              assertNumber(lowTemperature)
              private$.lowTemperature <- lowTemperature
            }
          ))


# stepType ------------------------------------------------------------

#' stepType R6 class.
#'
#' Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{stepType$new(nr, description = NULL,
#'   temperature = NULL, gradient = NULL, loop = NULL, pause = NULL, lidOpen =
#'   NULL)}
#'
#' @section Fields: \describe{ \item{\code{nr}}{\link[checkmate]{checkCount}. The
#'   incremental number of the step. First step should have value 1. The increment
#'   between steps should be constant and equivalent to 1.}
#'   \item{\code{description}}{\link[checkmate]{checkString}.}
#'   \item{\code{temperature}}{\link{temperatureType}.}
#'   \item{\code{gradient}}{\link{gradientType}.}
#'   \item{\code{loop}}{\link{loopType}.} \item{\code{pause}}{\link{pauseType}.}
#'   \item{\code{lidOpen}}{\link{lidOpenType}.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
stepType <-
  R6Class("stepType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(nr,
                                  description = NULL,
                                  temperature = NULL,
                                  gradient = NULL,
                                  loop = NULL,
                                  pause = NULL,
                                  lidOpen = NULL) {
              self$nr <- nr
              self$description <- description
              self$temperature <- temperature
              self$gradient <- gradient
              self$loop <- loop
              self$pause <- pause
              self$lidOpen <- lidOpen
            }
          ),
          private = list(
            .nr = NULL,
            .description = NULL,
            .temperature = NULL,
            .gradient = NULL,
            .loop = NULL,
            .pause = NULL,
            .lidOpen = NULL
          ),
          active = list(
            nr = function(nr) {
              if (missing(nr))
                return(private$.nr)
              assertCount(nr)
              private$.nr <- nr
            },
            description = function(description) {
              if (missing(description))
                return(private$.description)
              assertString(description, null.ok = TRUE)
              private$.description <- description
            },
            temperature = function(temperature) {
              if (missing(temperature))
                return(private$.temperature)
              assertR6(temperature, "temperatureType", null.ok = TRUE)
              private$.temperature <- temperature
            },
            gradient = function(gradient) {
              if (missing(gradient))
                return(private$.gradient)
              assertR6(gradient, "gradientType", null.ok = TRUE)
              private$.gradient <- gradient
            },
            loop = function(loop) {
              if (missing(loop))
                return(private$.loop)
              assertR6(loop, "loopType", null.ok = TRUE)
              private$.loop <- loop
            },
            pause = function(pause) {
              if (missing(pause))
                return(private$.pause)
              assertR6(pause, "pauseType", null.ok = TRUE)
              private$.pause <- pause
            },
            lidOpen = function(lidOpen) {
              if (missing(lidOpen))
                return(private$.lidOpen)
              assertR6(lidOpen, "lidOpenType", null.ok = TRUE)
              private$.lidOpen <- lidOpen
            }
          ))

# thermalCyclingConditionsType ------------------------------------------------------------

#' thermalCyclingConditionsType R6 class.
#'
#' A cycling program for PCR or to amplify cDNA. Inherits: \link{rdmlBaseType}.
#'
#' @section Initialization: \preformatted{thermalCyclingConditionsType$new(id,
#'   description = NULL, documentation = NULL, lidTemperature = NULL,
#'   experimenter = NULL, step)}
#'
#' @section Fields: \describe{ \item{\code{id}}{\link{idType}.}
#'   \item{\code{description}}{\link[checkmate]{checkString}.}
#'   \item{\code{documentation}}{\code{list} of \link{idReferencesType}.}
#'   \item{\code{lidTemperature}}{\link[checkmate]{checkNumber}. The temperature in
#'   degrees Celsius of the lid during cycling. }
#'   \item{\code{experimenter}}{\code{list} of \link{idReferencesType}.
#'   Reference to the person who made or uses this protocol. }
#'   \item{\code{step}}{\code{list} of \link{stepType}. The steps a protocol
#'   runs through to amplify DNA.}
#'   }
#'
#' @docType class
#' @format An \code{\link{R6Class}} generator object.
#' @export
thermalCyclingConditionsType <-
  R6Class("thermalCyclingConditionsType",
          # class = FALSE,
          inherit = rdmlBaseType,
          public = list(
            initialize = function(id,
                                  description = NULL,
                                  documentation = NULL,
                                  lidTemperature = NULL,
                                  experimenter = NULL,
                                  step) {
              self$id <- id
              self$description <- description
              self$documentation <- documentation
              self$lidTemperature <- lidTemperature
              self$experimenter <- experimenter
              self$step <- list.names(step,
                                          .$nr)
            }
          ),
          private = list(
            .id = NULL,
            .description = NULL,
            .documentation = NULL,
            .lidTemperature = NULL,
            .experimenter = NULL,
            .step = NULL
          ),
          active = list(
            id = function(id) {
              if (missing(id))
                return(private$.id)
              assertR6(id, "idType")
              private$.id <- id
            },
            description = function(description) {
              if (missing(description))
                return(private$.description)
              assertString(description, null.ok = TRUE)
              private$.description <- description
            },
            documentation = function(documentation) {
              if (missing(documentation))
                return(private$.documentation)
              assertList(documentation, "idReferencesType", unique = TRUE, null.ok = TRUE)
              private$.documentation <- documentation
            },
            lidTemperature = function(lidTemperature) {
              if (missing(lidTemperature))
                return(private$.lidTemperature)
              assertNumber(lidTemperature, null.ok = TRUE)
              private$.lidTemperature <- lidTemperature
            },
            experimenter = function(experimenter) {
              if (missing(experimenter))
                return(private$.experimenter)
              assertList(experimenter, "idReferencesType", unique = TRUE, null.ok = TRUE)
              private$.experimenter <- experimenter
            },
            step = function(step) {
              if (missing(step))
                return(private$.step)
              assertList(step, "stepType", unique = TRUE, null.ok = TRUE)
              private$.step <- list.names(step,
                                          .$nr)
            }
          ))
kablag/RDML documentation built on Oct. 20, 2022, 5:47 a.m.