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
|
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:
|
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:
|
report_draft_finding(message) |
Creates a diagnostic finding for the Draft. Parameters:
|
report_object_finding(object_with_finding, property_name, message) |
Creates a diagnostic finding for a specific object and property. Parameters:
|
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:
|
labels |
Returns a tuple of DiagnosticLabel objects representing the labels assigned to the project. |
has_label(label_name) |
Returns Parameters:
|
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:
|
labels |
Returns a tuple of DiagnosticLabel objects representing the labels assigned to the draft. |
has_label(label_name) |
Returns Parameters:
|
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:
|
A DiagnosticObject has the following methods:
Method |
Description |
|---|---|
property(property_name) |
Returns the value associated with the property of the object. Parameters:
|
has_label(label_name) |
Returns Parameters:
|
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}")