Custom Diagnostics

In addition to the standard Diagnostics it is possible to define Custom Diagnostics.

Custom Diagnostics can inspect Draft and Custom Objects.

A Custom Diagnostic has the following properties:

Property

Description

Short Name

Must be unique within the Rave URL. Can be up to 20 characters in length. Short names comprising 4 digits (0000 - 9999) are reserved for built-in diagnostics. It may be useful to use a standard prefix, for example 'C001', 'C002', etc.

Name

Must be unique within the Rave URL.

Description

A description of the custom diagnostic.

Object Types

The object types which the custom diagnostic will inspect. A diagnostic cannot access object types using diagnostic.objects.get("..object name..")` if it does not declare that it uses that type of object.

Active

If active is False the Custom Diagnostic will not be displayed in Project Manage Diagnostics and cannot be run against a Draft.

Code

The RestrictedPython code that implements the diagnostic logic.

Copying Custom Diagnostics between URLs

Custom Diagnostics can be copied from one URL into another and can be copied from one URL to other URLs. If a Custom Diagnostic has object types which do not exist in the target URL then a warning will be displayed. The Custom Diagnostic will be copied but might not function as expected. There is no check that any Custom Properties referenced in the Custom Diagnostic code exist in the target URL.

Custom Diagnostic Code

Custom Diagnostic code is written using a subset of the Python programming language called RestrictedPython. For security, RestrictedPython limits the code which can be used; for example it is not possible to use the 'import', 'exec' or 'eval' statements.

A 'diagnostic' object is passed into the Custom Diagnostic Code. The diagnostic object has the following methods which can be called from the Custom Diagnostic code:

Method

Description

objects.get(plural_name)

Returns a list of DiagnosticObjects which can be inspected for the given plural_name (the plural name of the Object Definition). See below for the definition of a DiagnosticObject.

Parameters:

  • plural_name (str) – (required). The plural name of the Object Definition.

debug(message)

Displays the string when testing the Custom Diagnostic. When the Custom Diagnostic has been activated and is run for Drafts no debug messages are displayed.

Parameters:

  • message (str) – (required). The message to be displayed.

report_draft_finding(message)

Creates a diagnostic finding for the Draft.

Parameters:

  • message (str) – (required). The finding text.

report_object_finding(object_with_finding, property_name, message)

Creates a diagnostic finding for a specific object and property.

Parameters:

  • object_with_finding (DiagnosticObject) – (required). The object associated with the finding.

  • property_name (str) – (required). The name of the property associated with the finding.

  • message (str) – (required). The finding text.

The diagnostic object has the following properties:

Property

Description

draft

The draft on which the diagnostic is being run.

project

The project for the draft.

Project

The diagnostic.project object provides access to project-level information.

Methods:

Method/Property

Description

property(property_name)

Returns the value associated with the project property.

Parameters:

  • property_name (str) – (required). The name of the project property.

labels

Returns a tuple of DiagnosticLabel objects representing the labels assigned to the project.

has_label(label_name)

Returns True if the project has a label with the given name, False otherwise.

Parameters:

  • label_name (str) – (required). The name of the label to check for.

Available Properties:

Property Name

Type

Description

id

int

The unique identifier of the project.

ProjectName

string

The name of the project.

ProjectDescription

string

The description of the project.

ProtocolName

string

The protocol name associated with the project.

?Custom Property Name?

string

Any additional custom properties defined for the project are accessible by name here

Draft

The diagnostic.draft object provides access to draft-level information.

Methods:

Method/Property

Description

property(property_name)

Returns the value associated with the draft property.

Parameters:

  • property_name (str) – (required). The name of the draft property.

labels

Returns a tuple of DiagnosticLabel objects representing the labels assigned to the draft.

has_label(label_name)

Returns True if the draft has a label with the given name, False otherwise.

Parameters:

  • label_name (str) – (required). The name of the label to check for.

Available Properties:

Property Name

Type

Description

id

int

The unique identifier of the draft.

DraftName

string

The name of the draft.

PrimaryForm_id

int

The ID of the primary form for this draft (foreign key reference).

DefaultMatrix_id

int

The ID of the default matrix for this draft (foreign key reference).

ConfirmationMessage

string

The confirmation message displayed to users.

SignaturePrompt

string

The signature prompt text.

LabStandardGroup

string

The lab standard group name.

ReferenceLabs

string

Reference labs configuration.

show_uat_coverage

bool

Whether UAT coverage is displayed.

approvals

string

Approval settings for the draft.

is_locked

bool

Whether the draft is locked.

allow_import

bool

Whether import is allowed for this draft.

?Custom Property Name?

string

Any additional custom properties defined for the draft are accessible by name here

DiagnosticObject

A DiagnosticObject (representing Forms, Folders, Edit Checks, Custom Objects etc) has the following properties:

Property

Description

identifier

Returns the identifier of the object.

labels

Returns a tuple of DiagnosticLabel objects representing the labels assigned to this object. Each DiagnosticLabel has the following properties:

  • label_id (int) – The unique identifier of the label.

  • name (str) – The name of the label.

  • color (str) – The hex color code of the label (e.g., #66bf39).

  • text_color (str) – The calculated text color for contrast (dark or light).

  • reserved_for_actions (bool) – Whether the label is controlled by Actions rather than users.

A DiagnosticObject has the following methods:

Method

Description

property(property_name)

Returns the value associated with the property of the object.

Parameters:

  • property_name (str) – (required). The name of the DiagnosticObject property.

has_label(label_name)

Returns True if the object has a label with the given name, False otherwise.

Parameters:

  • label_name (str) – (required). The name of the label to check for.

Diagnostic Object Properties

The list of properties available for the selected object types will be displayed in the "Properties" tab.

Custom Objects will have all defined Custom Properties; the data type will always be 'string'. Custom objects will also have a parent_model_id property that is the id of its parent custom object (if it is a child custom object).

Draft Objects will have built-in Medidata Rave properties and any Custom Properties which have been created for that type of Draft Object.

For example, if "Matrices" are selected for inclusion in the Custom Diagnostic the following built-in properties will be available:

  • Matrices
    • id (int)

    • MatrixName (string)

    • OID (string)

    • Addable (bool)

    • Maximum (int)

The "id" property is a unique integer identifying each Matrix in TrialGrid.

"Matrix Folder Forms" objects will also be included, with the following properties:

  • Matrix Folder Forms
    • id (int)

    • Matrix_id (int)

    • Folder_id (int)

    • Form_id (int)

The "id" property is a unique integer identifying each Matrix Folder Form in TrialGrid.

Properties ending with "_id" are "foreign key" references to another object. "Matrix Folder Form" objects have a "Matrix_id" property which references the "Matrix".

The related object can be looked up using this pattern:

matrices_by_id = {matrix.property("id") : matrix for matrix in diagnostic.objects.get('Matrices')}

for mff in diagnostic.objects.get("Matrix Folder Forms"):
    matrix = matrices_by_id[mff.property("Matrix_id")]

Examples

# Report a draft finding if the 'ID' property of the 'Specifications' objects is repeated in more than one object

spec_ids = []
all_spec_ids = []
for spec in diagnostic.objects.get('Specifications'):
    spec_id = spec.property('ID')
    if spec_id not in spec_ids:
        spec_ids.append(spec_id)
    all_spec_ids.append(spec_id)

for spec_id in spec_ids:
    spec_count = all_spec_ids.count(spec_id)
    if spec_count > 1:
        msg = f"Specification ID {spec_id} is repeated {spec_count} times"
        diagnostic.report_draft_finding(msg)
# Report an object finding if the length of the 'DraftFieldName' property of a 'Fields' object is more than 20

for field in diagnostic.objects.get('Fields'):
    if len(field.property('DraftFieldName')) > 20:
        diagnostic.report_object_finding(field, "DraftFieldName", "is longer than 20 characters")
# Report an object finding if the 'Description' property of a 'Specifications' object contains double-spacing

for spec in diagnostic.objects.get('Specifications'):
    if "  " in spec.property('Description'):
        diagnostic.report_object_finding(spec, "Description", "has double-spacing")
# Report an object finding for Forms that have the 'Review Required' label

for form in diagnostic.objects.get('Forms'):
    if form.has_label('Review Required'):
        diagnostic.report_object_finding(form, "OID", "is marked for review")
# Report an object finding for Forms that have any labels assigned

for form in diagnostic.objects.get('Forms'):
    if len(form.labels) > 0:
        label_names = ", ".join(label.name for label in form.labels)
        diagnostic.report_object_finding(form, "OID", f"has labels: {label_names}")