{"id":32007923,"url":"https://github.com/reiniervlinschoten/castoredc_api","last_synced_at":"2025-10-15T19:22:50.692Z","repository":{"id":38686462,"uuid":"393088296","full_name":"reiniervlinschoten/castoredc_api","owner":"reiniervlinschoten","description":"Python Wrapper for Castor EDC API","archived":false,"fork":false,"pushed_at":"2023-07-13T14:22:43.000Z","size":673,"stargazers_count":5,"open_issues_count":11,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-27T10:05:05.041Z","etag":null,"topics":["castor-edc","castor-edc-api","clinical-research","clinical-trials","data","data-science","python3","wrapper-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reiniervlinschoten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-05T15:16:03.000Z","updated_at":"2025-05-27T18:39:57.000Z","dependencies_parsed_at":"2023-02-08T18:31:28.725Z","dependency_job_id":null,"html_url":"https://github.com/reiniervlinschoten/castoredc_api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/reiniervlinschoten/castoredc_api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reiniervlinschoten%2Fcastoredc_api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reiniervlinschoten%2Fcastoredc_api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reiniervlinschoten%2Fcastoredc_api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reiniervlinschoten%2Fcastoredc_api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reiniervlinschoten","download_url":"https://codeload.github.com/reiniervlinschoten/castoredc_api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reiniervlinschoten%2Fcastoredc_api/sbom","scorecard":{"id":769441,"data":{"date":"2025-08-11","repo":{"name":"github.com/reiniervlinschoten/castoredc_api","commit":"7d0299520e77766ea7f8d827c2e8bf3fd416f1c2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/12 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/black.yml:1","Warn: no topLevel permission defined: .github/workflows/publish_conda.yml:1","Warn: no topLevel permission defined: .github/workflows/publish_pypi.yml:1","Warn: no topLevel permission defined: .github/workflows/pylint.yml:1","Warn: no topLevel permission defined: .github/workflows/pytest.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/black.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/black.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/black.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/black.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_conda.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/publish_conda.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_conda.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/publish_conda.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish_conda.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/publish_conda.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_pypi.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/publish_pypi.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_pypi.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/publish_pypi.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pylint.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/pylint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pylint.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/pylint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pytest.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/pytest.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pytest.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/pytest.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pytest.yml:119: update your workflow using https://app.stepsecurity.io/secureworkflow/reiniervlinschoten/castoredc_api/pytest.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/black.yml:27","Warn: pipCommand not pinned by hash: .github/workflows/black.yml:28","Warn: pipCommand not pinned by hash: .github/workflows/publish_conda.yml:24","Warn: pipCommand not pinned by hash: .github/workflows/publish_conda.yml:25","Warn: pipCommand not pinned by hash: .github/workflows/publish_conda.yml:26","Warn: pipCommand not pinned by hash: .github/workflows/publish_conda.yml:41","Warn: pipCommand not pinned by hash: .github/workflows/publish_pypi.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/publish_pypi.yml:30","Warn: pipCommand not pinned by hash: .github/workflows/publish_pypi.yml:31","Warn: pipCommand not pinned by hash: .github/workflows/pylint.yml:27","Warn: pipCommand not pinned by hash: .github/workflows/pylint.yml:28","Warn: pipCommand not pinned by hash: .github/workflows/pylint.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/pytest.yml:38","Warn: pipCommand not pinned by hash: .github/workflows/pytest.yml:39","Warn: pipCommand not pinned by hash: .github/workflows/pytest.yml:40","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   0 out of  15 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 21 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T01:49:59.076Z","repository_id":38686462,"created_at":"2025-08-23T01:49:59.077Z","updated_at":"2025-08-23T01:49:59.077Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279105972,"owners_count":26104894,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-15T02:00:07.814Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["castor-edc","castor-edc-api","clinical-research","clinical-trials","data","data-science","python3","wrapper-api"],"created_at":"2025-10-15T19:22:49.722Z","updated_at":"2025-10-15T19:22:50.687Z","avatar_url":"https://github.com/reiniervlinschoten.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CastorEDC API\n[![MIT License](https://img.shields.io/github/license/reiniervlinschoten/castoredc_api)](https://github.com/reiniervlinschoten/castoredc_api/blob/main/LICENSE.md)\n[![pylint](https://github.com/reiniervlinschoten/castoredc_api/actions/workflows/pylint.yml/badge.svg)](https://github.com/reiniervlinschoten/castoredc_api/actions/workflows/pylint.yml)\n[![pytest](https://github.com/reiniervlinschoten/castoredc_api/actions/workflows/pytest.yml/badge.svg)](https://github.com/reiniervlinschoten/castoredc_api/actions/workflows/pytest.yml)\n[![coverage](https://img.shields.io/codecov/c/github/reiniervlinschoten/castoredc_api)](https://app.codecov.io/gh/reiniervlinschoten/castoredc_api)\n[![black](https://github.com/reiniervlinschoten/castoredc_api/actions/workflows/black.yml/badge.svg)](https://github.com/reiniervlinschoten/castoredc_api/actions/workflows/black.yml)\n\n[![pypi](https://img.shields.io/pypi/v/castoredc_api)](https://pypi.org/project/castoredc-api/)\n[![conda](https://img.shields.io/conda/v/reiniervl/castoredc_api)](https://anaconda.org/reiniervl/castoredc_api)\n[![conda-forge](https://img.shields.io/conda/v/conda-forge/castoredc_api)](https://anaconda.org/conda-forge/castoredc_api)\n\n## Features\n#### Supports CastorEDC Release 2023.2\n\nThis is a Python package for interacting with the API of Castor Electronic Data Capture (EDC). \nThe package contains functions to interact with all the endpoints defined on https://data.castoredc.com/api#/.\nWithin the package are functions for easy export and import of your data through the API.\n\n### Export\nSupported export formats are\n* Pandas\n* CSV\n* R (using Feather)\n\n### Import\nImport currently only supports .xlsx files with some configuration.  \nSee for more information below.\n\n## Getting Started\n1. Install the package \n   * `pip install castoredc-api`\n   * `conda install -c conda-forge castoredc_api`\n   * `conda install -c reiniervl castoredc_api`\n2. Import the client\n3. Instantiate the client with your client-ID and client-secret (don't share these!) and url to the server.\n   * ID and secret: Account -\u003e Settings -\u003e Castor EDC API\n   * url: *region*.castoredc.com\n4. Link the client to your study with the study-ID\n   * ID: Study -\u003e Settings -\u003e Castor Study ID\n5. Use the wrapper functions to start working with your study.\n\nFor all implemented functions, see: https://data.castoredc.com/api#/\n\n```python\nfrom castoredc_api import CastorClient\n\n# Create a client with your credentials\nc = CastorClient('MYCLIENTID', \n                 'MYCLIENTSECRET', \n                 'data.castoredc.com')\n\n# Link the client to your study in the Castor EDC database\nc.link_study('MYSTUDYID')\n\n# Then you can interact with the API\n# Get all records\nc.all_records()\n\n# Create a new survey package\nc.create_survey_package_instance(survey_package_id=\"FAKESURVEY-PACKAGE-ID\",\n                                 record_id=\"TEST-RECORD\",\n                                 email_address=\"obviously@fakeemail.com\",\n                                 auto_send=True)\n```\n\n### Export\n1. Instantiate the CastorStudy with your credentials, study ID and server url.\n2. Use the Study functions to start working with your database\n\nFor exporting data: The endpoint that extracts data for the study can't be used if the authenticated user has a role within the study.  \nSee: https://data.castoredc.com/api#/export/get_study__study_id__export_data\n\n\n```python\nfrom castoredc_api import CastorStudy\n\n# Instantiate Study\nstudy = CastorStudy('MYCLIENTID', \n                    'MYCLIENTSECRET', \n                    'MYSTUDYID', \n                    'data.castoredc.com')\n\n# Export your study to pandas dataframes or CSV files\nstudy.export_to_dataframe()\nstudy.export_to_csv()\n\n# Data and structure mapping are automatically done on export, but you can also map these without exporting your data\n# Map your study data locally (also maps structure)\nstudy.map_data()\n\n# Map only your study structure locally\nstudy.map_structure()\n\n# After mapping data and/or structure, you can start working with your study\n# Get all reports\nstudy.get_all_report_forms()\n# Get all data points of a single record\nstudy.get_single_record('000011').get_all_data_points()\n```\n\n#### Data Formatting\nDate fields are returned as strings (dd-mm-yyyy)  \nDatetime fields are returned as strings (dd-mm-yyyy hh-mm)  \nNumeric fields are all returned as floats.\n\nThis can be changed by supplying the argument format_options when intialising the CastorStudy.  \nAllowed options are date, datetime, datetime_seconds and time.  \nSee https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior for formatting options.\n\n```python\nfrom castoredc_api import CastorStudy\n\n# Instantiate Study with different formatting settings\nstudy = CastorStudy('MYCLIENTID', \n                    'MYCLIENTSECRET', \n                    'MYSTUDYID', \n                    'data.castoredc.com', \n                    format_options={\n                      \"date\": \"%B %e %Y\",\n                      \"datetime\": \"%B %e %Y %I:%M %p\",\n                      \"datetime_seconds\": \"%B %e %Y %I:%M:%S %p\",\n                      \"time\": \"%I:%M %p\",\n                    })\n```\n\n#### Missing Data\nMissing data is mostly handled through pandas (NaN).\n\nUser-defined missing data is handled through its definitions in Castor.  \nFor numeric and text-like variables, these values are -95, -96, -97, -98 and -99.  \nFor datetime data, missing data values are with the years 2995, 2996, 2997, 2998, and 2999.  \n\n### Import\n1. Instantiate the CastorStudy with your credentials, study ID and server url.\n2. Format your data in the right format (see below)\n3. Create a link file to link external and Castor variables (see below)\n4. (Optional) Create a variable translation file to translate values and labels to Castor optiongroups (see below).\n5. (Optional) Create a merge file to merge multiple columns into one CastorField (see below).\n6. (Optional) Set date, datetime and time formatting to translate local format into Castor format (see below).\n7. Import your data with the import_data function.\n   * If label_data is set to true, it translates the string values to their integer values of the optiongroup in Castor.\n   * If set to false, it takes the integer values as is.\n\nData is validated against the Castor database, meaning that:\n* Existence of records and fields is checked\n* Numeric values are compared against allowed values (min \u0026 max)\n* Date(time) and time formats are compared against the specified format\n\n#### Synchronous Upload\nThe synchronous upload option uploads each row one by one.  \nWhen an Error is encountered or the upload finishes successfully, the program outputs the upload log to the output folder and stops.\n \n#### Asynchronous Upload\nThe asynchronous upload option uploads each row one by one.  \nThis is about 15-30 times faster than synchronous upload.  \nThe program does not stop if uploading a row encounters an error.  \nWhen the upload finishes, the program outputs the upload log to the output folder and stops.  \nError messages are stored in the output folder for debugging.\n\n#### Simple Example\n\n```python\nfrom castoredc_api import CastorStudy\nfrom castoredc_api import import_data\n\n# Create a Study with your credentials\nstudy = CastorStudy('MYCLIENTID',\n                    'MYCLIENTSECRET',\n                    'MYSTUDYID',\n                    'data.castoredc.com')\n\n# Import labelled study data\nimported_data = import_data(data_source_path=\"PATH/TO/YOUR/LABELLED/STUDY/DATA\",\n                            column_link_path=\"PATH/TO/YOUR/LINK/FILE\", \n                            study=study, \n                            label_data=True, \n                            target=\"Study\")\n\n# Import labelled study data (asynchronous)\nimported_data = import_data(data_source_path=\"PATH/TO/YOUR/LABELLED/STUDY/DATA\",\n                            column_link_path=\"PATH/TO/YOUR/LINK/FILE\", \n                            study=study, \n                            label_data=True, \n                            target=\"Study\",\n                            use_async=True)\n\n# Import non-labelled report data\nimported_data = import_data(data_source_path=\"PATH/TO/YOUR/REPORT/DATA\", \n                            column_link_path=\"PATH/TO/YOUR/LINK/FILE\",\n                            study=study, \n                            label_data=False, \n                            target=\"Report\", \n                            target_name=\"Medication\")\n\n# Import labelled survey data\nimported_data = import_data(data_source_path=\"PATH/TO/YOUR/LABELLED/SURVEY/DATA\",\n                            column_link_path=\"PATH/TO/YOUR/LINK/FILE\", \n                            study=study, \n                            label_data=True, \n                            target=\"Survey\",\n                            target_name=\"My first survey package\", \n                            email=\"python_wrapper@you-spam.com\")\n```\n#### Specifying the data structure\n#### Data files\nSee below and example_files/ for an examples.\n* Dates should be formatted as dd-mm-yyyy.\n* Datetime should be formatted as dd-mm-yyyy;hh:mm\n* Use semicolons for fields that allow multiple options (e.g. checkboxes)\n* If any value for a column is translated, all values should have a translation mapped (see below)\n\n##### Labels\nThe mg/4 weeks and mg/8 weeks under units will be imported to the med_other_unit fields as they do not match any option of the optiongroup, see link files.\n\n##### Example\n\n| patient | medication   | startdate  | stopdate   | dose | units      |\n| ------- | ------------ | ---------- | ---------- | ---- | ---------- |\n| 110001  | Azathioprine | 05-12-2019 | 05-12-2020 | 0.05 | g/day      |\n| 110002  | Vedolizumab  | 17-08-2018 | 17-09-2020 | 300  | mg/4 weeks |\n| 110003  | Ustekinumab  | 19-12-2017 | 03-06-2019 | 90   | mg/8 weeks |\n| 110004  | Thioguanine  | 25-04-2020 | 27-05-2021 | 15   | mg/day     |\n| 110005  | Tofacitinib  | 01-03-2020 | 31-12-2999 | 10   | mg/day     |\n\n##### Values\nThe non-integer variables under units will be imported to the med_other_unit fields as they do not match any optionvalue of the optiongroup, see link files.\n\n##### Example\n\n| patient | medication   | startdate  | stopdate   | dose | units      |\n| ------- | ------------ | ---------- | ---------- | ---- | ---------- |\n| 110001  | Azathioprine | 05-12-2019 | 05-12-2020 | 0.05 | 3          |\n| 110002  | Vedolizumab  | 17-08-2018 | 17-09-2020 | 300  | mg/4 weeks |\n| 110003  | Ustekinumab  | 19-12-2017 | 03-06-2019 | 90   | mg/8 weeks |\n| 110004  | Thioguanine  | 25-04-2020 | 27-05-2021 | 15   | 2          |\n| 110005  | Tofacitinib  | 01-03-2020 | 31-12-2999 | 10   | 2          |\n\n\n##### Link files\nLink files should be of the format as shown below.\nThe mapping is variable name in the Excel file -\u003e variable name in Castor.\nIf a variable in other is referenced twice in the Castor column, it means that it has a dependency in Castor.\n\nThis is a way to import data that has an \"other\" category, for example a radio question that reads:\n* A\n* B\n* C\n* Other\n\nIn which case selecting other opens a new text box to enter this information. \nThe second variable in the link_file should be this new text box.\n\nThis is treated in the following manner:\n* First, the data is mapped to the first variable referenced\n* For all data that could not be mapped to the first variable, the 'other' category is selected in the first variable\n* Then the data that could not be mapped is written to the second variable referenced.\n\n##### Example\n\n| other      | castor           |\n| ---------- | ---------------- |\n| patient    | record\\_id       |\n| medication | med\\_name        |\n| startdate  | med\\_start       |\n| stopdate   | med\\_stop        |\n| dose       | med\\_dose        |\n| units      | med\\_units       |\n| units      | med\\_other\\_unit |\n\n##### Translation files\nTranslation files link the optiongroup value or label from the external database to the optiongroups from Castor.\nValues are translated for all variables specified in the first column of the file.\n\nTwo situations can occur when a value is encountered for which no translation is given:\n* If a dependent field is specified (see link files): the value is not translated and imported to the dependent field.\n* If no dependent field is specified: the program gives an error. In this situation, every value that occurs in the external database needs to be mapped.\n\n##### Example\n| variable               | other                  | castor                              |\n| ---------------------- | ---------------------- | ----------------------------------- |\n| family disease history | none                   | None                                |\n| family disease history | don't know             | Unknown                             |\n| family disease history | deaf                   | Deafness                            |\n| family disease history | cardiomyopathy         | (Cardio)myopathy                    |\n| family disease history | encephalopathy         | Encephalopathy                      |\n| family disease history | diabetes               | Diabetes Mellitus                   |\n| family disease history | cardiovascular disease | Hypertension/Cardiovascular disease |\n| family disease history | thromboembolism        | Thrombosis                          |\n| family disease history | tumor                  | Malignancy                          |\n\n```python\nfrom castoredc_api import CastorStudy\nfrom castoredc_api import import_data\n\n# Create a Study with your credentials\nstudy = CastorStudy('MYCLIENTID',\n                    'MYCLIENTSECRET',\n                    'MYSTUDYID',\n                    'data.castoredc.com')\n\n# Import study data with a translation file\nimported_data = import_data(data_source_path=\"PATH/TO/YOUR/LABELLED/STUDY/DATA\",\n                            column_link_path=\"PATH/TO/YOUR/LINK/FILE\", \n                            study=study, \n                            label_data=True, \n                            target=\"Study\",\n                            translation_path=\"PATH/TO/YOUR/TRANSLATION/FILE\")\n```\n\n##### Merge files\nMerge files link the multiple columns from the external database to a single checkbox field in Castor.  \nFor each column from the external database specified under other_variable the value under other_value is mapped to the castor_value for the castor_variable.  \nIf specifying a merge file, note that castor_value is the new other variable for your link file (see below).  \nAll other_values not defined raise an Error.\nOnly supports many-to-one matching.\n\n##### Example\n\n###### Data File\n| patient | date baseline blood sample | baseline hemoglobin | factor V Leiden | datetime onset stroke | time onset trombectomy | year of birth | patient sex | patient race    | famhist\\_none | famhist\\_deaf | famhist\\_cardiomyopathy | famhist\\_encephalopathy | famhist\\_diabmell | famhist\\_cardiovasc | famhist\\_malignancy | famhist\\_unknown |\n| ------- | -------------------------- | ------------------- | --------------- | --------------------- | ---------------------- | ------------- | ----------- | --------------- | ------------- | ------------- | ----------------------- | ----------------------- | ----------------- | ------------------- | ------------------- | ---------------- |\n| 110001  | 16-03-2021                 | 8.3                 | 55;16-03-2021   | 16-03-2021;07:30      | 09:25                  | 1999          | Female      | Asian           | No            | No            | Yes                     | Yes                     | Yes               | No                  | No                  | No               |\n| 110002  | 17-03-2021                 | 7.2                 | 33;17-03-2021   | 17-03-2021;15:30      | 06:33                  | 1956          | Female      | African/black   | No            | Yes           | Yes                     | No                      | No                | No                  | No                  | No               |\n| 110003  | 16-03-2022                 | 9.1                 | \\-45;18-03-2022 | 18-03-2022;02:00      | 12:24                  | 1945          | Male        | Chinese         | Yes           | No            | No                      | No                      | No                | No                  | No                  | No               |\n| 110004  | 17-03-2022                 | 3.2                 | 28;19-03-2022   | 17-03-2022;21:43      | 23:23                  | 1933          | Male        | Caucasian/white | No            | No            | No                      | No                      | No                | Yes                 | Yes                 | No               |\n| 110005  | 16-03-2023                 | 10.3                | 5;20-03-2023    | 16-03-2023;07:22      | 08:14                  | 1921          | Female      | Hispanic        | No            | No            | No                      | No                      | No                | No                  | No                  | Yes              |\n\n###### Merge File\n\n| other\\_variable         | other\\_value | castor\\_variable | castor\\_value                       |\n| ----------------------- | ------------ | ---------------- | ----------------------------------- |\n| famhist\\_none           | Yes          | his\\_family      | None                                |\n| famhist\\_deaf           | Yes          | his\\_family      | Deafness                            |\n| famhist\\_cardiomyopathy | Yes          | his\\_family      | (Cardio)myopathy                    |\n| famhist\\_encephalopathy | Yes          | his\\_family      | Encephalopathy                      |\n| famhist\\_diabmell       | Yes          | his\\_family      | Diabetes Mellitus                   |\n| famhist\\_cardiovasc     | Yes          | his\\_family      | Hypertension/Cardiovascular disease |\n| famhist\\_malignancy     | Yes          | his\\_family      | Malignancy                          |\n| famhist\\_unknown        | Yes          | his\\_family      | Unknown                             |\n| famhist\\_none           | No           | his\\_family      |                                     |\n| famhist\\_deaf           | No           | his\\_family      |                                     |\n| famhist\\_cardiomyopathy | No           | his\\_family      |                                     |\n| famhist\\_encephalopathy | No           | his\\_family      |                                     |\n| famhist\\_diabmell       | No           | his\\_family      |                                     |\n| famhist\\_cardiovasc     | No           | his\\_family      |                                     |\n| famhist\\_malignancy     | No           | his\\_family      |                                     |\n| famhist\\_unknown        | No           | his\\_family      |                                     |\n\n###### Link File\n\n| other                      | castor             |\n| -------------------------- | ------------------ |\n| patient                    | record\\_id         |\n| date baseline blood sample | base\\_bl\\_date     |\n| baseline hemoglobin        | base\\_hb           |\n| factor V Leiden            | fac\\_V\\_leiden     |\n| datetime onset stroke      | onset\\_stroke      |\n| time onset trombectomy     | onset\\_trombectomy |\n| year of birth              | pat\\_birth\\_year   |\n| patient sex                | pat\\_sex           |\n| patient race               | pat\\_race          |\n| **his\\_family**            | **his\\_family**    |\n\n```python\nfrom castoredc_api import CastorStudy\nfrom castoredc_api import import_data\n\n# Create a Study with your credentials\nstudy = CastorStudy('MYCLIENTID',\n                    'MYCLIENTSECRET',\n                    'MYSTUDYID',\n                    'data.castoredc.com')\n\n# Import study data with a merge file\nimported_data = import_data(data_source_path=\"PATH/TO/YOUR/LABELLED/STUDY/DATA\",\n                            column_link_path=\"PATH/TO/YOUR/LINK/FILE\", \n                            study=study, \n                            label_data=True, \n                            target=\"Study\",\n                            merge_path=\"PATH/TO/YOUR/MERGE/FILE\")\n```\n\n#### Data Formatting\nStandard date formatting settings are the following.\nDate(time) and time fields should follow these formats in the Excel sheet to be uploaded.\n- Date = dd-mm-yyyy  \n- Datetime = dd-mm-yyyy;hh-mm\n- Time = hh:mm  \n- Decimal separator = . \n\nThese can be changed by supplying the argument format_options when calling create upload.  \nAllowed options are date, datetime, and time. Decimal separator cannot be changed.  \nSee https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior for formatting options.\n\n```python\nfrom castoredc_api import CastorStudy\nfrom castoredc_api import import_data\n\n# Create a Study with your credentials\nstudy = CastorStudy('MYCLIENTID',\n                    'MYCLIENTSECRET',\n                    'MYSTUDYID',\n                    'data.castoredc.com')\n\n# Import labelled study data with changed formats\nimported_data = import_data(data_source_path=\"PATH/TO/YOUR/LABELLED/STUDY/DATA\",\n                            column_link_path=\"PATH/TO/YOUR/LINK/FILE\", \n                            study=study, \n                            label_data=True, \n                            target=\"Study\",\n                            format_options={\n                               \"date\": \"%B %d %Y\",\n                               \"datetime\": \"%B %d %Y %I:%M %p\",\n                               \"time\": \"%I:%M %p\",\n                            })\n```\n## Prerequisites\n\n1. Python Version \u003e= 3.8\n2. See [requirements.txt](requirements.txt)\n\n## Known Issues\n\n1. Async import and export cannot be used in an IPython environment, see [this discussion](https://github.com/reiniervlinschoten/castoredc_api/pull/39#discussion_r740389868)\n2. Feather export is uncompressed, see [this issue](https://github.com/ContinuumIO/anaconda-issues/issues/12500)\n3. Device token and Econsent endpoints are untested. Use at your own risk.\n\n\n## Contributing\n\nPlease read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.\n\n## Running Tests\n\nWant to contribute to the testing suite? Or test possible changes you want to contribute?\nTests can be ran via two methods: on Github and on your local machine.\n\nOn Github: when you create a pull request for this project, Pytest automatically runs for the testing suite (see [pytest.yml](.github/workflows/pytest.yml)).\nIf you have added a whole new testing module, don't forget to add this to the pytest.yml file. Within the repository, applicable access rights have been set for the client.\nUse the following fixtures for the respective modules you want to test:\n* Testing API read endpoints: client\n* Testing API write endpoints: write_client\n* Testing output:\n  * For structure output to Python: integration_study \u0026 integration_study_format\n  * For data output to Python: integration_study_mapped \u0026 integration_study_format_mapped\n  * For data output to csv: output_data\n* Testing importing of data: import_study\n\nLocally: You can only run tests locally when you have read and write access to the correct Castor Studies. \nPlease send a message to the repository owner to ask for the correct access, with information on why.\nAccess and correct study IDs will then be given to run the tests.\n\n## Versioning\n\nWe use [SemVer](https://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/reiniervlinschoten/castoredc_api/tags). \n\n## Authors\n\n* **R.C.A. van Linschoten** - *Initial Development* - [Reinier van Linschoten](https://github.com/reiniervlinschoten)\n\nSee also the list of [contributors](https://github.com/reiniervlinschoten/castoredc_api/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details\n\n## Acknowledgments\n\n* Franciscus Gasthuis \u0026 Vlietland for making time available for development  \n* Castor EDC for support and code review\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freiniervlinschoten%2Fcastoredc_api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freiniervlinschoten%2Fcastoredc_api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freiniervlinschoten%2Fcastoredc_api/lists"}