|pypi| |actions| |codecov| |downloads|
edc-visit-schedule
------------------
Add longitudinal data collection schedules to your EDC project.
Installation
============
Add to settings:
.. code-block:: python
INSTALLED_APPS = [
...
'edc_visit_schedule.apps.AppConfig',
...
]
Overview
========
* A ``Visit Schedule`` lives in your app in ``visit_schedules.py``. Each app can declare and register one or more visit schedules in its ``visit_schedules`` module. Visit schedules are loaded when ``autodiscover`` is called from ``AppConfig``.
* A ``VisitSchedule`` contains ``Schedules`` which contain ``Visits`` which contain ``Crfs`` and ``Requisitions``.
* A ``schedule`` is effectively a "data collection schedule" where each contained ``visit`` represents a data collection timepoint.
* A subject is put on a ``schedule`` by the schedule's ``onschedule`` model and taken off by the schedule's ``offschedule`` model. In the example below we use models ``OnSchedule`` and ``OffSchedule`` to do this for schedule ``schedule1``.
Usage
=====
First, create a file ``visit_schedules.py`` in the root of your app where the visit schedule code below will live.
Next, declare lists of data ``Crfs`` and laboratory ``Requisitions`` to be completed during each visit. For simplicity, we assume that every visit has the same data collection requirement (not usually the case).
.. code-block:: python
from myapp.models import SubjectVisit, OnSchedule, OffSchedule, SubjectDeathReport, SubjectOffstudy
from edc_visit_schedule.site_visit_schedules import site_visit_schedules
from edc_visit_schedule.schedule import Schedule
from edc_visit_schedule.visit import Crf, Requisition, CrfCollection, RequisitionCollection
from edc_visit_schedule.visit_schedule import VisitSchedule
crfs = CrfCollection(
Crf(show_order=10, model='myapp.crfone'),
Crf(show_order=20, model='myapp.crftwo'),
Crf(show_order=30, model='myapp.crfthree'),
Crf(show_order=40, model='myapp.crffour'),
Crf(show_order=50, model='myapp.crffive'),
)
requisitions = RequisitionCollection(
Requisition(
show_order=10, model='myapp.subjectrequisition', panel_name='Research Blood Draw'),
Requisition(
show_order=20, model='myapp.subjectrequisition', panel_name='Viral Load'),
)
Create a new visit schedule:
.. code-block:: python
visit_schedule = VisitSchedule(
name='visit_schedule',
verbose_name='My Visit Schedule',
death_report_model=SubjectDeathReport,
offstudy_model=SubjectOffstudy)
Visit schedules contain ``Schedules`` so create a schedule:
.. code-block:: python
schedule = Schedule(
name='schedule',
onschedule_model='myapp.onschedule',
offschedule_model='myapp.offschedule',
consent_definitions=[consent_definition_v1])
About consent_definitions:
As you will see below, the ``schedule`` is a container for a data collection schedule of forms (CRFs and requisitions)
for a single study timepoint or ``visit``. Ethically, a subject's data may not be collected before the subject has signed and submitted the informed consent form (ICF).
``Schedule`` is configured with information about the ICF that covers the forms it contains. When a form for a subject is validated and submitted, the ``Schedule`` will
provide the consent_definition (or definitions) so that the calling object can confirm the subject is consented. The ICF is represented by
the class ``ConsentDefinition`` from ``edc_consent``.
See also class ``ConsentDefinition`` in ``edc_consent``.
Schedules contains visits, so declare some visits and add to the ``schedule``:
.. code-block:: python
visit0 = Visit(
code='1000',
title='Visit 1000',
timepoint=0,
rbase=relativedelta(days=0),
requisitions=requisitions,
crfs=crfs)
visit1 = Visit(
code='2000',
title='Visit 2000',
timepoint=1,
rbase=relativedelta(days=28),
requisitions=requisitions,
crfs=crfs)
schedule.add_visit(visit=visit0)
schedule.add_visit(visit=visit1)
Add the schedule to your visit schedule:
.. code-block:: python
schedule = visit_schedule.add_schedule(schedule)
Register the visit schedule with the site registry:
.. code-block:: python
visit_schedules.register(visit_schedule)
When Django loads, the visit schedule class will be available in the global ``site_visit_schedules``.
The ``site_visit_schedules`` has a number of methods to help query the visit schedule and some related data.
**Note:** The ``schedule`` above was declared with ``onschedule_model=OnSchedule``. An on-schedule model uses the ``CreateAppointmentsMixin`` from ``edc_appointment``. On ``onschedule.save()`` the method ``onschedule.create_appointments`` is called. This method uses the visit schedule information to create the appointments as per the visit data in the schedule. See also ``edc_appointment``.
OnSchedule and OffSchedule models
=================================
Two models mixins are required for the on-schedule and off-schedule models, ``OnScheduleModelMixin`` and ``OffScheduleModelMixin``. OnSchedule/OffSchedule models are specific to a ``schedule``. The ``visit_schedule_name`` and ``schedule_name`` are declared on the model's ``Meta`` class attribute ``visit_schedule_name``.
For example:
.. code-block:: python
class OnSchedule(OnScheduleModelMixin, BaseUuidModel):
"""A model used by the system. Auto-completed by subject_consent."""
objects = SubjectIdentifierManager()
on_site = CurrentSiteManager()
history = HistoricalRecords()
class Meta(OnScheduleModelMixin.Meta, BaseUuidModel.Meta):
pass
class OffSchedule(ActionModelMixin, OffScheduleModelMixin, BaseUuidModel):
action_name = OFFSCHEDULE_ACTION
class Meta(OffScheduleModelMixin.Meta, BaseUuidModel.Meta):
verbose_name = "Off-schedule"
verbose_name_plural = "Off-schedule"
.. |pypi| image:: https://img.shields.io/pypi/v/edc-visit-schedule.svg
:target: https://pypi.python.org/pypi/edc-visit-schedule
.. |actions| image:: https://github.com/clinicedc/edc-visit-schedule/actions/workflows/build.yml/badge.svg
:target: https://github.com/clinicedc/edc-visit-schedule/actions/workflows/build.yml
.. |codecov| image:: https://codecov.io/gh/clinicedc/edc-visit-schedule/branch/develop/graph/badge.svg
:target: https://codecov.io/gh/clinicedc/edc-visit-schedule
.. |downloads| image:: https://pepy.tech/badge/edc-visit-schedule
:target: https://pepy.tech/project/edc-visit-schedule
Raw data
{
"_id": null,
"home_page": "https://github.com/clinicedc/edc-visit-schedule",
"name": "edc-visit-schedule",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "django edc visit schedule, data collection schedule, clinicedc, clinical trials",
"author": "Erik van Widenfelt",
"author_email": "ew2789@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/73/78/7c9265f612acf3675ead390e33379a7ddd7515a6440d2ce12ed031223888/edc_visit_schedule-4.0.8.tar.gz",
"platform": null,
"description": "|pypi| |actions| |codecov| |downloads|\n\nedc-visit-schedule\n------------------\n\nAdd longitudinal data collection schedules to your EDC project.\n\n\nInstallation\n============\n\nAdd to settings:\n\n.. code-block:: python\n\n INSTALLED_APPS = [\n ...\n 'edc_visit_schedule.apps.AppConfig',\n ...\n ]\n\nOverview\n========\n\n* A ``Visit Schedule`` lives in your app in ``visit_schedules.py``. Each app can declare and register one or more visit schedules in its ``visit_schedules`` module. Visit schedules are loaded when ``autodiscover`` is called from ``AppConfig``.\n* A ``VisitSchedule`` contains ``Schedules`` which contain ``Visits`` which contain ``Crfs`` and ``Requisitions``.\n* A ``schedule`` is effectively a \"data collection schedule\" where each contained ``visit`` represents a data collection timepoint.\n* A subject is put on a ``schedule`` by the schedule's ``onschedule`` model and taken off by the schedule's ``offschedule`` model. In the example below we use models ``OnSchedule`` and ``OffSchedule`` to do this for schedule ``schedule1``.\n\nUsage\n=====\n\nFirst, create a file ``visit_schedules.py`` in the root of your app where the visit schedule code below will live.\n\n\nNext, declare lists of data ``Crfs`` and laboratory ``Requisitions`` to be completed during each visit. For simplicity, we assume that every visit has the same data collection requirement (not usually the case).\n\n.. code-block:: python\n\n from myapp.models import SubjectVisit, OnSchedule, OffSchedule, SubjectDeathReport, SubjectOffstudy\n\n from edc_visit_schedule.site_visit_schedules import site_visit_schedules\n from edc_visit_schedule.schedule import Schedule\n from edc_visit_schedule.visit import Crf, Requisition, CrfCollection, RequisitionCollection\n from edc_visit_schedule.visit_schedule import VisitSchedule\n\n\n crfs = CrfCollection(\n Crf(show_order=10, model='myapp.crfone'),\n Crf(show_order=20, model='myapp.crftwo'),\n Crf(show_order=30, model='myapp.crfthree'),\n Crf(show_order=40, model='myapp.crffour'),\n Crf(show_order=50, model='myapp.crffive'),\n )\n\n requisitions = RequisitionCollection(\n Requisition(\n show_order=10, model='myapp.subjectrequisition', panel_name='Research Blood Draw'),\n Requisition(\n show_order=20, model='myapp.subjectrequisition', panel_name='Viral Load'),\n )\n\nCreate a new visit schedule:\n\n.. code-block:: python\n\n visit_schedule = VisitSchedule(\n name='visit_schedule',\n verbose_name='My Visit Schedule',\n death_report_model=SubjectDeathReport,\n offstudy_model=SubjectOffstudy)\n\n\nVisit schedules contain ``Schedules`` so create a schedule:\n\n.. code-block:: python\n\n schedule = Schedule(\n name='schedule',\n onschedule_model='myapp.onschedule',\n offschedule_model='myapp.offschedule',\n consent_definitions=[consent_definition_v1])\n\nAbout consent_definitions:\n As you will see below, the ``schedule`` is a container for a data collection schedule of forms (CRFs and requisitions)\n for a single study timepoint or ``visit``. Ethically, a subject's data may not be collected before the subject has signed and submitted the informed consent form (ICF).\n ``Schedule`` is configured with information about the ICF that covers the forms it contains. When a form for a subject is validated and submitted, the ``Schedule`` will\n provide the consent_definition (or definitions) so that the calling object can confirm the subject is consented. The ICF is represented by\n the class ``ConsentDefinition`` from ``edc_consent``.\n\n See also class ``ConsentDefinition`` in ``edc_consent``.\n\nSchedules contains visits, so declare some visits and add to the ``schedule``:\n\n.. code-block:: python\n\n visit0 = Visit(\n code='1000',\n title='Visit 1000',\n timepoint=0,\n rbase=relativedelta(days=0),\n requisitions=requisitions,\n crfs=crfs)\n\n visit1 = Visit(\n code='2000',\n title='Visit 2000',\n timepoint=1,\n rbase=relativedelta(days=28),\n requisitions=requisitions,\n crfs=crfs)\n\n schedule.add_visit(visit=visit0)\n schedule.add_visit(visit=visit1)\n\n\nAdd the schedule to your visit schedule:\n\n.. code-block:: python\n\n schedule = visit_schedule.add_schedule(schedule)\n\nRegister the visit schedule with the site registry:\n\n.. code-block:: python\n\n visit_schedules.register(visit_schedule)\n\nWhen Django loads, the visit schedule class will be available in the global ``site_visit_schedules``.\n\nThe ``site_visit_schedules`` has a number of methods to help query the visit schedule and some related data.\n\n **Note:** The ``schedule`` above was declared with ``onschedule_model=OnSchedule``. An on-schedule model uses the ``CreateAppointmentsMixin`` from ``edc_appointment``. On ``onschedule.save()`` the method ``onschedule.create_appointments`` is called. This method uses the visit schedule information to create the appointments as per the visit data in the schedule. See also ``edc_appointment``.\n\nOnSchedule and OffSchedule models\n=================================\n\nTwo models mixins are required for the on-schedule and off-schedule models, ``OnScheduleModelMixin`` and ``OffScheduleModelMixin``. OnSchedule/OffSchedule models are specific to a ``schedule``. The ``visit_schedule_name`` and ``schedule_name`` are declared on the model's ``Meta`` class attribute ``visit_schedule_name``.\n\nFor example:\n\n.. code-block:: python\n\n class OnSchedule(OnScheduleModelMixin, BaseUuidModel):\n\n \"\"\"A model used by the system. Auto-completed by subject_consent.\"\"\"\n\n objects = SubjectIdentifierManager()\n\n on_site = CurrentSiteManager()\n\n history = HistoricalRecords()\n\n class Meta(OnScheduleModelMixin.Meta, BaseUuidModel.Meta):\n pass\n\n\n class OffSchedule(ActionModelMixin, OffScheduleModelMixin, BaseUuidModel):\n\n action_name = OFFSCHEDULE_ACTION\n\n class Meta(OffScheduleModelMixin.Meta, BaseUuidModel.Meta):\n verbose_name = \"Off-schedule\"\n verbose_name_plural = \"Off-schedule\"\n\n\n.. |pypi| image:: https://img.shields.io/pypi/v/edc-visit-schedule.svg\n :target: https://pypi.python.org/pypi/edc-visit-schedule\n\n.. |actions| image:: https://github.com/clinicedc/edc-visit-schedule/actions/workflows/build.yml/badge.svg\n :target: https://github.com/clinicedc/edc-visit-schedule/actions/workflows/build.yml\n\n.. |codecov| image:: https://codecov.io/gh/clinicedc/edc-visit-schedule/branch/develop/graph/badge.svg\n :target: https://codecov.io/gh/clinicedc/edc-visit-schedule\n\n.. |downloads| image:: https://pepy.tech/badge/edc-visit-schedule\n :target: https://pepy.tech/project/edc-visit-schedule\n",
"bugtrack_url": null,
"license": "GPL license, see LICENSE",
"summary": "Base classes for visit reports/tracking in clinicedc/edc",
"version": "4.0.8",
"project_urls": {
"Homepage": "https://github.com/clinicedc/edc-visit-schedule"
},
"split_keywords": [
"django edc visit schedule",
" data collection schedule",
" clinicedc",
" clinical trials"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9c1dde84c67125d801d07eb67ebdd96301d75b65a8c318d38616e31ad153decd",
"md5": "6fac4bedf70c33c80f4d8fce48eb2dd9",
"sha256": "1a6a8f694a9b1f004487d808b43e082d80a752f525d82276235ef0225a38207f"
},
"downloads": -1,
"filename": "edc_visit_schedule-4.0.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6fac4bedf70c33c80f4d8fce48eb2dd9",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 118930,
"upload_time": "2025-01-25T18:46:31",
"upload_time_iso_8601": "2025-01-25T18:46:31.286781Z",
"url": "https://files.pythonhosted.org/packages/9c/1d/de84c67125d801d07eb67ebdd96301d75b65a8c318d38616e31ad153decd/edc_visit_schedule-4.0.8-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "73787c9265f612acf3675ead390e33379a7ddd7515a6440d2ce12ed031223888",
"md5": "15a4b1d890e80aaa74b18e29d60ab40a",
"sha256": "affc8f980e160d2fd711329f54042519a5617ec0fba5d8d44e0beaafb3ff3cdf"
},
"downloads": -1,
"filename": "edc_visit_schedule-4.0.8.tar.gz",
"has_sig": false,
"md5_digest": "15a4b1d890e80aaa74b18e29d60ab40a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 83787,
"upload_time": "2025-01-25T18:46:34",
"upload_time_iso_8601": "2025-01-25T18:46:34.816127Z",
"url": "https://files.pythonhosted.org/packages/73/78/7c9265f612acf3675ead390e33379a7ddd7515a6440d2ce12ed031223888/edc_visit_schedule-4.0.8.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-25 18:46:34",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "clinicedc",
"github_project": "edc-visit-schedule",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "edc-visit-schedule"
}