15.2.122. camcops_server.cc_modules.cc_redcap

camcops_server/cc_modules/cc_redcap.py


Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com).

This file is part of CamCOPS.

CamCOPS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

CamCOPS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.


Implements communication with REDCap.

We use an XML fieldmap to describe how the rows in CamCOPS task tables are translated into REDCap records. See REDCap export.

REDCap does not assign instance IDs for repeating instruments so we need to query the database in order to determine the next instance ID. It is possible to create a race condition if more than one client is trying to update the same record at the same time.

exception camcops_server.cc_modules.cc_redcap.RedcapExportException[source]
class camcops_server.cc_modules.cc_redcap.RedcapFieldmap(filename: str)[source]

Internal representation of the fieldmap XML file. This describes how the task fields should be translated to the REDCap record.

__init__(filename: str) → None[source]
Parameters

filename – Name of an XML file telling CamCOPS how to map task fields to REDCap. See REDCap export.

instrument_names() → List[str][source]

Returns the names of all REDCap instruments.

class camcops_server.cc_modules.cc_redcap.RedcapNewRecordUploader(req: CamcopsRequest, project: redcap.project.Project)[source]

Creates a new REDCap record.

property force_auto_number

Should we force auto-numbering of records in REDCap?

get_new_record_id(record_id: str, response: List[str]) → str[source]

For autonumbering, read the generated record ID from the response. Otherwise we already have it.

get_record_id(existing_record_id: str) → str[source]

Get the record ID to send to REDCap when importing records

static log_success(record_id: str) → None[source]

Report upload success to the Python log.

Parameters

record_id – REDCap record ID

property return_content

The return_content argument to be passed to redcap.project.Project.import_records(). Can be:

  • count [default] - the number of records imported

  • ids - a list of all record IDs that were imported

  • auto_ids = (used only when forceAutoNumber=true) a list of

    pairs of all record IDs that were imported, includes the new ID created and the ID value that was sent in the API request (e.g., 323,10).

Note (2020-01-27) that it can return e.g. 15-30,0, i.e. the ID values can be non-integer.

class camcops_server.cc_modules.cc_redcap.RedcapRecordStatus(value)[source]

Corresponds to valid values of Form Status -> Complete? field in REDCap

class camcops_server.cc_modules.cc_redcap.RedcapTaskExporter[source]

Main entry point for task export to REDCap. Works out which record needs updating or creating. Creates the fieldmap and initiates upload.

export_task(req: CamcopsRequest, exported_task_redcap: ExportedTaskRedcap) → None[source]

Exports a specific task.

Parameters
get_fieldmap(recipient: camcops_server.cc_modules.cc_exportrecipient.ExportRecipient)camcops_server.cc_modules.cc_redcap.RedcapFieldmap[source]

Returns the relevant RedcapFieldmap.

Parameters

recipient – an camcops_server.cc_modules.cc_exportmodels.ExportRecipient

static get_fieldmap_filename(recipient: camcops_server.cc_modules.cc_exportrecipient.ExportRecipient) → str[source]

Returns the name of the XML file containing our fieldmap details, or raises RedcapExportException.

Parameters

recipient – an camcops_server.cc_modules.cc_exportmodels.ExportRecipient

static get_project(recipient: camcops_server.cc_modules.cc_exportrecipient.ExportRecipient) → redcap.project.Project[source]

Returns the redcap.project.Project.

Parameters

recipient – an camcops_server.cc_modules.cc_exportmodels.ExportRecipient

class camcops_server.cc_modules.cc_redcap.RedcapUpdatedRecordUploader(req: CamcopsRequest, project: redcap.project.Project)[source]

Updates an existing REDCap record.

get_new_record_id(old_record_id: str, response: Any) → str[source]

Returns the ID of the new (or updated) REDCap record.

Parameters
  • record_id – existing record ID

  • response – response from redcap.project.Project.import_records()

get_record_id(existing_record_id: str) → str[source]

Returns the REDCap record ID to use.

Parameters

existing_record_id – highest existing record ID, if known

static log_success(record_id: str) → None[source]

Report upload success to the Python log.

Parameters

record_id – REDCap record ID

class camcops_server.cc_modules.cc_redcap.RedcapUploader(req: CamcopsRequest, project: redcap.project.Project)[source]

Uploads records and files into REDCap, transforming the fields via the fieldmap.

Abstract base class.

Knows nothing about ExportedTaskRedcap, ExportedTask, ExportRecipient

__init__(req: CamcopsRequest, project: redcap.project.Project) → None[source]
Parameters
property autonumbering_enabled

Does this REDCap project have record autonumbering enabled?

property force_auto_number

Should we force auto-numbering of records in REDCap?

get_extra_symbols() → Dict[str, Any][source]

Returns a dictionary made available to the asteval interpreter. These become variables that the system administrator can refer to in their fieldmap XML; see REDCap export.

get_new_record_id(record_id: str, response: List[str]) → str[source]

Returns the ID of the new (or updated) REDCap record.

Parameters
  • record_id – existing record ID

  • response – response from redcap.project.Project.import_records()

get_record_id(existing_record_id: Optional[str]) → str[source]

Returns the REDCap record ID to use.

Parameters

existing_record_id – highest existing record ID, if known

static log_success(record_id: str) → None[source]

Report upload success to the Python log.

Parameters

record_id – REDCap record ID

property return_content

The return_content argument to be passed to redcap.project.Project.import_records(). Can be:

  • count [default] - the number of records imported

  • ids - a list of all record IDs that were imported

  • auto_ids = (used only when forceAutoNumber=true) a list of

    pairs of all record IDs that were imported, includes the new ID created and the ID value that was sent in the API request (e.g., 323,10).

Note (2020-01-27) that it can return e.g. 15-30,0, i.e. the ID values can be non-integer.

transform_fields(field_dict: Dict[str, Any], task: Task, formula_dict: Dict[str, str]) → None[source]

Uses the definitions from the fieldmap XML to set up field values to be exported to REDCap.

Parameters
  • field_dict – Exported field values go here (the dictionary is modified).

  • task – the camcops_server.cc_modules.cc_task.Task

  • formula_dict – dictionary (from the XML information) mapping REDCap field name to a “formula”. The formula is applied to extract data from the task in a flexible way.

upload(task: Task, existing_record_id: Optional[str], next_instance_id: int, fieldmap: camcops_server.cc_modules.cc_redcap.RedcapFieldmap, idnum_value: int) → str[source]

Uploads a CamCOPS task to REDCap.

Parameters
  • taskcamcops_server.cc_modules.cc_task.Task to be uploaded

  • existing_record_id – REDCap ID of the existing record, if there is one

  • next_instance_id – REDCap instance ID to be used for a repeating instrument

  • fieldmapRedcapFieldmap

  • idnum_value – CamCOPS patient ID number

Returns

REDCap record ID of the record that was created or updated

Return type

str

upload_files(task: Task, record_id: Union[int, str], repeat_instance: int, file_dict: Dict[str, bytes], event: Optional[str] = None) → None[source]

Uploads files attached to a task (e.g. a PDF of the CamCOPS task).

Parameters
  • task – the camcops_server.cc_modules.cc_task.Task

  • record_id – the REDCap record ID

  • repeat_instance – instance number for repeating instruments

  • file_dict – dictionary mapping filename to file contents

  • event – for longitudinal projects, specify the unique event here

Raises

RedcapExportException

upload_record(record: Dict[str, Any], **kwargs) → Union[Dict, List, str][source]

Uploads a REDCap record via the pycap redcap.project.Project.import_record() function. Returns its response.