diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 38a9bb2d..ed286ceb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,19 +1,17 @@ # Contribution to {sdtm.oak} -This outlines how to propose a change to the {sdtm.oak} package. For more detailed info -about contributing to {sdtm.oak}, and other [pharmaverse -packages](https://pharmaverse.org/), please see the [development process -guide](https://pharmaverse.github.io/sdtm.oak/CONTRIBUTING.html) -as well as other Developer Guides in the Articles section of the [{admiral} -website](https://pharmaverse.github.io/admiral/index.html) +This outlines how to propose a change to the sdtm.oak package. For more detailed info about contributing to {sdtm.oak}, and other [pharmaverse packages](https://pharmaverse.org/), please see the [Contribution Guide](https://pharmaverse.github.io/admiral/CONTRIBUTING.html) as well as other Developer Guides in the Articles section of the [{admiraldev} website](https://pharmaverse.github.io/admiraldev/). + +Please note that we try to align to best practices used in other R packages' development processes - so veteran developers should be familiar with our processes. However, we do deviate slightly from some best practices and we advise all new contributors to review our package documentation accordingly. + # Basics - * For each new contribution, the user creates an issue on the issue tab on [GitHub](https://github.com/pharmaverse/oak/issues) to put it in our backlog. + * For each new contribution, the user creates an issue on the issue tab on [GitHub](https://github.com/pharmaverse/sdtm.oak/issues) to put it in our backlog. The issues can range from bug identification and/or fixes, enhancements to functions, documentation, tests or new features. * We advise you to contact us when an -[issue](https://github.com/pharmaverse/oak/issues) is created via +[issue](https://github.com/pharmaverse/sdtm.oak/issues) is created via [Slack](https://oakgarden.slack.com) (If you don't have access, use this [link](https://join.slack.com/t/oakgarden/shared_invite/zt-204sf8w5c-Vxl71cI~WAYhsMLbHGxeMw) to join). We can discuss details or align expectations if you are not familiar @@ -21,126 +19,4 @@ with the `{sdtm.oak}` philosophy and programming strategy. The team will try to review the issues within the next backlog meeting and give some initial feedback. Since we are not a 100% fully resourced software development team it might be that some issues will take longer to respond to depending on the amount -of overall issues. - - * Familiarize yourself with our [programming strategy](https://pharmaverse.github.io/admiraldev/articles/programming_strategy.html), guidance for [GitHub usage](https://pharmaverse.github.io/admiraldev/articles/git_usage.html) and [unit testing](https://pharmaverse.github.io/admiraldev/articles/unit_test_guidance.html). - - * All newly [created issues](https://github.com/pharmaverse/oak/issues) will be -reviewed within the next backlog meeting and the creator will receive an -initial feedback via a comment. Someone from the core development team will -then triage new issues by assigning the appropriate labels (such as “user -request” so we can easily identify new requests). - - * Issues are meant to be taken on by users from the Pharma programming -community. - -# Contribution Model - - -## Type 1 Contribution with Code: - - * First, the user creates an issue or comments on an existing issue to notify -that they’d like to contribute code. - * Follow our development process step-by-step guide. - * We advise to contact an `{sdtm.oak}` core development team directly via [Slack](https://app.slack.com/client/T028PB489D3/C02M8KN8269) before submitting code for complex functionality. - - -## Type 2 Contribution without Code: - - * User creates an issue and ideally contacts an `{sdtm.oak}` team member via [Slack](https://oakgarden.slack.com). - * The `{sdtm.oak}` core development team will contact the issue creator as soon -as possible to discuss further details. - - -See [Contribution to {admiral}](https://pharmaverse.github.io/admiral/articles/contribution_model.html) for additional details. - -# Containers guideline - -This guideline will walk you through the process of setting up and using the Oak image in both GitHub Codespaces and Visual Studio Code's devcontainer functionality. - -## Use GitHub Codespaces - -1. **Prerequisites** : - -* Have a GitHub account. -* The repository you want to open in Codespaces must be under your account or you must have appropriate permissions. - -2. **Open the Repository** : - -* Navigate to the desired GitHub repository on GitHub's website. - -3. **Start Codespaces** : - -* Click on the "Code" button (it has a green color most of the times). -* In the dropdown, you'll find an option named "Open with Codespaces". Click on it. - -4. **Choose or Create a Codespace** : - -* If you've already created a Codespace for this repository, you'll see it listed. You can click on it to open. -* If not, click on the "+ New codespace" button. - -5. **Configure the Environment (If needed)** : - -* Depending on the repository, you might have a `.devcontainer` folder which will define the environment. GitHub Codespaces will use the settings defined here to set up the environment. -* If you need to customize or install additional tools, you can do so once the Codespace is launched. - -6. **Use Codespaces** : - -* Once your environment is set up, you'll have an instance of Visual Studio Code running in your browser, connected to the repository. -* You can now edit, run, and debug your code just like you would in a local environment. - -7. **Close the Codespace** : - -* When you're done, you can close the browser tab/window. -* Remember, you'll be billed (if you're on a paid plan) for the time your Codespace is running, so it's a good idea to stop or delete it if you're not using it. You can do this from the Codespaces tab in your GitHub repository. - -## Use Visual Code devcontainer - -1. **Prerequisites** : - -* Have a Docker and VS Code installed -* linux/arm64 is supported only for R 4.3 - -2. **Install devcontainer extension** : - -* In the left sidebar, click on the extensions icon (it looks like square blocks or a Lego piece). -* In the search bar, type "Dev Containers" to search for the extension. -* From the search results, locate the "Dev Containers" extension provided by Microsoft and click the 'Install' button. - -3. **Open in Container** : - -* In VS Code, use the command palette (`Ctrl+Shift+P` or `Cmd+Shift+P` on macOS) and run the "Dev Containers: Rebuild and Reopen in Container" command. VS Code will then set up the devcontainer using the Oak image. - -4. **Using the Devcontainer** : - -* Once the environment is set up, you can start coding in VS Code as if you were in a local environment, but with the capabilities and tools provided by the Oak image. - -## Use docker run - -1. **Prerequisites** : - -* Have a docker installed - -2. **Example command** : - -``` -docker run --rm -d \ - --name oak-dev \ - -p 127.0.0.1:8888:8787 \ - -e ROOT=true -e DISABLE_AUTH=true \ - -v "$(pwd):/home/rstudio/oak" \ - ghcr.io/pharmaverse/sdtm.oak-4.3:latest -``` - -This command is used to start a new container from a Docker image. Here's a breakdown of the parameters used: - -* docker run: This is the basic command to start a new container from a Docker image. -* --rm: This option ensures that the container is removed automatically when it's stopped. This is useful if you don’t want to keep the container around once you're done with it, helping to save storage space. -* -d: This option runs the container in detached mode, which means the container runs in the background and doesn't attach to your command line session. -* --name oak-dev: This assigns the name oak-dev to the container. Naming your containers makes them easier to identify and manage. -* -p 127.0.0.1:8888:8787: This maps port 8787 inside the container to port 8888 on the host machine, and binds it to the localhost IP (127.0.0.1). The format is -p ::. This means any traffic directed at port 8888 on your host machine will be forwarded to port 8787 in the container. -* -e ROOT=true -e DISABLE_AUTH=true: These are environment variables being passed into the container. -e denotes that an environment variable is being set. In this case, two environment variables are being set: - * ROOT=true: This likely grants root permissions inside the container. - * DISABLE_AUTH=true: This likely disables authentication when opening RStudio. -* -v "$(pwd):/home/rstudio/oak": This maps a volume (essentially a directory) from the host machine into the container. The $(pwd) is a command that returns the current directory you're in on the host machine. This current directory is then mapped to /home/rstudio/oak inside the container. This is useful for sharing files between your host machine and the container. -* ghcr.io/pharmaverse/sdtm.oak-4.3:latest: This is the name of the Docker image that the container will be created from. It's pulled from the GitHub Container Registry (ghcr.io) and the image belongs to the pharmaverse repository. The image name is sdtm.oak-4.3 and the tag being used is latest. There are image for three versions available. +of overall issues. \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index 60c5e227..bd5e53b6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -3,17 +3,23 @@ Type: Package Title: SDTM Data Transformation Engine Version: 0.0.0.9001 Authors@R: c( - person("Omar", "Garcia", email = "ogcalderon@cdisc.org", role = c("aut", "cre")), - person("Rammprasad", "Ganapathy", role = "aut"), + person("Rammprasad", "Ganapathy", role = c("aut", "cre"), + email = "ganapathy.rammprasad@gene.com"), + person("Adam", "Forys", role = "aut"), + person("Edgar", "Manukyan", role = "aut"), + person("Rosemary", "Li", role = "aut"), + person("Preetesh", "Parikh", role = "aut"), + person("Lisa", "Houterloot", role = "aut"), + person("Yogesh", "Gupta", role = "aut"), + person("Omar", "Garcia", email = "ogcalderon@cdisc.org", role = "aut"), person("Ramiro", "Magno", email = "rmagno@pattern.institute", role = "aut", comment = c(ORCID = "0000-0001-5226-3441")), person("Pattern Institute", role = c("cph", "fnd")), person("F. Hoffmann-La Roche AG", role = c("cph", "fnd")), person("Pfizer Inc", role = c("cph", "fnd")) ) -Description: An EDC and Data Standard agnostic SDTM data transformation engine - that automates the transformation of raw clinical data in ODM format to SDTM - based on standard mapping algorithms. +Maintainer: Rammprasad Ganapathy +Description: An EDC and Data Standard-agnostic SDTM data transformation engine designed for SDTM programming in R. Powered by metadata sdtm.oak can automate the conversion of raw clinical data to SDTM through standardized mapping algorithms. SDTM is one of the required standards for data submission to FDA (U.S.) and PMDA (Japan). SDTM standards are implemented in accordance with the SDTM Implemetation guide as defined by CDISC Language: en-US License: Apache License (>= 2) BugReports: https://github.com/pharmaverse/sdtm.oak/issues @@ -26,9 +32,9 @@ Depends: R (>= 4.2) Imports: admiraldev, dplyr (>= 1.0.0), - purrr (>= 1.0.0), - rlang (>= 1.0.0), - stringr, + purrr (>= 0.3.3), + rlang (>= 0.4.4), + stringr (>= 1.4.0), tibble Suggests: knitr, diff --git a/_pkgdown.yml b/_pkgdown.yml index d71acfb9..d0716d79 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1,4 +1,8 @@ -url: ~ +url: https://pharmaverse.github.io/sdtm.oak + template: bootstrap: 5 + bootswatch: flatly +navbar: + title: "sdtm.oak" diff --git a/inst/cm_domain/cm_raw_data.csv b/inst/cm_domain/cm_raw_data.csv new file mode 100644 index 00000000..5ffc75bf --- /dev/null +++ b/inst/cm_domain/cm_raw_data.csv @@ -0,0 +1,15 @@ +PATNUM,SUBJSTAT,SITENM,INSTANCE,INSTRN,FOLDER,FOLDERL,FOLDERSQ,FORM,FORML,DATAPGID,PGREPNUM,RECORDDT,RECORDID,RECPOS,RECSTAT,MDNUM,MDNUM_RAW,MDREC,MDRAW,MDIND,MDBDR,MDBDTU,MDBTM,MDBTMU,MDPRIOR,MDEDR,MDEDT,MDETM,MDETMU,MDONG,DOS,DOSU,DOSUV,MDFORM,MDRTE,MDFRQ,MDPROPH,TERMID,SRCLN,RAVRFID,CMMODIFY,CMDRG,CMDRGCD,CMDECOD,CMPNCD,SPLIT,OMIT,ACTTYP,ACTTEXT,CMDICT,CMCLAS,CMCLASCD,CMATC4,CMATC4CD,CMATC3,CMATC3CD,CMATC2,CMATC2CD,CMATC1,CMATC1CD,CLASSNUM +375,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56379253,0,,111885785,1,N,1,1,No,BABY ASPIRIN,,,1,,1,1,,,,0,1,10,mg,MG,Tablet,PO (Oral),QD (Every Day),0,109576058,20,5652739,BABY ASPIRIN,BABY ASPIRIN,2701701,ACETYLSALICYLIC ACID,2701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,STOMATOLOGICAL PREPARATIONS,A01A,STOMATOLOGICAL PREPARATIONS,A01,ALIMENTARY TRACT AND METABOLISM,A,1 +375,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56379253,0,,111969387,2,N,2,2,No,CORTISPORIN,NAUSEA,15-Sep-20,0,,1,0,,,,0,1,50,g,G,Pill,PO (Oral),,0,105820348,28,5533807,CORTISPORIN (UNITED STATES),CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03C,OPHTHALMOLOGICAL AND OTOLOGICAL PREPARATIONS,S03,SENSORY ORGANS,S,1 +376,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56407664,0,,111939965,1,N,1,1,No,ASPIRIN,ANEMIA,17-Feb-21,0,8:00,0,0,17-Feb-21,2/17/21,,0,0,,,,,,,0,80619660,8,4297014,ASPIRIN,ASPIRIN [ACETYLSALICYLIC ACID],2701004,ACETYLSALICYLIC ACID,2701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,STOMATOLOGICAL PREPARATIONS,A01A,STOMATOLOGICAL PREPARATIONS,A01,ALIMENTARY TRACT AND METABOLISM,A,1 +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,111942855,1,N,1,1,No,DIPHENHYDRAMINE HCL,NAUSEA,4-Oct-20,0,9:00,0,0,,,,0,1,50,mg,MG,Capsule,PO (Oral),BID (Twice a Day),0,79751919,3,4240092,DIPHENHYDRAMINE HCL,DIPHENHYDRAMINE HCL,402246,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972536,2,N,2,2,No,PARCETEMOL,PYREXIA,20-Jan-20,0,10:00,0,0,20-Jan-20,1/20/20,10:00,0,0,,mg,MG,Capsule,PO (Oral),BID (Twice a Day),1,129972536,2,,,,,,,,,,,,,,,,,,,,,, +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972541,3,N,3,3,No,VOMIKIND,VOMITINGS,UN UNK 2019,1,,1,0,UN UNK 2019,6/15/19,,1,0,,Tablet,TABLET,,PO (Oral),PRN (As Needed),1,129972541,3,,,,,,,,,,,,,,,,,,,,,, +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972568,4,N,5,5,No,ZENFLOX OZ,DIARHHEA,20 UNK 2019,0,10:00,0,0,20 UNK 2019,6/15/19,,1,0,,mL,ML,Injection,IM (Intramuscular),PRN (As Needed),1,129972568,4,,,,,,,,,,,,,,,,,,,,,, +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472439,4,N,4,4,No,AMITRYPTYLINE,COLD,UN UNK 2020,0,,1,1,UN UNK 2020,6/15/20,,1,0,12,g,G,Inhalant,IA (Intra-arterial),QD (Every Day),0,81845879,6,4382628,AMITRIPTYLINE,AMITRIPTYLINE,2201001,AMITRIPTYLINE,2201001,,,SPELLING UPDATE,AMITRIPTYLINE,"WHODRUG GLOBAL B3 MARCH 1, 2021",DRUGS FOR URINARY FREQUENCY AND INCONTINENCE,G04BD,DRUGS FOR URINARY FREQUENCY AND INCONTINENCE,G04BD,UROLOGICALS,G04B,UROLOGICALS,G04,GENITO URINARY SYSTEM AND SEX HORMONES,G,1 +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472436,1,N,1,1,No,BENADRYL,FEVER,26-Jan-20,0,9:00,0,0,26-Jan-20,1/26/20,7:00,0,0,100,mg,MG,Capsule,PO (Oral),BID (Twice a Day),1,95547017,4,5211852,BENADRYL (UNITED STATES),BENADRYL [DIPHENHYDRAMINE HYDROCHLORIDE],402002,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472437,2,N,2,2,Yes,DIPHENHYDRAMINE HYDROCHLORIDE,LEG PAIN,28-Jan-20,1,,1,1,1-Feb-20,2/1/20,,1,1,100,Capsule,CAPSULE,Capsule,Unknown,QD (Every Day),0,94095723,13,5084095,DIPHENHYDRAMINE HYDROCHLORIDE,DIPHENHYDRAMINE HYDROCHLORIDE,402001,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472438,3,N,3,3,Yes,TETRACYCLINE,FEVER,12-Feb-20,0,12:12,0,1,18-Feb-20,2/18/20,,0,0,10,mg,MG,Capsule,DE (Transdermal),BID (Twice a Day),1,84246445,6,4537684,TETRACYCLINE,TETRACYCLINE,1701001,TETRACYCLINE,1701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",ANTIBIOTICS,S01AA,ANTIBIOTICS,S01AA,ANTIINFECTIVES,S01A,OPHTHALMOLOGICALS,S01,SENSORY ORGANS,S,1 +379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472565,3,N,1,1,No,BENADRYL,COLD,10 UNK 2020,0,,0,0,20 UNK 2020,6/15/20,,0,0,12,IU,IU,Lotion,IJ (Intra-articular), , ,84734661,12,4567194,BENADRYL (UNITED STATES),BENADRYL [DIPHENHYDRAMINE HYDROCHLORIDE],402002,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472563,1,N,2,2,No,SOMINEX,COLD,,1,,1,0,,,,1,1,,mL,ML,Liquid,EP (Epidural),PRN (As Needed),0,82746644,5,4580551,SOMINEX (UNITED STATES),SOMINEX [DIPHENHYDRAMINE HYDROCHLORIDE],402060,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472564,2,N,3,3,No,ZQUILL,PAIN,,1,,1,0,17-Feb-20,2/17/20,,1,0,5,%,%,Aerosol,OP (Ophthalmic),Q2H (Every 2 Hours),0,99707553,22,5330876,ZZZQUIL,ZZZQUIL,402326,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,SPELLING UPDATE,ZZZQUIL,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 \ No newline at end of file diff --git a/inst/cm_domain/cm_sdtm.csv b/inst/cm_domain/cm_sdtm.csv new file mode 100644 index 00000000..6fe047db --- /dev/null +++ b/inst/cm_domain/cm_sdtm.csv @@ -0,0 +1,7 @@ +STUDYID,DOMAIN,USUBJID,CMSEQ,CMGRPID,CMREFID,CMSPID,CMTRT,CMMODIFY,CMDECOD,CMCAT,CMPRESP,CMOCCUR,CMINDC,CMDOSE,CMDOSTXT,CMDOSU,CMDOSFRM,CMDOSFRQ,CMROUTE,VISITNUM,VISIT,VISITDY,EPOCH,CMDTC,CMSTDTC,CMENDTC,CMDY,CMSTDY,CMENDY,CMSTRTPT,CMSTTPT,CMENRTPT,CMENTPT,CMPROPH,CMDRG,CMDRGCD,CMPNCD +LPSTUDY,CM,LPSTUDY-375,1,NA,NA,/F:VACHX-D:56379540-R:1,TETANUS,NA,NA,VACCINATION HISTORY,Y,Y,NA,NA,NA,NA,NA,NA,NA,1,Screening,-8,SCREENING,2020-09-01,2019-02-02,NA,-27,-604,NA,NA,NA,NA,NA,NA,NA,NA,NA +LPSTUDY,CM,LPSTUDY-375,2,NA,NA,/F:VACHX-D:56379540-R:2,COVID-19,NA,NA,VACCINATION HISTORY,Y,Y,NA,NA,NA,NA,NA,NA,NA,1,Screening,-8,SCREENING,2020-09-01,2020-08-31,NA,-27,-28,NA,NA,NA,NA,NA,NA,NA,NA,NA +LPSTUDY,CM,LPSTUDY-375,3,NA,NA,/F:VACHX-D:56379540-R:3,FLU,NA,NA,VACCINATION HISTORY,NA,NA,NA,NA,NA,NA,NA,NA,NA,1,Screening,-8,SCREENING,2020-09-01,NA,NA,-27,NA,NA,BEFORE,SCREENING,NA,NA,NA,NA,NA,NA +LPSTUDY,CM,LPSTUDY-375,4,1,5652739,/F:MD1-D:56379253-R:1,BABY ASPIRIN,NA,ACETYLSALICYLIC ACID,NA,NA,NA,NA,10,NA,mg,TABLET,QD,ORAL,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,BEFORE,SCREENING,ONGOING,DATE OF LAST ASSESSMENT,NA,BABY ASPIRIN,00002701701,00002701001 +LPSTUDY,CM,LPSTUDY-375,5,2,5533807,/F:MD1-D:56379253-R:2,CORTISPORIN,CORTISPORIN (UNITED STATES),CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,NA,NA,NA,NAUSEA,50,NA,g,PILL,NA,ORAL,NA,NA,NA,SCREENING,NA,2020-09-15,NA,NA,-13,NA,NA,NA,ONGOING,DATE OF LAST ASSESSMENT,NA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,90104001001 +LPSTUDY,CM,LPSTUDY-378,1,3,4537684,/F:MD1-D:63059916-R:3,TETRACYCLINE,NA,TETRACYCLINE,NA,NA,NA,FEVER,10,NA,mg,CAPSULE,BID,TRANSDERMAL,NA,NA,NA,TREATMENT,NA,2020-02-12T12:12,2020-02-18,NA,18,24,BEFORE,SCREENING,NA,NA,Y,TETRACYCLINE,00001701001,00001701001 diff --git a/inst/cm_domain/cm_sdtm_oak_ct.csv b/inst/cm_domain/cm_sdtm_oak_ct.csv new file mode 100644 index 00000000..bf231e7e --- /dev/null +++ b/inst/cm_domain/cm_sdtm_oak_ct.csv @@ -0,0 +1,35 @@ +codelist_code,term_code,CodedData,term_value,collected_value,term_preferred_term,term_synonyms,raw_codelist +C71113,C25473,QD,QD,QD (Every Day),Daily,/day; Daily; Per Day,FREQ_CV1 +C71113,C64496,BID,BID,BID (Twice a Day),Twice Daily,BD; Twice per day,FREQ_CV1 +C71113,C64499,PRN,PRN,PRN (As Needed),As Needed,As needed,FREQ_CV1 +C71113,C64516,Q2H,Q2H,Q2H (Every 2 Hours),Every Two Hours,Every 2 hours,FREQ_CV1 +C71113,C64530,QID,QID,QID (4 Times a Day),Four Times Daily,4 times per day,FREQ_CV1 +C66726,C25158,CAPSULE,CAPSULE,Capsule,Capsule Dosage Form,cap,FRM_CV1 +C66726,C25394,PILL,PILL,Pill,Pill Dosage Form,NA,FRM_CV1 +C66726,C29167,LOTION,LOTION,Lotion,Lotion Dosage Form,NA,FRM_CV1 +C66726,C42887,AEROSOL,AEROSOL,Aerosol,Aerosol Dosage Form,aer,FRM_CV1 +C66726,C42944,INHALANT,INHALANT,Inhalant,Inhalant Dosage Form,NA,FRM_CV1 +C66726,C42946,INJECTION,INJECTION,Injection,Injectable Dosage Form,NA,FRM_CV1 +C66726,C42953,LIQUID,LIQUID,Liquid,Liquid Dosage Form,NA,FRM_CV1 +C66726,C42998,TABLET,TABLET,Tablet,Tablet Dosage Form,tab,FRM_CV1 +C66742,C49488,Y,Y,Yes,Yes,Yes,NY_CV1 +C66729,C28161,INTRAMUSCULAR,INTRAMUSCULAR,IM (Intramuscular),Intramuscular Route of Administration,NA,ROUTE_CV1 +C66729,C38210,EPIDURAL,EPIDURAL,EP (Epidural),Epidural Route of Administration,NA,ROUTE_CV1 +C66729,C38222,INTRA-ARTERIAL,INTRA-ARTERIAL,IA (Intra-arterial),Intraarterial Route of Administration,NA,ROUTE_CV1 +C66729,C38223,INTRA-ARTICULAR,INTRA-ARTICULAR,IJ (Intra-articular),Intraarticular Route of Administration,NA,ROUTE_CV1 +C66729,C38287,OPHTHALMIC,OPHTHALMIC,OP (Ophthalmic),Ophthalmic Route of Administration,NA,ROUTE_CV1 +C66729,C38288,ORAL,ORAL,PO (Oral),Oral Route of Administration,Intraoral Route of Administration; PO,ROUTE_CV1 +C66729,C38305,TRANSDERMAL,TRANSDERMAL,DE (Transdermal),Transdermal Route of Administration,NA,ROUTE_CV1 +C66729,C38311,UNKNOWN,UNKNOWN,Unknown,Unknown Route of Administration,NA,ROUTE_CV1 +C71620,C25613,%,%,%,Percentage,Percentage,UNIT_CV1 +C71620,C28253,MG,mg,mg,Milligram,Milligram,UNIT_CV1 +C71620,C28254,ML,mL,mL,Milliliter,cm3; Milliliter,UNIT_CV1 +C71620,C48155,G,g,g,Gram,Gram,UNIT_CV1 +C71620,C48480,CAPSULE,CAPSULE,Capsule,Capsule Dosing Unit,cap; Capsule Dosing Unit,UNIT_CV1 +C71620,C48542,TABLET,TABLET,Tablet,Tablet Dosing Unit,tab; Tablet Dosing Unit,UNIT_CV1 +C71620,C48579,IU,IU,IU,International Unit,IE; International Unit,UNIT_CV1 +C71620,C28254,ML,mL,mL,Milliliter,cm3; Milliliter,UNIT_CV5 +C66728,C25629,BEFORE,BEFORE,Prior,Prior,,NA +C66728,C53279,ONGOING,ONGOING,Continue,Continue,Continuous,NA +C66734,C49568,CM,CM,Concomitant Medication Domain,Concomitant Medication Domain,Concomitant/Prior Medications,NA +,,,,,,, \ No newline at end of file diff --git a/inst/cm_domain/cm_sdtm_oak_spec.csv b/inst/cm_domain/cm_sdtm_oak_spec.csv new file mode 100644 index 00000000..ce635d9d --- /dev/null +++ b/inst/cm_domain/cm_sdtm_oak_spec.csv @@ -0,0 +1,49 @@ +study_number,raw_source_model,raw_dataset,raw_dataset_ordinal,raw_dataset_label,raw_variable,raw_variable_label,raw_variable_ordinal,raw_variable_type,raw_data_format,raw_codelist,study_specific,annotation_ordinal,mapping_is_dataset,annotation_text,target_sdtm_domain,target_sdtm_variable,target_sdtm_variable_role,target_sdtm_variable_codelist_code,target_sdtm_variable_controlled_terms_or_format,target_sdtm_variable_ordinal,origin,mapping_algorithm,entity_sub_algorithm,target_hardcoded_value,target_term_value,target_term_code,condition_ordinal,condition_group_ordinal,condition_left_raw_dataset,condition_left_raw_variable,condition_left_sdtm_domain,condition_left_sdtm_variable,condition_operator,condition_right_text_value,condition_right_sdtm_domain,condition_right_sdtm_variable,condition_right_raw_dataset,condition_right_raw_variable,condition_next_logical_operator,merge_type,merge_left,merge_right,merge_condition,unduplicate_keys,groupby_keys,target_resource_raw_dataset,target_resource_raw_variable +lp_study,e-CRF,MD1,27,Concomitant Medications,,,,,,,FALSE,1,TRUE,CM = 'Concomitant/Prior Medications',CM,DOMAIN,Identifier Variable,C66734,,,Assigned,DATASET_LEVEL,HARDCODE_CT,,CM,C49568,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,,,,,,,FALSE,1,TRUE,CM = 'Concomitant/Prior Medications',CM,DOMAIN,Identifier Variable,C66734,,,Assigned,DATASET_LEVEL,REMOVE_DUP,,CM,C49568,,,,,,,,,,,,,,,,,,"MD1.PATNUM,MD1.MDNUM,MD1.MDRAW,MD1.RAVRFID",,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDREC,Were there any medications taken protocol specific?,1,DropDownList,$3 ,NY_CV1,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDNUM,MD number,2,Text,3,,FALSE,2,FALSE,CM.CMGRPID,CM,CMGRPID,Identifier Variable,,,6,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDRAW,Medication,3,LongText,$200 ,,FALSE,1,FALSE,CM.CMTRT,CM,CMTRT,Topic Variable,,,10,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDIND,Indication,4,LongText,$100 ,,FALSE,1,FALSE,CM.CMINDC,CM,CMINDC,Record Qualifier,,,19,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDBDR,Start date,5,DateTime,dd- MMM- yyyy,,FALSE,1,FALSE,CM.CMSTDTC,CM,CMSTDTC,Timing Variable,,ISO 8601,39,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDBDTU,Start date unknown,6,CheckBox,1,,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDBTM,Start time,7,DateTime,HH nn,,FALSE,1,FALSE,CM.CMSTDTC,CM,CMSTDTC,Timing Variable,,ISO 8601,39,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDBTMU,Start time unknown,8,CheckBox,1,,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDPRIOR,Select if taken prior to study,9,CheckBox,1,,FALSE,1,FALSE,If checked then CM.CMSTRTPT = 'BEFORE',CM,CMSTRTPT,Timing Variable,C66728,(STENRF),50,CRF,IF_THEN_ELSE,HARDCODE_CT,,BEFORE,C25629,1.1,0,MD1,MDPRIOR,,,Checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDPRIOR,Select if taken prior to study,9,CheckBox,1,,FALSE,2,FALSE,CM.CMSTTPT = 'SCREENING',CM,CMSTTPT,Timing Variable,,,51,CRF,IF_THEN_ELSE,HARDCODE_NO_CT,SCREENING,,,2.1,0,MD1,MDPRIOR,,,Checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDPRIOR,Select if taken prior to study,9,CheckBox,1,,FALSE,3,FALSE,Else NOT SUBMITTED,,,,,,,CRF,IF_THEN_ELSE,NOTSUBMITTED,,,,3.1,0,MD1,MDPRIOR,,,Not_checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDEDR,End date,10,DateTime,dd- MMM- yyyy,,FALSE,1,FALSE,CM.CMENDTC,CM,CMENDTC,Timing Variable,,ISO 8601,40,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDETM,End time,11,DateTime,HH nn,,FALSE,1,FALSE,CM.CMENDTC,CM,CMENDTC,Timing Variable,,ISO 8601,40,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDETMU,End time unknown,12,CheckBox,1,,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDONG,Select if ongoing,13,CheckBox,1,,FALSE,1,FALSE,If checked then CM.CMENRTPT = 'ONGOING',CM,CMENRTPT,Timing Variable,C66728,(STENRF),52,CRF,IF_THEN_ELSE,HARDCODE_CT,,ONGOING,C53279,1.1,0,MD1,MDONG,,,Checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDONG,Select if ongoing,13,CheckBox,1,,FALSE,2,FALSE,CM.CMENTPT = 'DATE OF LAST ASSESSMENT',CM,CMENTPT,Timing Variable,,,53,CRF,IF_THEN_ELSE,HARDCODE_NO_CT,DATE OF LAST ASSESSMENT,,,2.1,0,MD1,MDONG,,,Checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDONG,Select if ongoing,13,CheckBox,1,,FALSE,3,FALSE,Else NOT SUBMITTED,,,,,,,CRF,IF_THEN_ELSE,NOTSUBMITTED,,,,3.1,0,MD1,MDONG,,,Not_checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,DOS,Dose,14,Text,8.3,,FALSE,1,FALSE,If numeric then CM.CMDOSE,CM,CMDOSE,Record Qualifier,,,22,CRF,IF_THEN_ELSE,ASSIGN_NO_CT,,,,1.1,0,MD1,DOS,,,is_numeric,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,DOS,Dose,14,Text,8.3,,FALSE,2,FALSE,Else CM.CMDOSTXT,CM,CMDOSTXT,Record Qualifier,,,23,CRF,IF_THEN_ELSE,ASSIGN_NO_CT,,,,2.1,0,MD1,DOS,,,is_character,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,DOSU,Dose unit,15,SearchList,$30 ,UNIT_CV1,FALSE,1,FALSE,CM.CMDOSU,CM,CMDOSU,Variable Qualifier,C71620,(UNIT),24,CRF,ASSIGN_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDFORM,Dose form,16,SearchList,$80 ,FRM_CV1,FALSE,1,FALSE,CM.CMDOSFRM,CM,CMDOSFRM,Variable Qualifier,C66726,(FRM),25,CRF,ASSIGN_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDRTE,Route,17,DropDownList,$25 ,ROUTE_CV1,FALSE,1,FALSE,CM.CMROUTE,CM,CMROUTE,Variable Qualifier,C66729,(ROUTE),29,CRF,ASSIGN_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDFRQ,Dose Frequency,18,SearchList,$25 ,FREQ_CV1,FALSE,1,FALSE,CM.CMDOSFRQ,CM,CMDOSFRQ,Variable Qualifier,C71113,(FREQ),26,CRF,ASSIGN_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDPROPH,Given for prophylaxis?,19,CheckBox,1,,FALSE,1,FALSE,If checked then CMPROPH = 'Y' in SUPPCM,CM,CMPROPH,Supplemental Record Qualifier,C66742,(NY),106,CRF,IF_THEN_ELSE,HARDCODE_CT,,Y,C49488,1.1,0,MD1,MDPROPH,,,Checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,27,Concomitant Medications,MDPROPH,Given for prophylaxis?,19,CheckBox,1,,FALSE,2,FALSE,Else NOT SUBMITTED,,,,,,,CRF,IF_THEN_ELSE,NOTSUBMITTED,,,,2.1,0,MD1,MDPROPH,,,Not_checked,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,TERMID,TERM_REC_ID,1,Text,$15 ,,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,SRCLN,SOURCE_LINE_NUMBER,2,Text,3,,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,RAVRFID,RAVE_REFERENCE_ID,3,Text,15,,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,MDRAW,Medication,4,LongText,$200 ,,FALSE,1,FALSE,NOT SUBMITTED,,,,,,,CRF,NOTSUBMITTED,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMMODIFY,Corrected Term,5,LongText,"$1,500 ",,FALSE,1,FALSE,If different to CM.CMTRT then CM.CMMODIFY,CM,CMMODIFY,Synonym Qualifier,,,11,CRF,IF_THEN_ELSE,ASSIGN_NO_CT,,,,1.1,0,MD1,CMMODIFY,,,Different_to,,CM,CMTRT,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMMODIFY,Corrected Term,5,LongText,"$1,500 ",,FALSE,2,FALSE,"If [CM.CMMODIFY] is over 200 characters, split CM.CMMODIFY into CMMODIFn in SUPPCM to the nearest semicolon, where n is 1 to N number of 200-character segments.",CM,CMMODIFY,Synonym Qualifier,,,11,CRF,OTHER,,,,,,,,CMMODIFY,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMDRG,WHODrug Drug Name,6,LongText,"$1,500 ",,FALSE,1,FALSE,CMDRG in SUPPCM,CM,CMDRG,Supplemental Variable Qualifier,,WHO DD,109,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMDRG,WHODrug Drug Name,6,LongText,"$1,500 ",,FALSE,2,FALSE,"If [MD1C.CMDRG] is over 200 characters, split CMDRG in SUPPCM into CMDRGn in SUPPCM to the nearest semicolon, where n is 1 to N number of 200-character segments.",CM,CMDRG,Supplemental Variable Qualifier,,WHO DD,109,CRF,OTHER,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMDRGCD,WHODrug Drug Name Code,7,Text,$30 ,,FALSE,1,FALSE,CMDRGCD in SUPPCM,CM,CMDRGCD,Supplemental Variable Qualifier,,WHO DD,111,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMDECOD,WHODrug Preferred Name,8,LongText,"$1,500 ",,FALSE,1,FALSE,CM.CMDECOD,CM,CMDECOD,Synonym Qualifier,,*,12,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMDECOD,WHODrug Preferred Name,8,LongText,"$1,500 ",,FALSE,2,FALSE,"If [MD1C.CMDECOD] is over 200 characters, split CM.CMDECOD into CMDECODn in SUPPCM to the nearest semicolon, where n is 1 to N number of 200-character segments.",CM,CMDECOD,Synonym Qualifier,,*,12,CRF,OTHER,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,MD1,28,Concomitant Medications,CMPNCD,WHODrug Preferred Name Code,9,Text,$30 ,,FALSE,1,FALSE,CMPNCD in SUPPCM,CM,CMPNCD,Supplemental Variable Qualifier,,WHO DD,112,CRF,ASSIGN_NO_CT,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,Unique identifier for a study.,CM,STUDYID,Identifier Variable,,,1,Protocol,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,"Set to USUBJID in SDTM.DM domain. Set to Subject Identifier (SDTM.DM.SUBJID) used for the first trial the subject participated in involving the product. Taken directly from SDTM IG 3.1.2, p29: ""Unique subject identifier must be unique for each trial participant (subject) across all trials in the submission. This means that no two (or more) subjects across all trials in the submission, may have the same USUBJID. Additionally the same person who participates in multiple clinical trials (when this is known) must be assigned the same USUBJID value in all trials."" Practical guidance for SMTs to follow in order to ensure we are aligned with the latest regulatory guidance: 1) When we have a planned study design which anticipates enrolling subjects who have participated in a previous study for the same indication, we must add a CRF page to the subsequent study to collect the study id,and subject id from the original study. These data will be used to construct the USUBJID variable in the subsequent study, in order to provide a unique subject identifier across studies for the same study participant. 2) When we discover that we have two or more studies in a submission that may have subjects who have participated in more than one study, we must provide a common value in USUBJID to provide a unique subject identifier across studies. Since this was not planned we must manually construct a dataset to link the IDs of patients in multiple studies. Post-processing is required to amend the study data with this information.",CM,USUBJID,Identifier Variable,,,3,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,Sequence Number given to ensure uniqueness of subject records within a domain. May be any valid number.,CM,CMSEQ,Identifier Variable,,,5,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,Sponsor-defined reference number. Examples: a number pre-printed on the CRF as an explicit line identifier or record identifier defined in the sponsor's operational database. Example: line number on a concomitant medication page.,CM,CMSPID,Identifier Variable,,,8,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,"1. Clinical encounter number. 2. Numeric version of VISIT, used for sorting.",CM,VISITNUM,Timing Variable,,,34,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,1. Protocol-defined description of clinical encounter. 2. May be used in addition to VISITNUM and/or VISITDY.,CM,VISIT,Timing Variable,,,35,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,"Epoch associated with the start date/time of the observation, or the date/time of collection if start date/time is not collected.",CM,EPOCH,Timing Variable,C99079,(EPOCH),37,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,"Taken directly from SDTM IG 3.1.2, p41: --DY = (date portion of --DTC) - (date portion of SDTM.DM.RFSTDTC) + 1 if --DTC is on or after SDTM.DM.RFSTDTC; --DY = (date portion of --DTC) - (date portion of SDTM.DM.RFSTDTC) if --DTC precedes SDTM.DM.RFSTDTC.",CM,CMSTDY,Timing Variable,,,42,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, +lp_study,e-CRF,,,,,,,,,,,,,"Taken directly from SDTM IG 3.1.2, p41: --DY = (date portion of --DTC) - (date portion of SDTM.DM.RFSTDTC) + 1 if --DTC is on or after SDTM.DM.RFSTDTC; --DY = (date portion of --DTC) - (date portion of SDTM.DM.RFSTDTC) if --DTC precedes SDTM.DM.RFSTDTC.",CM,CMENDY,Timing Variable,,,43,Derived,,,,,,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file diff --git a/inst/cm_domain/create_cm_template.R b/inst/cm_domain/create_cm_template.R new file mode 100644 index 00000000..346f5909 --- /dev/null +++ b/inst/cm_domain/create_cm_template.R @@ -0,0 +1,233 @@ +# Name: CM domain +# +# Label: R program to create CM Domain +# +# Input raw data: +# study_sdtm_spec +# study_controlled_terminology +# study_raw_datasets +# +# + +library(sdtm.oak) +library(dplyr) + +# Read Specification + +sdtm_spec <- read_(filename = "~/inst/cm_domain/cm_sdtm_oak_spec.csv") + +study_ct <- read_study_ct(filename = "~/inst/cm_domain/cm_sdtm_oak_ct.csv") + +# Read in raw data + +cm_raw_data <- read_raw_data_csv(filename = "~/inst/cm_domain/cm_raw_data.csv") |> + # Derive oak_id_vars + derive_oak_id_vars() + +# Create CM domain. The first step in creating CM domain is to create the topic variable + +cm <- cm_daw_data |> + # Derive topic variable + assign_no_ct( + raw_dataset = MD1, # This is added for pseudocode. Not required as pipe will send it + raw_variable = MDRAW, + target_sdtm_var = CMTRT + ) |> + # Derive qualifier CMDOSU + # Use merge and add the qualifier to the topic variable + assign_ct( + raw_dataset = MD1, + raw_variable = DOSU, + target_sdtm_var = CMDOSU, + study_ct = study_ct, + target_sdtm_variable_codelist_code = "C71620", + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive qualifier CMDOSFRM and merge it with the target dataset + assign_ct( + raw_dataset = MD1, + raw_variable = MDFORM, + target_sdtm_var = CMDOSFRM, + target_sdtm_variable_codelist_code = "C66726", + study_ct = study_ct, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # DERIVE CMROUTE + assign_ct( + raw_dataset = MD1, + raw_variable = MDFORM, + target_sdtm_var = MDRTE, + target_sdtm_variable_codelist_code = "C66729", + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # DERIVE CMDOSFRQ + assign_ct( + raw_dataset = MD1, + raw_variable = MDFRQ, + target_sdtm_var = CMDOSFRQ, + target_sdtm_variable_codelist_code = "C71113", + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # DERIVE CMINDC + assign_no_ct( + raw_dataset = MD1, + raw_variable = MDIND, + target_sdtm_var = CMINDC, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive qualifier CMDOSE. Annotation text = If numeric then CM.CMDOSE + if_then_else( + raw_dataset = MD1, + raw_variable = DOS, + condition_left_raw_dataset = MD1, + condition_left_raw_variable = DOS, + condition_operator = "is_numeric", + sub_algorithm = assign_no_ct, # pass the function as the argument + target_sdtm_var = CMDOSE, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive qualifier CMDOSTXT. Annotation text = If character then CM.CMDOSTXT + if_then_else( + raw_dataset = MD1, + raw_variable = DOS, + condition_left_raw_dataset = MD1, + condition_left_raw_variable = DOS, + condition_operator = "is_character", + sub_algorithm = assign_no_ct, + target_sdtm_var = CMDOSETXT, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive qualifier CMMODIFY Annotation text = If different to CM.CMTRT then CM.CMMODIFY + if_then_else( + raw_dataset = MD1, + raw_variable = CMMODIFY, + condition_left_raw_dataset = MD1, + condition_left_raw_variable = CMMODIFY, + condition_operator = "diffferent_to", + condition_right_sdtm_variable_domain = CM, + condition_right_sdtm_variable = CMTRT, + sub_algorithm = assign_no_ct, + target_sdtm_var = CMDOSETXT, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive CMDECOD + assign_no_ct( + raw_dataset = MD1, + raw_variable = CMDECOD, + target_sdtm_var = CMDECOD + ) |> + # Derive CMSTDTC. This function calls create_iso8601 + assign_no_ct( + raw_dataset = MD1, + raw_variable = c("MDBD", "MDBTM"), + target_sdtm_var = CMSTDTC, + .format = c("ddmmmyyyy", "HHMM") + ) |> + # Derive CMENDTC. This function calls create_iso8601 + assign_no_ct( + raw_dataset = MD1, + raw_variable = c("MDED", "MDETM"), + target_sdtm_var = CMENDTC, + .format = c("ddmmmyyyy", "HHMM") + ) |> + # Derive qualifier CMSTRTPT Annotation text = If checked then CM.CMSTRTPT = 'BEFORE' + if_then_else( + raw_dataset = MD1, + raw_variable = MDPRIOR, + condition_left_raw_dataset = MD1, + condition_left_raw_variable = MDPRIOR, + condition_operator = "if_checked", + sub_algorithm = assign_ct, + target_sdtm_variable_codelist_code = "C66728", + target_sdtm_var = CMSTRTPT, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive qualifier CMSTRTPT Annotation text = If checked then CM.CMSTTPT = 'SCREENING' + if_then_else( + raw_dataset = MD1, + raw_variable = MDPRIOR, + condition_left_raw_dataset = MD1, + condition_left_raw_variable = MDPRIOR, + condition_operator = "if_checked", + sub_algorithm = hardcode_no_ct, + target_hardcoded_value = "SCREENING", + target_sdtm_var = CM.CMSTTPT, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive qualifier CMENRTPT Annotation text = If checked then CM.CMENRTPT = 'ONGOING' + if_then_else( + raw_dataset = MD1, + raw_variable = MDONG, + condition_left_raw_dataset = MD1, + condition_left_raw_variable = MDONG, + condition_operator = "if_checked", + sub_algorithm = hardcode_ct, + target_hardcoded_value = "ONGOING", + target_sdtm_variable_codelist_code = "C66728", + target_sdtm_var = CMENRTPT, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive qualifier CMENTPT Annotation text = If checked then CM.CMENTPT = 'DATE OF LAST ASSESSMENT' + if_then_else( + raw_dataset = MD1, + raw_variable = MDONG, + condition_left_raw_dataset = MD1, + condition_left_raw_variable = MDONG, + condition_operator = "if_checked", + sub_algorithm = hardcode_no_ct, + target_hardcoded_value = "DATE OF LAST ASSESSMENT", + target_sdtm_var = CMENTPT, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + # Derive CMGRPID + assign_no_ct( + raw_dataset = MD1, + raw_variable = MDNUM, + target_sdtm_var = CMGRPID, + merge_to_topic_by = c(oak_id_vars, + topic_var_source = MDRAW + ) + ) |> + dplyr::mutate( + STUDYID = "test_study", + DOMAIN = "CM", + CMCAT = "GENERAL CONMED" + ) |> + derive_usubjid() |> + derive_sequence(keys = c(USUBJID, CMTRT)) |> + derive_visit_visitnum() |> + calculate_study_day( + dm_domain = dm, + study_day_var = "RFSTDTS", + var_in = CMSTDTC, + target_var = CMSTDY, + merge_key = "USUBJID" + ) |> + derive_study_day( + var_in = CMENDTC, + target_var = CMENDY + ) diff --git a/man/sdtm.oak-package.Rd b/man/sdtm.oak-package.Rd index fc04b354..20606fa4 100644 --- a/man/sdtm.oak-package.Rd +++ b/man/sdtm.oak-package.Rd @@ -6,7 +6,7 @@ \alias{sdtm.oak-package} \title{sdtm.oak: SDTM Data Transformation Engine} \description{ -An EDC and Data Standard agnostic SDTM data transformation engine that automates the transformation of raw clinical data in ODM format to SDTM based on standard mapping algorithms. +An EDC and Data Standard-agnostic SDTM data transformation engine designed for SDTM programming in R. Powered by metadata sdtm.oak can automate the conversion of raw clinical data to SDTM through standardized mapping algorithms. SDTM is one of the required standards for data submission to FDA (U.S.) and PMDA (Japan). SDTM standards are implemented in accordance with the SDTM Implemetation guide as defined by CDISC \url{https://www.cdisc.org/standards/foundational/sdtmig} } \seealso{ Useful links: @@ -18,11 +18,17 @@ Useful links: } \author{ -\strong{Maintainer}: Omar Garcia \email{ogcalderon@cdisc.org} +\strong{Maintainer}: Rammprasad Ganapathy \email{ganapathy.rammprasad@gene.com} Authors: \itemize{ - \item Rammprasad Ganapathy + \item Adam Forys + \item Edgar Manukyan + \item Rosemary Li + \item Preetesh Parikh + \item Lisa Houterloot + \item Yogesh Gupta + \item Omar Garcia \email{ogcalderon@cdisc.org} \item Ramiro Magno \email{rmagno@pattern.institute} (\href{https://orcid.org/0000-0001-5226-3441}{ORCID}) } diff --git a/renv.lock b/renv.lock index 77ba5c8d..20b69f01 100644 --- a/renv.lock +++ b/renv.lock @@ -41,7 +41,7 @@ }, "R.oo": { "Package": "R.oo", - "Version": "1.25.0", + "Version": "1.26.0", "Source": "Repository", "Repository": "RSPM", "Requirements": [ @@ -50,7 +50,7 @@ "methods", "utils" ], - "Hash": "a0900a114f4f0194cf4aa8cd4a700681" + "Hash": "4fed809e53ddb5407b3da3d0f572e591" }, "R.utils": { "Package": "R.utils", diff --git a/renv/profiles/4.2/renv.lock b/renv/profiles/4.2/renv.lock index e59b2625..a85cc2fe 100644 --- a/renv/profiles/4.2/renv.lock +++ b/renv/profiles/4.2/renv.lock @@ -41,7 +41,7 @@ }, "R.oo": { "Package": "R.oo", - "Version": "1.25.0", + "Version": "1.26.0", "Source": "Repository", "Repository": "RSPM", "Requirements": [ @@ -50,7 +50,7 @@ "methods", "utils" ], - "Hash": "a0900a114f4f0194cf4aa8cd4a700681" + "Hash": "4fed809e53ddb5407b3da3d0f572e591" }, "R.utils": { "Package": "R.utils", diff --git a/renv/profiles/4.3/renv.lock b/renv/profiles/4.3/renv.lock index 77ba5c8d..20b69f01 100644 --- a/renv/profiles/4.3/renv.lock +++ b/renv/profiles/4.3/renv.lock @@ -41,7 +41,7 @@ }, "R.oo": { "Package": "R.oo", - "Version": "1.25.0", + "Version": "1.26.0", "Source": "Repository", "Repository": "RSPM", "Requirements": [ @@ -50,7 +50,7 @@ "methods", "utils" ], - "Hash": "a0900a114f4f0194cf4aa8cd4a700681" + "Hash": "4fed809e53ddb5407b3da3d0f572e591" }, "R.utils": { "Package": "R.utils", diff --git a/staged_dependencies.yaml b/staged_dependencies.yaml index 72a49b08..a1406e69 100644 --- a/staged_dependencies.yaml +++ b/staged_dependencies.yaml @@ -8,4 +8,3 @@ downstream_repos: current_repo: repo: pharmaverse/sdtm.oak host: https://github.com - \ No newline at end of file diff --git a/vignettes/articles/algo_sub_algo_combo.jpg b/vignettes/articles/algo_sub_algo_combo.jpg new file mode 100644 index 00000000..ff9246da Binary files /dev/null and b/vignettes/articles/algo_sub_algo_combo.jpg differ diff --git a/vignettes/articles/algorithms.Rmd b/vignettes/articles/algorithms.Rmd new file mode 100644 index 00000000..f3a5317b --- /dev/null +++ b/vignettes/articles/algorithms.Rmd @@ -0,0 +1,214 @@ +--- +title: "Algorithms & Sub-Algorithms" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Algorithms} + %\VignetteEncoding{UTF-8} + %\VignetteEngine{knitr::rmarkdown} +editor_options: + markdown: + wrap: 72 +--- + +## Core Concept + +SDTM mappings are defined as algorithms that transform the collected +(eCRF, eDT) source data into the target SDTM data model. Mapping +algorithms are the backbone of the sdtm.oak - SDTM data transformation +engine. + +**Key Points:** + +- Algorithms can be re-used across multiple SDTM domains. + +- Algorithms are pre-specified for data collection standards in MDR + (if applicable) + +- Programming language agnostic - this concept does not rely on a + specific programming language for implementation. The OAK team + implemented them as R functions. + +Here is an example of reusing an algorithm across multiple domains, +variables, and also to a non-standard + +![](reusable_algorithms.jpg){width="600px"} + +## List of Algorithms + +```{r echo = FALSE, results = "asis"} +library(knitr) +algorithms <- data.frame( + `Algorithm Name` = c( + "ASSIGN_NO_CT", + "ASSIGN_CT", + "AE_AEREL", + "HARDCODE_CT", + "HARDCODE_NO_CT", + "DATASET_LEVEL", + "NOTSUBMITTED", + "IF_THEN_ELSE", + "MERGE", + "RELREC", + "MULTIPLE_RESPONSES", + "SPLIT_TO_SUPPQUAL", + "REMOVE_DUP", + "GROUP_BY" + ), + `Description` = c( + paste( + "One-to-one mapping between the raw source and a target", + "SDTM variable that has no controlled terminology restrictions.", + "Just a simple assignment", + "statement. This algorithm will also handle the concatenation of", + "multiple items into a target SDTM variable." + ), + paste( + "One-to-one mapping between the raw source and a target ", + "SDTM variable that is subject to controlled terminology restrictions.", + "A simple assign statement and applying controlled terminology.", + "This will be used only if the SDTM variable has an associated", + "controlled terminology." + ), + paste( + "Algorithm that is currently unique to AE.AEREL,", + "particularly when more than one drug is used in the study.
If any collected study drug", + "causalities are 'Yes' then AE.AEREL is Y.
If all collected study", + "drug causalities are 'NA' then AE.AEREL is NA.
If no study drug", + "causalities are 'Yes' but there is at least one causality of 'No'", + "then AE.AEREL is N.
Individual study drug causality responses are", + "stored in AERELn in SUPPAE." + ), + paste( + "Mapping a hardcoded value to a target SDTM variable that is subject to terminology restrictions.", + "This will be used only if the SDTM variable has an associated", + "controlled terminology." + ), + paste( + "Mapping a hardcoded value to a target SDTM variable that has no terminology restrictions." + ), + paste( + "Indicates a dataset-level mapping. These mappings will", + "be applied to all SDTM records created from that source.", + "Also called a eCRF-level mappings in eCRF and dataset-level", + "mappings in eDT" + ), + paste( + "Instruction that `sdtm.oak` should not map the collected item to SDTM at all." + ), + paste( + "Represents the If then else statement. This can be an if statement", + "with no else or with the else condition. This algorithm will be", + "used for the annotations where a condition has to be evaluated", + "before a mapping is performed. A sub-algorithm is required. If the", + "condition resolves to `TRUE`, the sub-algorithm will be executed." + ), + paste( + "To indicate a join condition with a secondary source or multiple sources.", + "Merges are expressed at the domain level only", + "(not at data point or variable level).", + "This is a sub-algorithm and can only be used with algorithm DATASET_LEVEL." + ), + paste( + "Associate two domains based on the variables in each domain and how those are related.", + "Specifies the name of two domains that are related via RELREC." + ), + paste( + "Consolidate the responses from more than one source variable into one target variable.", + "Used when multiple responses may be given for a single SDTM column.", + "`sdtm.oak` will populate all target variable(s) after determining the number of responses provided." + ), + paste( + "Consolidates the responses from more than one", + "source variable into more than one target variable", + "(always a suppqual/non-standard variable).", + "There is no 'parent' target variable that is populated with 'MULTIPLE'." + ), + paste( + "Sub-algorithm at the domain level that indicates some source records may", + "be removed during the `sdtm.oak` mapping process if determined to be duplicate records." + ), + paste( + "Sub-algorithm used at the domain level to group source records", + "before mapping to SDTM. This is used in the event we need to collapse data", + "collected across multiple rows into one row in SDTM but it is not a simple", + "un-duplication effort. For example, the way infusion study drug", + "administration data requires us to create 1 SDTM record in EC from 1 or more source", + "records in the mixed log form. When there is more than one source record,", + "we need to take the earliest collected infusion start date (for ECSTDTC) and", + "the latest collected infusion end date within an eCRF instance." + ) + ), + `Example` = c( + paste( + "MH.MHTERM
", + "VS.VSDTC
", + "MH.MHTERM = [LNGCAHX1.HSTYP] || ' ' || 'NON-METASTATIC LUNG CANCER'
", + "CM.CMINDC = [MD9.MDCIND] || ' ' || [MD9.MDCINDSP]" + ), + paste("VS.VSPOS
", "VS.VSLAT"), + paste("For AE.AEREL and AERELn in SUPPAE"), + paste( + "MH.MHPRESP = 'Y'
", + "VS.VSTEST = 'Systolic Blood Pressure'
", + "VS.VSORRESU = 'mmHg'
" + ), + paste( + "FA.FASCAT = 'COVID-19 PROBABLE CASE'
", + "CM.CMTRT = 'FLUIDS'" + ), + paste( + "VS = 'Vital Signs'
", + "MH.MHCAT = 'PROSTATE CANCER HISTORY'
" + ), + paste(""), + paste( + "If 'Ongoing' then MH.MHENRTPT = 'ONGOING'
Else MH.MHENRTPT = 'BEFORE'

", + "If [HX1.STATUS] is present then MH.MHENTPT = 'FIRST DOSE OF STUDY DRUG'

", + "If checked then MH.MHSTTPT = 'SCREENING'
Else NOT SUBMITTED

", + "VS.VSMETHOD when VS.VSTESTCD = 'TEMP'", + "(Though the annotation text does not have the If condition,", + "we need to map VSMETHOD only if the VSTESTCD is TEMP. The IF_THEN_ELSE will be", + "used as the Algorithm for such cases even the 'If' condition is not explicitly", + "defined in the annotation text)" + ), + paste("AE = 'Adverse Events' on the early phase SAE eCRF"), + paste("BE record related to BS record via RELREC"), + paste( + "AE.AERELNST/ AERELNSn IN SUPPAE

", + "DM.RACE, if only one value is selected.
", + "DM.RACE = MULTIPLE, if more than one value is selected.
", + "RACEn in SUPPDM where n = 1 to N selected values" + ), + paste( + "If both Filipino and Samoan are checked,", + "CRACE1 will be 'FILIPINO' and CRACE2 will be 'SAMOAN'.
", + "If only Chinese is checked, CRACE1 will be 'CHINESE'." + ), + paste("AE = 'Adverse Events' on early phase SAE form"), + paste("EC = 'Exposure as Collected'") + ), + stringsAsFactors = TRUE +) +knitr::kable(algorithms) +``` + +## Sub-algorithms + +sdtm.oak supports two levels for defining algorithms. For example, there +are some SDTM mappings where a certain action has to be taken only when +a condition is met. In such cases, the primary algorithm checks for the +condition, and the sub-algorithm executes the mappings when the +condition is met. + +Currently, sub-algorithms must be provided for these main algorithms. + +- IF_THEN_ELSE +- DATASET_LEVEL + +Algorithms can be interchangeably used as algorithms and as +sub-algorithms as seen below (not an exhaustive list) + +![](algo_sub_algo_combo.jpg){width="650px"} + +The permutation & combination of algorithms & sub-algorithms creates +endless possibilities to accommodate different types of mappings. diff --git a/vignettes/articles/reusable_algorithms.jpg b/vignettes/articles/reusable_algorithms.jpg new file mode 100644 index 00000000..71c8962b Binary files /dev/null and b/vignettes/articles/reusable_algorithms.jpg differ diff --git a/vignettes/articles/study_sdtm_spec.Rmd b/vignettes/articles/study_sdtm_spec.Rmd new file mode 100644 index 00000000..3f4715d2 --- /dev/null +++ b/vignettes/articles/study_sdtm_spec.Rmd @@ -0,0 +1,361 @@ +--- +title: "All about Metadata" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{All about Metadata} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- +```{css, echo = FALSE} +#pkgdown-sidebar{ + display:none; +} +.wide .table{ + font-size: 8px; + overflow: visible +} + +``` + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +options(rmarkdown.html_vignette.check_title = FALSE) +``` + +{sdtm.oak} is a metadata-driven solution that is designed to be Electronic Data +Capture (EDC) and standards agnostic. Throughout this article, the term "metadata" +is used several times. In this context, "metadata" refers to the specific +metadata used by {sdtm.oak}. This article aims to provide users with a more +detailed understanding of the {sdtm.oak} metadata. + +In general, metadata can be defined as "data about data." It does not include +any patient-level data. Instead, the metadata provides a blueprint of the data +that needs to be collected during a study. + +## Standards Metadata + +The standards metadata used in {sdtm.oak} is sourced from the CDISC Library or +sponsor MDR or any other form of documentation where standards are maintained. +This metadata provides information on the following: + +- The relationship between Data Collection Standards (eCRF & eDT), SDTM mapping, +and Controlled Terminology +- Machine-readable standard SDTM mappings +- Algorithms and associated metadata required for the SDTM automation of +standards in the study. + +In the upcoming releases of {sdtm.oak}, we will effectively utilize the +standards metadata and customize it to meet the study requirements. + +## Study Definition Metadata + +Study Definition Metadata is also referred to as Study Metadata. Study Definition +Metadata provides information about the eCRF and eDT data collected in the study. + +**eCRF Metadata** +The eCRF Design Metadata is fetched from the EDC system. This Metadata includes + +- Forms Metadata: Identifier, eCRF label, Repeating format and other properties of the eCRF. + +- Fields Metadata: Identifier, question label, datatype, and other +properties of data collection fields in the study. + +- Data Dictionaries: Identifier and the controlled terms collected at the +source. + +- Visits: Name of the visits as defined in the EDC. + +**eDT Metadata** + +eDT Metadata is the blueprint metadata that describes the data collected as part of that external data transfer (from clinical sites to the sponsor). This includes + +- Dataset name, label, repeating properties, etc. + +- Variable name, datatype, label and associated codelist, etc. + + +## Study SDTM Mappings Metadata (specifications) + +Study SDTM mappings metadata is the study SDTM specification. To develop the SDTM domains, {sdtm.oak} requires the user to prepare the Study SDTM mappings metadata. Unlike the conventional SDTM specification, which includes one tab per domain defining the target (SDTM domain, Variables) to source (raw dataset, raw variables) and SDTM mappings, the SDTM spec for {sdtm.oak} defines the source-to-target relationship. For each source, the SDTM mapping, algorithms, and associated metadata are defined. The table below presents the columns in the SDTM mapping specification and its explanation. + +
+```{r echo = FALSE, results = "asis"} +library(knitr) +definition <- data.frame( + Variable_Name = c( + "study_number", + "raw_source_model", + "raw_dataset", + "raw_dataset_ordinal", + "raw_dataset_label", + "raw_variable", + "raw_variable_label", + "raw_variable_ordinal", + "raw_variable_type", + "raw_data_format", + "raw_codelist", + "study_specific", + "annotation_ordinal", + "mapping_is_dataset", + "annotation_text", + "target_domain", + "target_sdtm_variable", + "target_sdtm_variable_role", + "target_sdtm_variable_codelist_code", + paste( + "target_sdtm_variable_", + "controlled_terms_or_format" + ), + "target_sdtm_variable_ordinal", + "origin", + "mapping_algorithm", + "sub_algorithm", + "target_hardcoded_value", + "target_term_value", + "target_term_code", + "condition_ordinal", + "condition_group_ordinal", + "condition_left_raw_dataset", + "condition_left_raw_variable", + "condition_left_sdtm_domain", + "condition_left_sdtm_variable", + "condition_operator", + "condition_right_text_value", + "condition_right_sdtm_domain", + "condition_right_sdtm_variable", + "condition_right_raw_dataset", + "condition_right_raw_variable", + "condition_next_logical_operator", + "merge_type", + "merge_left", + "merge_right", + "merge_condition", + "unduplicate_keys", + "groupby_keys", + "target_resource_dataset", + "target_resource_variable" + ), + `Description_of_the_variable` = c( + "Study Number", + "Data Collection model", + "Name of the raw or source dataset", + "Ordinal of the raw dataset as defined in EDC or eDT specification", + "Label of the raw or source dataset", + "Name of the raw variable", + "Label of the raw variable", + paste( + "Ordinal of the variable as defined in the eCRF or", + "eDT specification" + ), + "Type of the Raw Variable", + "Data format of the raw variable", + paste( + "Dictionary name which is assigned to the ", + "eCRF field or a eDT variable" + ), + paste( + "`TRUE` indicates that the source is study specific. ", + "`FALSE` indicates that the raw variable is part of data standards" + ), + "Ordinal of the SDTM mappings for the particular raw source", + paste( + "Indicates if the SDTM mapping is at the dataset level. ", + "`TRUE` indicates that it is dataset level mapping." + ), + "SDTM mapping text or annotation text", + "Name of the target domain.", + "Name of the target SDTM variable", + "CDISC Role for the SDTM target variable defined in the annotation.", + paste( + "NCI or sponsor code of the codelist assigned to the ", + "SDTM target variable defined in the annotation." + ), + paste( + "Controlled terms or format for the target variable ", + "defined in the annotation (as defined per CDISC).", + "`target_sdtm_variable_controlled_terms_or_format` is required ", + "for SDTM Define.xml" + ), + "Ordinal of the target SDTM variable", + "Origin of metadata source, values are subject to controlled terminology", + "Mapping Algorithm", + "The sub-algorithm (scenario) of the source-to-target mapping", + "Text (Hardcoded value) that applies to the target.", + paste( + "CDISC Submission value or sponsor value which represents a", + "hardcoded text" + ), + paste( + "NCI code or sponsor code of the hardcoded value" + ), + paste( + "Ordinal of a (sub)condition, increasing when there ", + "are more than one sub-conditions (e.g. X AND Y)" + ), + paste( + "Ordinal of a group of sub-conditions, used to ", + "disambiguate complex conditions such as (A AND B) OR C. ", + "The ordinal increases in each group and gives the final ", + "precedence of the logical operators." + ), + "Name of the raw dataset on the left part of the condition", + "Name of the raw variable on the left part of the condition", + "Name of the SDTM variable used in the left part of the condition.", + paste( + "Name of the SDTM domain of the variable that is used in ", + "the left part of the condition." + ), + "Operator between the left and right part of the condition", + paste( + "A text that applies to the right part of the condition as ", + "indicated per `condition_operator`." + ), + "Name of the SDTM variable used in the right part of the condition.", + paste( + "Name of the SDTM domain of the variable that is used ", + "in the right part of the condition." + ), + "Name of the raw dataset on the right part of the condition", + "Name of the raw variable on the right part of the condition", + paste( + "The logical operator that applies to the next ", + "sub-conditions, typically AND, OR" + ), + "Specifies the type of join", + "Specifies the left component of the merge", + "Specifies the right component of the merge", + paste( + "Specify the condition of the join (e.g. a specific ", + "variable that should match in the components of the merge)" + ), + paste( + "Raw variables that should be used to determine whether ", + "an observation in the source data is a duplicate record and ", + "subject to being removed" + ), + paste( + "Raw Variables or aggregation functions (i.e. earliest, ", + "latest) to group source data records before mapping to SDTM" + ), + paste( + "Raw dataset name of the raw variable. This will be used when ", + " values are assigned from a from a different source", + "other than the source the mapping is associated with" + ), + paste( + "Raw variable name. This will be used when ", + "values are assigned from a from a different source", + "other than the source the mapping is associated with" + ) + ), + Example_Values = c( + "test_study", + "e-CRF or eDT", + "VTLS1, DEM", + "1, 2, 3, etc", + "Vital Signs,
Demographics", + "SEX_001,
BRTHDD", + "Systolic Blood Pressure,
Birth Day", + "1, 2, 3, etc", + "Text Box,
Date control", + "$200,
dd MON YYYY", + "SEX, ETHNIC", + "TRUE, FALSE", + "1, 2, 3, etc", + "TRUE, FALSE", + "VS.VSORRES when VSTESTCD = 'SYSBP'", + "VS, MH", + "VSORRES, MHSTDTC", + "Topic Variable,
Grouping Qualifier,
Identifier Variable", + "C66742
C66790", + "(AGEU)
ISO 8601
(SEX)", + "1, 2, 3", + "Derived,
Assigned,
Collected,
Predecessor", + "DATASET_LEVEL
ASSIGN_CT
AE_AEREL
HARDCODE_CT", + "ASSIGN_NO_CT
HARCODE_CT", + "ALZHEIMER'S DISEASE HISTORY", + "Y,
beats/min,
INFORMED CONSENT OBTAINED", + "C49488", + "1, 2, 3", + "1, 2, 3", + "VTLS1", + "POSITION", + "AE", + "AEENRTPT", + paste( + "Checked
Not_checked
Is_null
Is_not_null", + "
Equals_to
Different_to
is_numeric
in", + "
not_in" + ), + "('Not Recovered/Not Resolved','Recovering/Resolving')
HOSPITALIZATION", + "AE", + "AETERM", + "SMKHX", + "SUNAM", + "and, or", + "left_join
right_join
full_join
visit_join
subject_join", + "VTLS1", + "VACREC", + "VTLS1.SUBJECT = VACREC.SUBJECT,
MD1.MDNUM = VACREC.MDNUM", + "VTLS1.SUBJECT,
VTLS1.DATAPAGEID", + "TXINF1.DATAPGID,
Earliest", + "AEDE", + "DATAPAGEID" + ), + Association_with_mapping_Algorithms = c( + "Generic Use", + "Generic Use", + "Required for all mapping algorithms", + "Generic Use", + "Generic Use", + "Generic Use", + "Generic Use", + "Generic Use", + "Required for all mapping algorithms", + "Required for all mapping algorithms", + "Required for all mapping algorithms", + "Generic Use", + "Required for all mapping algorithms", + "Required for all mapping algorithms", + "Generic Use", + "Required for all mapping algorithms", + "Required for all mapping algorithms", + "Required for all mapping algorithms", + "Required for all mapping algorithms", + "Generic Use", + "Required for all mapping algorithms", + "Used for define.xml", + "Required for all mapping algorithms", + "Only when Mapping Algorithm is
IF_THEN_ELSE
DATASET_LEVEL", + "ASSIGN_NO_CT
HARDCODE_NO_CT", + "HARDCODE_CT", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "IF_THEN_ELSE", + "MERGE", + "MERGE", + "MERGE", + "MERGE", + "REMOVE_DUP", + "GROUP_BY", + "ASSIGN_NO_CT", + "ASSIGN_NO_CT" + ), + stringsAsFactors = TRUE +) +knitr::kable(definition) +```