|pypi| |actions| |coverage|
edc-identifier
--------------
Add research subject identifiers and other useful identifiers to your project
Installation
------------
Add to settings:
.. code-block:: python
INSTALLED_APPS = [
...
'edc_identifier.apps.AppConfig',
...
]
Identifiers for research subjects
---------------------------------
Create subject identifiers.
.. code-block:: python
from edc_identifier.subject_identifier import SubjectIdentifier
subject_identifier = SubjectIdentifier(
subject_type_name='subject',
model='edc_example.enrollment',
protocol='000',
device_id='99',
study_site='40')
>>> subject_identifier.identifier
'000-40990001-6'
Maternal and Infant Identifiers
-------------------------------
See also, ``edc_pregnancy`` model mixins ``DeliveryMixin``, ``BirthMixin``.
For example:
.. code-block:: python
from edc_identifier.maternal_identifier import MaternalIdentifier
maternal_identifier = MaternalIdentifier(
subject_type_name='maternal',
model='edc_example.enrollment',
study_site='40',
last_name='Carter')
>>> maternal_identifier.identifier
'000-40990001-6'
Add infants
.. code-block:: python
>>> maternal_identifier.deliver(2, model='edc_example.maternallabdel')
>>> [infant.identifier for infant in maternal_identifier.infants]
['000-40990001-6-25', '000-40990001-6-26']
``maternal_identifier.infants`` is a list of ``InfantIdentifier`` instances
Reload class:
.. code-block:: python
>>> maternal_identifier = MaternalIdentifier(identifier='000-40990001-6')
>>> maternal_identifier.identifier
'000-40990001-6'
>>> [infant.identifier for infant in maternal_identifier.infants]
['000-40990001-6-25', '000-40990001-6-26']
Only allocate an identifier to one infant of twins:
.. code-block:: python
>>> maternal_identifier.deliver(2, model='edc_example.maternallabdel', birth_orders='2')
>>> [infant.identifier for infant in maternal_identifier.infants]
[None, '000-40990001-6-26']
Of triplets, allocate identifiers to the 2nd and 3rd infants only:
.. code-block:: python
>>> maternal_identifier.deliver(3, model='edc_example.maternallabdel', birth_orders='2,3')
>>> [infant.identifier for infant in maternal_identifier.infants]
[None, '000-40990001-6-37', '000-40990001-6-38']
Research subject identifier classes can create a Registered Subject instance
See also ``edc_registration``
``SubjectIdentifier`` by default does not create a ``RegisteredSubject`` instance unless ``create_registration=True``.
By default, ``MaternalIdentifier`` and ``InfantIdentifier`` create ``RegisteredSubject`` instances that can be updated with full details later with the Delivery and Birth models. Continuing from above:
.. code-block:: python
maternal_identifier = MaternalIdentifier(identifier='000-40990001-6')
maternal_identifier.deliver(1, model='edc_example.maternallabdel', create_registration=True)
# mother
>>> RegisteredSubject.objects.get(subject_identifier='000-40990001-6')
<RegisteredSubject '000-40990001-6'>
# infant is linked to the mother
>>> RegisteredSubject.objects.get(linked_identifier='000-40990001-6')
<RegisteredSubject '000-40990001-6-10'>
# infant
>>> obj = RegisteredSubject.objects.get(subject_identifier='000-40990001-6-10')
>>> obj.first_name
'Baby1Carter' ## generates a temp name until Birth form is added with complete information.
>>> obj.relative_identifier
'000-40990001-6'
Subject type "Caps" are enforced by the research subject identifier classes
See also ``edc_protocol``
Limits on the number of identifiers that can be allocated per subject type are enforced when identifiers are created. ``edc_identifier`` reads the "caps" from ``edc_protocol.apps.AppConfig`` linking the subject type, e.g. ``subject``, or ``maternal`` or ``infant``, to the relevant cap and not allowing the number of allocated identifiers to exceed the cap.
(Subject type "Caps" still working? needs to be verified)
Numeric Identifiers
-------------------
The numeric identifier uses a check-digit and may have a separator if specified.
.. code-block:: python
from edc_identifier import NumericIdentifier
class MyIdentifier(NumericIdentifier):
pass
>>> id = MyIdentifier(None)
>>> id
MyIdentifier('00000000018')
>>> next(id)
'00000000026'
>>> next(id)
'00000000034'
# add a separator
class MyIdentifier(NumericIdentifier):
identifier_pattern = r'^[0-9]{4}\-[0-9]{4}\-[0-9]{4}$'
checkdigit_pattern = r'^\-[0-9]{1}$'
separator = '-'
seed = ['3200-0000-0000']
>>> id = MyIdentifier(None)
>>> id
MyIdentifier('3200-0000-0001-1')
>>> next(id)
'3200-0000-0002-9'
>>> next(id)
'3200-0000-0003-7'
# start from the last identifier, increment is immediate and automatic
>>> id = MyIdentifier('3200-0000-3222-0')
>>> id
MyIdentifier('3200-0000-3223-8')
Alphanumeric Identifiers
------------------------
.. code-block:: python
from edc_identifier import AlphanumericIdentifier
class MyIdentifier(AlphanumericIdentifier):
alpha_pattern = r'^[A-Z]{3}$'
numeric_pattern = r'^[0-9]{4}$'
seed = ['AAA', '0000']
>>> id = MyIdentifier(None)
>>> id
MyIdentifier('AAA00015')
Your identifier will starts with 'AAA0001' plus the checkdigit "5". Subsequent calls to next increment like this:
.. code-block:: python
>>> print(next(id))
AAA00023
>>> print(next(id))
AAA00031
>>> print(next(id))
AAA00049
The identifier increments on the numeric sequence then the alpha:
.. code-block:: python
>>> id = MyIdentifier('AAA99991)
>>> id
MyIdentifier('AAB00013')
>>> next(id)
'AAB00021'
>>> next(id)
'AAB00039'
>>> next(id)
'AAB00047'
>>> id = MyIdentifier('AAB99999')
>>> id
MyIdentifier('AAC00010')
...
See ``getresults-receive`` for sample usage with ``settings`` and a ``History`` model.
Short Identifiers
-----------------
Creates a small identifier that is almost unique, for example, across 25 Edc devices in a community. We use these as sample requisition identifiers that are transcribed manually onto a tube from the Edc screen in a household. Once the sample is received at the local lab it is allocated a laboratory-wide unique specimen identifier.
.. code-block:: python
from edc_identifier import ShortIdentifier
>>> ShortIdentifier()
ShortIdentifier('46ZZ2')
Add a static prefix -- ``prefix(2) + identifier(5)``:
.. code-block:: python
from edc_identifier import ShortIdentifier
class MyIdentifier(ShortIdentifier):
prefix_pattern = r'^[0-9]{2}$'
>>> options = {'prefix': 22}
>>> id = MyIdentifier(options=options)
>>> id
MyIdentifier('22UYMBT')
>>> next(id)
'22KM84G'
Add a checkdigit -- ``prefix(2) + identifier(5) + checkdigit(1)``:
.. code-block:: python
from edc_identifier import ShortIdentifier
class MyIdentifier(ShortIdentifier):
prefix_pattern = r'^[0-9]{2}$'
checkdigit_pattern = r'^[0-9]{1}$'
>>> options = {'prefix': 22}
>>> id = MyIdentifier(options=options)
>>> id
MyIdentifier('223GF8A3')
>>> next(id)
'22DXVW23'
We use this in edc-quota to get a confirmation code:
.. code-block:: python
from edc_identifier import ShortIdentifier
class ConfirmationCode(ShortIdentifier):
identifier_type = 'confirmation'
prefix_pattern = ''
>>> code = ConfirmationCode()
>>> print(code)
CAT33
>>> next(code)
3FU7D
Add more to the prefix, such as device code and community code.
.. code-block:: python
from edc_identifier.short_identifier import ShortIdentifier
class RequisitionIdentifier(ShortIdentifier):
identifier_type = 'requisition'
prefix_pattern = r'^[0-9]{4}$'
template = '{device_id}{community_id}{random_string}'
@property
def options(self):
if 'prefix' not in self._options:
self._options.update(
{'prefix': str(self._options.get('device_id')) + str(self._options.get('community_id'))})
return self._options
>>> options = {'device_id': 22, 'community_id': '12'}
>>> id = RequisitionIdentifier(options=options)
>>> id
RequisitionIdentifier('22126MZXD')
>>> next(id)
'2212Y899C'
... if you prefer not to use the ``IdentifierHistory`` model, for example, if you are filling in a model field on ``save()``:
.. code-block:: python
from my_app.models import Requisition
class RequisitionIdentifier(ShortIdentifier):
identifier_type = 'requisition'
requisition_model = Requisition
def is_duplicate(self, identifier):
try:
self.requisition_model.get(requisition_identifier=identifier)
return True
except self.requisition_model.DoesNotExist:
pass
return False
def update_history(self):
pass
Batch Identifier
----------------
To have an identifier prefixed by the current date stamp:
.. code-block:: python
from edc_identifier.batch_identifier import BatchIdentifier
>>> datetime.today().strftime('%Y%m%d)
20150817
>>> id = BatchIdentifier()
>>> id
BatchIdentifier('201508170001')
>>> next(id)
'201508170002'
.. |pypi| image:: https://img.shields.io/pypi/v/edc-identifier.svg
:target: https://pypi.python.org/pypi/edc-identifier
.. |actions| image:: https://github.com/clinicedc/edc-identifier/actions/workflows/build.yml/badge.svg
:target: https://github.com/clinicedc/edc-identifier/actions/workflows/build.yml
.. |coverage| image:: https://coveralls.io/repos/github/clinicedc/edc-identifier/badge.svg?branch=develop
:target: https://coveralls.io/github/clinicedc/edc-identifier?branch=develop
Raw data
{
"_id": null,
"home_page": "https://github.com/clinicedc/edc-identifier",
"name": "edc-identifier",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": "",
"keywords": "django Edc participant identifier,clinicedc,clinical trials",
"author": "Erik van Widenfelt",
"author_email": "ew2789@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/ef/c4/7456981db9d564ef80e63939ab1feef90b688762da271fc41bfb2e1deb13/edc-identifier-0.3.36.tar.gz",
"platform": null,
"description": "|pypi| |actions| |coverage|\n\nedc-identifier\n--------------\n\nAdd research subject identifiers and other useful identifiers to your project\n\nInstallation\n------------\n\nAdd to settings:\n\n.. code-block:: python\n\n INSTALLED_APPS = [\n ...\n 'edc_identifier.apps.AppConfig',\n ...\n ]\n\nIdentifiers for research subjects\n---------------------------------\n\nCreate subject identifiers.\n\n.. code-block:: python\n\n from edc_identifier.subject_identifier import SubjectIdentifier\n\n subject_identifier = SubjectIdentifier(\n subject_type_name='subject',\n model='edc_example.enrollment',\n protocol='000',\n device_id='99',\n study_site='40')\n >>> subject_identifier.identifier\n '000-40990001-6'\n\n\nMaternal and Infant Identifiers\n-------------------------------\n\nSee also, ``edc_pregnancy`` model mixins ``DeliveryMixin``, ``BirthMixin``.\n\nFor example:\n\n.. code-block:: python\n\n from edc_identifier.maternal_identifier import MaternalIdentifier\n\n maternal_identifier = MaternalIdentifier(\n subject_type_name='maternal',\n model='edc_example.enrollment',\n study_site='40',\n last_name='Carter')\n\n >>> maternal_identifier.identifier\n '000-40990001-6'\n\nAdd infants\n\n.. code-block:: python\n\n >>> maternal_identifier.deliver(2, model='edc_example.maternallabdel')\n >>> [infant.identifier for infant in maternal_identifier.infants]\n ['000-40990001-6-25', '000-40990001-6-26']\n\n``maternal_identifier.infants`` is a list of ``InfantIdentifier`` instances\n\nReload class:\n\n.. code-block:: python\n\n >>> maternal_identifier = MaternalIdentifier(identifier='000-40990001-6')\n >>> maternal_identifier.identifier\n '000-40990001-6'\n >>> [infant.identifier for infant in maternal_identifier.infants]\n ['000-40990001-6-25', '000-40990001-6-26']\n\nOnly allocate an identifier to one infant of twins:\n\n.. code-block:: python\n\n >>> maternal_identifier.deliver(2, model='edc_example.maternallabdel', birth_orders='2')\n >>> [infant.identifier for infant in maternal_identifier.infants]\n [None, '000-40990001-6-26']\n\nOf triplets, allocate identifiers to the 2nd and 3rd infants only:\n\n.. code-block:: python\n\n >>> maternal_identifier.deliver(3, model='edc_example.maternallabdel', birth_orders='2,3')\n >>> [infant.identifier for infant in maternal_identifier.infants]\n [None, '000-40990001-6-37', '000-40990001-6-38']\n\n\nResearch subject identifier classes can create a Registered Subject instance\n\nSee also ``edc_registration``\n\n``SubjectIdentifier`` by default does not create a ``RegisteredSubject`` instance unless ``create_registration=True``.\n\nBy default, ``MaternalIdentifier`` and ``InfantIdentifier`` create ``RegisteredSubject`` instances that can be updated with full details later with the Delivery and Birth models. Continuing from above:\n\n.. code-block:: python\n\n maternal_identifier = MaternalIdentifier(identifier='000-40990001-6')\n maternal_identifier.deliver(1, model='edc_example.maternallabdel', create_registration=True)\n\n # mother\n >>> RegisteredSubject.objects.get(subject_identifier='000-40990001-6')\n <RegisteredSubject '000-40990001-6'>\n\n # infant is linked to the mother\n >>> RegisteredSubject.objects.get(linked_identifier='000-40990001-6')\n <RegisteredSubject '000-40990001-6-10'>\n\n # infant\n >>> obj = RegisteredSubject.objects.get(subject_identifier='000-40990001-6-10')\n >>> obj.first_name\n 'Baby1Carter' ## generates a temp name until Birth form is added with complete information.\n >>> obj.relative_identifier\n '000-40990001-6'\n\n\nSubject type \"Caps\" are enforced by the research subject identifier classes\n\nSee also ``edc_protocol``\n\nLimits on the number of identifiers that can be allocated per subject type are enforced when identifiers are created. ``edc_identifier`` reads the \"caps\" from ``edc_protocol.apps.AppConfig`` linking the subject type, e.g. ``subject``, or ``maternal`` or ``infant``, to the relevant cap and not allowing the number of allocated identifiers to exceed the cap.\n\n(Subject type \"Caps\" still working? needs to be verified)\n\nNumeric Identifiers\n-------------------\n\nThe numeric identifier uses a check-digit and may have a separator if specified.\n\n.. code-block:: python\n\n\tfrom edc_identifier import NumericIdentifier\n\n\tclass MyIdentifier(NumericIdentifier):\n\t\tpass\n\n\t>>> id = MyIdentifier(None)\n\t>>> id\n\tMyIdentifier('00000000018')\n\t>>> next(id)\n\t'00000000026'\n\t>>> next(id)\n\t'00000000034'\n\n\n\t# add a separator\n\tclass MyIdentifier(NumericIdentifier):\n \tidentifier_pattern = r'^[0-9]{4}\\-[0-9]{4}\\-[0-9]{4}$'\n \tcheckdigit_pattern = r'^\\-[0-9]{1}$'\n \tseparator = '-'\n \tseed = ['3200-0000-0000']\n\n\t>>> id = MyIdentifier(None)\n\t>>> id\n\tMyIdentifier('3200-0000-0001-1')\n\t>>> next(id)\n\t'3200-0000-0002-9'\n\t>>> next(id)\n\t'3200-0000-0003-7'\n\n\t# start from the last identifier, increment is immediate and automatic\n\t>>> id = MyIdentifier('3200-0000-3222-0')\n\t>>> id\n\tMyIdentifier('3200-0000-3223-8')\n\n\nAlphanumeric Identifiers\n------------------------\n\n.. code-block:: python\n\n\tfrom edc_identifier import AlphanumericIdentifier\n\n\tclass MyIdentifier(AlphanumericIdentifier):\n\t\talpha_pattern = r'^[A-Z]{3}$'\n\t\tnumeric_pattern = r'^[0-9]{4}$'\n\t\tseed = ['AAA', '0000']\n\n\t>>> id = MyIdentifier(None)\n\t>>> id\n\tMyIdentifier('AAA00015')\n\nYour identifier will starts with 'AAA0001' plus the checkdigit \"5\". Subsequent calls to next increment like this:\n\n.. code-block:: python\n\n\t>>> print(next(id))\n\tAAA00023\n\t>>> print(next(id))\n\tAAA00031\n\t>>> print(next(id))\n\tAAA00049\n\n\nThe identifier increments on the numeric sequence then the alpha:\n\n.. code-block:: python\n\n\t>>> id = MyIdentifier('AAA99991)\n\t>>> id\n\tMyIdentifier('AAB00013')\n\n\t>>> next(id)\n\t'AAB00021'\n\t>>> next(id)\n\t'AAB00039'\n\t>>> next(id)\n\t'AAB00047'\n\n\t>>> id = MyIdentifier('AAB99999')\n\t>>> id\n\tMyIdentifier('AAC00010')\n\t...\n\nSee ``getresults-receive`` for sample usage with ``settings`` and a ``History`` model.\n\nShort Identifiers\n-----------------\n\nCreates a small identifier that is almost unique, for example, across 25 Edc devices in a community. We use these as sample requisition identifiers that are transcribed manually onto a tube from the Edc screen in a household. Once the sample is received at the local lab it is allocated a laboratory-wide unique specimen identifier.\n\n.. code-block:: python\n\n from edc_identifier import ShortIdentifier\n\n >>> ShortIdentifier()\n ShortIdentifier('46ZZ2')\n\nAdd a static prefix -- ``prefix(2) + identifier(5)``:\n\n.. code-block:: python\n\n\tfrom edc_identifier import ShortIdentifier\n\n\tclass MyIdentifier(ShortIdentifier):\n \tprefix_pattern = r'^[0-9]{2}$'\n\n >>> options = {'prefix': 22}\n >>> id = MyIdentifier(options=options)\n\t>>> id\n\tMyIdentifier('22UYMBT')\n\t>>> next(id)\n\t'22KM84G'\n\nAdd a checkdigit -- ``prefix(2) + identifier(5) + checkdigit(1)``:\n\n.. code-block:: python\n\n\tfrom edc_identifier import ShortIdentifier\n\n\tclass MyIdentifier(ShortIdentifier):\n \tprefix_pattern = r'^[0-9]{2}$'\n \tcheckdigit_pattern = r'^[0-9]{1}$'\n\n >>> options = {'prefix': 22}\n >>> id = MyIdentifier(options=options)\n\t>>> id\n\tMyIdentifier('223GF8A3')\n\t>>> next(id)\n\t'22DXVW23'\n\nWe use this in edc-quota to get a confirmation code:\n\n.. code-block:: python\n\n\tfrom edc_identifier import ShortIdentifier\n\n\tclass ConfirmationCode(ShortIdentifier):\n\n\t identifier_type = 'confirmation'\n\t prefix_pattern = ''\n\n\t>>> code = ConfirmationCode()\n\t>>> print(code)\n\tCAT33\n\t>>> next(code)\n\t3FU7D\n\nAdd more to the prefix, such as device code and community code.\n\n.. code-block:: python\n\n\tfrom edc_identifier.short_identifier import ShortIdentifier\n\n\tclass RequisitionIdentifier(ShortIdentifier):\n\n\t\tidentifier_type = 'requisition'\n\t\tprefix_pattern = r'^[0-9]{4}$'\n\t\ttemplate = '{device_id}{community_id}{random_string}'\n\n\t\t@property\n\t\tdef options(self):\n\t\t\tif 'prefix' not in self._options:\n\t\t\t\tself._options.update(\n\t\t\t\t\t{'prefix': str(self._options.get('device_id')) + str(self._options.get('community_id'))})\n\t\t\treturn self._options\n\n >>> options = {'device_id': 22, 'community_id': '12'}\n >>> id = RequisitionIdentifier(options=options)\n\t>>> id\n\tRequisitionIdentifier('22126MZXD')\n\t>>> next(id)\n\t'2212Y899C'\n\n... if you prefer not to use the ``IdentifierHistory`` model, for example, if you are filling in a model field on ``save()``:\n\n.. code-block:: python\n\n\tfrom my_app.models import Requisition\n\n\tclass RequisitionIdentifier(ShortIdentifier):\n\n\t identifier_type = 'requisition'\n\t requisition_model = Requisition\n\n\t def is_duplicate(self, identifier):\n\t try:\n\t self.requisition_model.get(requisition_identifier=identifier)\n\t return True\n\t except self.requisition_model.DoesNotExist:\n\t pass\n\t return False\n\n\t\tdef update_history(self):\n\t\t\tpass\n\n\nBatch Identifier\n----------------\n\nTo have an identifier prefixed by the current date stamp:\n\n\n.. code-block:: python\n\n\tfrom edc_identifier.batch_identifier import BatchIdentifier\n\n\t>>> datetime.today().strftime('%Y%m%d)\n\t20150817\n\t>>> id = BatchIdentifier()\n\t>>> id\n\tBatchIdentifier('201508170001')\n\t>>> next(id)\n\t'201508170002'\n\n\n.. |pypi| image:: https://img.shields.io/pypi/v/edc-identifier.svg\n :target: https://pypi.python.org/pypi/edc-identifier\n\n.. |actions| image:: https://github.com/clinicedc/edc-identifier/actions/workflows/build.yml/badge.svg\n :target: https://github.com/clinicedc/edc-identifier/actions/workflows/build.yml\n\n.. |coverage| image:: https://coveralls.io/repos/github/clinicedc/edc-identifier/badge.svg?branch=develop\n :target: https://coveralls.io/github/clinicedc/edc-identifier?branch=develop\n",
"bugtrack_url": null,
"license": "GPL license, see LICENSE",
"summary": "Manage participant and other identifiers in the clinicedc/edc projects",
"version": "0.3.36",
"project_urls": {
"Homepage": "https://github.com/clinicedc/edc-identifier"
},
"split_keywords": [
"django edc participant identifier",
"clinicedc",
"clinical trials"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "a4443997b0f50d2af30cc47dd3ca70704a8068e65ee2ab6d68255826390133dc",
"md5": "ffb5c22df6308c4bed5abfde4ccd2cca",
"sha256": "e2ab5c59ad32aaad011d2a93a06f3d424c7df63f39912be66534515b1c4e5cd0"
},
"downloads": -1,
"filename": "edc_identifier-0.3.36-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ffb5c22df6308c4bed5abfde4ccd2cca",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 55742,
"upload_time": "2024-03-13T23:00:13",
"upload_time_iso_8601": "2024-03-13T23:00:13.203660Z",
"url": "https://files.pythonhosted.org/packages/a4/44/3997b0f50d2af30cc47dd3ca70704a8068e65ee2ab6d68255826390133dc/edc_identifier-0.3.36-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "efc47456981db9d564ef80e63939ab1feef90b688762da271fc41bfb2e1deb13",
"md5": "f51df63482146125e8a7acb02b4d659a",
"sha256": "055f22932b40022139072ffb35fd9b3556be5d41be73166d29afd991ebc0fa98"
},
"downloads": -1,
"filename": "edc-identifier-0.3.36.tar.gz",
"has_sig": false,
"md5_digest": "f51df63482146125e8a7acb02b4d659a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 42127,
"upload_time": "2024-03-13T23:00:16",
"upload_time_iso_8601": "2024-03-13T23:00:16.164762Z",
"url": "https://files.pythonhosted.org/packages/ef/c4/7456981db9d564ef80e63939ab1feef90b688762da271fc41bfb2e1deb13/edc-identifier-0.3.36.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-03-13 23:00:16",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "clinicedc",
"github_project": "edc-identifier",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "edc-identifier"
}