From 600aad21ef4a8966f35b30b75a8799d2ad7b4fb2 Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Thu, 16 Jul 2026 14:32:47 -0400 Subject: [PATCH 01/13] Changes made to the builder class and the unit test Changes made to add the new columns to the documentation --- ...with_define_and_library_dataset_builder.py | 91 ++++ resources/schema/rule-merged/CORE-base.json | 142 +++-- .../schema/rule-merged/MetaVariables.json | 32 ++ resources/schema/rule-merged/Operations.json | 301 +++++++++-- resources/schema/rule-merged/Operator.json | 487 ++++++++++++++---- .../rule-merged/Organization_CDISC.json | 112 +++- .../rule-merged/Organization_Custom.json | 53 +- .../schema/rule-merged/Organization_FDA.json | 38 +- resources/schema/rule-merged/Rule_Type.json | 5 +- resources/schema/rule/MetaVariables.json | 24 + resources/schema/rule/MetaVariables.md | 32 ++ resources/schema/rule/Rule_Type.md | 18 +- ...with_define_and_library_dataset_builder.py | 27 + 13 files changed, 1132 insertions(+), 230 deletions(-) diff --git a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py index 930c55953..1493386b5 100644 --- a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py +++ b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py @@ -1,6 +1,7 @@ from cdisc_rules_engine.dataset_builders.base_dataset_builder import BaseDatasetBuilder from typing import List from cdisc_rules_engine.models.dataset import DatasetInterface +import pandas as pd class VariablesMetadataWithDefineAndLibraryDatasetBuilder(BaseDatasetBuilder): @@ -31,6 +32,14 @@ def build(self): define_variable_codelist_coded_values, define_variable_codelist_coded_codes, define_variable_mandatory, + define_vlm_present, + define_vlm_item_count, + define_vlm_ccodes, + define_vlm_has_codelist_any, + define_vlm_has_codelist_all, + define_vlm_ccode_missing_any, + define_vlm_ccode_matches_library_any, + define_vlm_ccode_matches_library_all, library_variable_name, library_variable_label, library_variable_data_type, @@ -95,6 +104,88 @@ def build(self): ) ) + # Third merge: add VLM summary columns + define_vlm_records: List[dict] = self.get_define_xml_value_level_metadata() + define_vlm_dataset = self.dataset_implementation.from_records(define_vlm_records) + define_vlm_df = define_vlm_dataset.data + has_vlm = not define_vlm_df.empty + + required_vlm_cols = [ + "define_variable_name", + "define_vlm_ccode", + "define_vlm_has_codelist", + ] + + # Normalize VLM columns so groupby is safe + define_vlm_df = define_vlm_df.reindex(columns=required_vlm_cols) + define_vlm_df["define_vlm_ccode"] = define_vlm_df["define_vlm_ccode"].fillna("") + define_vlm_df["define_vlm_has_codelist"] = ( + define_vlm_df["define_vlm_has_codelist"].fillna(False).astype(bool) + ) + + if has_vlm: + vlm_summary = ( + define_vlm_df.groupby("define_variable_name", as_index=False) + .agg( + define_vlm_item_count=("define_vlm_ccode", "count"), + define_vlm_ccodes=( + "define_vlm_ccode", + lambda x: sorted(set(v for v in x if v != "")) + ), + define_vlm_has_codelist_any=("define_vlm_has_codelist", "any"), + define_vlm_has_codelist_all=("define_vlm_has_codelist", "all"), + define_vlm_ccode_missing_any=( + "define_vlm_ccode", + lambda x: (x == "").any() + ), + ) + ) + vlm_summary["define_vlm_present"] = True + else: + vlm_summary = pd.DataFrame(columns=[ + "define_variable_name", + "define_vlm_item_count", + "define_vlm_ccodes", + "define_vlm_has_codelist_any", + "define_vlm_has_codelist_all", + "define_vlm_ccode_missing_any", + "define_vlm_present", + ]) + + vlm_summary = vlm_summary.rename(columns={"define_variable_name": "variable_name"}) + final_dataframe = final_dataframe.merge( + vlm_summary, + how="left", + on="variable_name", + ) + final_dataframe.drop(columns=["define_variable_name_y"], errors="ignore", inplace=True) + + final_dataframe["define_vlm_present"] = ( + final_dataframe["define_vlm_present"].fillna(False) + ) + final_dataframe["define_vlm_item_count"] = ( + final_dataframe["define_vlm_item_count"].fillna(0).astype(int) + ) + final_dataframe["define_vlm_ccodes"] = final_dataframe["define_vlm_ccodes"].apply( + lambda x: x if isinstance(x, list) else [] + ) + for col in ["define_vlm_has_codelist_any", "define_vlm_has_codelist_all", + "define_vlm_ccode_missing_any"]: + final_dataframe[col] = final_dataframe[col].fillna(False) + + final_dataframe["define_vlm_ccode_matches_library_any"] = final_dataframe.apply( + lambda row: row["library_variable_ccode"] in row["define_vlm_ccodes"] + if row["define_vlm_ccodes"] else False, + axis=1, + ) + final_dataframe["define_vlm_ccode_matches_library_all"] = final_dataframe.apply( + lambda row: ( + bool(row["define_vlm_ccodes"]) + and all(c == row["library_variable_ccode"] for c in row["define_vlm_ccodes"]) + ), + axis=1, + ) + return final_dataframe def get_variable_null_stats( diff --git a/resources/schema/rule-merged/CORE-base.json b/resources/schema/rule-merged/CORE-base.json index 9b77c67c6..b94f14038 100644 --- a/resources/schema/rule-merged/CORE-base.json +++ b/resources/schema/rule-merged/CORE-base.json @@ -9,7 +9,9 @@ "$ref": "#/$defs/CheckItems" } }, - "required": ["all"], + "required": [ + "all" + ], "type": "object" }, { @@ -19,7 +21,9 @@ "$ref": "#/$defs/CheckItems" } }, - "required": ["any"], + "required": [ + "any" + ], "type": "object" }, { @@ -29,7 +33,9 @@ "$ref": "#/$defs/CheckItem" } }, - "required": ["not"], + "required": [ + "not" + ], "type": "object" } ] @@ -127,13 +133,18 @@ "$ref": "#/$defs/Domains" }, "include_split_datasets": { - "enum": [true] + "enum": [ + true + ] } }, "type": "object" }, "JoinType": { - "enum": ["inner", "left"], + "enum": [ + "inner", + "left" + ], "type": "string" }, "LeftRightKeys": { @@ -146,7 +157,10 @@ "$ref": "#/$defs/VariableName" } }, - "required": ["Left", "Right"], + "required": [ + "Left", + "Right" + ], "type": "object" }, "PascalCases": { @@ -231,7 +245,10 @@ "type": "string" } }, - "required": ["Document", "Cited Guidance"], + "required": [ + "Document", + "Cited Guidance" + ], "type": "object" }, "type": "array" @@ -240,10 +257,14 @@ "additionalProperties": false, "anyOf": [ { - "required": ["Logical Expression"] + "required": [ + "Logical Expression" + ] }, { - "required": ["Plain Language Expression"] + "required": [ + "Plain Language Expression" + ] } ], "properties": { @@ -257,18 +278,25 @@ "type": "string" } }, - "required": ["Rule"], + "required": [ + "Rule" + ], "type": "object" }, "Plain Language Expression": { "type": "string" }, "Type": { - "enum": ["Failure", "Success"], + "enum": [ + "Failure", + "Success" + ], "type": "string" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -282,11 +310,18 @@ "type": "string" }, "Relationship": { - "enum": ["Predecessor", "Related", "Successor"], + "enum": [ + "Predecessor", + "Related", + "Successor" + ], "type": "string" } }, - "required": ["Id", "Relationship"], + "required": [ + "Id", + "Relationship" + ], "type": "object" }, "type": "array" @@ -304,7 +339,9 @@ "type": "string" } }, - "required": ["Id"], + "required": [ + "Id" + ], "type": "object" }, "Validator Rule Message": { @@ -314,7 +351,11 @@ "type": "string" } }, - "required": ["Origin", "Rule Identifier", "Version"], + "required": [ + "Origin", + "Rule Identifier", + "Version" + ], "type": "object" }, "minItems": 1, @@ -327,7 +368,11 @@ "type": "string" } }, - "required": ["Name", "References", "Version"], + "required": [ + "Name", + "References", + "Version" + ], "type": "object" }, "minItems": 1, @@ -350,7 +395,10 @@ "$ref": "Organization_Custom.json" } ], - "required": ["Organization", "Standards"], + "required": [ + "Organization", + "Standards" + ], "type": "object" }, "minItems": 1, @@ -390,10 +438,15 @@ "const": "Published" } }, - "required": ["Id"] + "required": [ + "Id" + ] } ], - "required": ["Status", "Version"], + "required": [ + "Status", + "Version" + ], "type": "object" }, "Description": { @@ -439,7 +492,9 @@ "type": "string" } }, - "required": ["Name"], + "required": [ + "Name" + ], "type": "object" }, "minItems": 1, @@ -465,7 +520,9 @@ "type": "array" } }, - "required": ["Message"], + "required": [ + "Message" + ], "type": "object" }, "Rule Type": { @@ -483,7 +540,9 @@ "$ref": "#/$defs/Classes" } }, - "required": ["Include"], + "required": [ + "Include" + ], "type": "object" }, { @@ -493,7 +552,9 @@ "$ref": "#/$defs/Classes" } }, - "required": ["Exclude"], + "required": [ + "Exclude" + ], "type": "object" } ] @@ -507,7 +568,9 @@ "$ref": "#/$defs/DataStructures" } }, - "required": ["Include"], + "required": [ + "Include" + ], "type": "object" }, { @@ -517,7 +580,9 @@ "$ref": "#/$defs/DataStructures" } }, - "required": ["Exclude"], + "required": [ + "Exclude" + ], "type": "object" } ] @@ -557,10 +622,14 @@ }, "anyOf": [ { - "required": ["Exclude"] + "required": [ + "Exclude" + ] }, { - "required": ["Include"] + "required": [ + "Include" + ] } ], "type": "object" @@ -582,13 +651,20 @@ }, "oneOf": [ { - "required": ["Classes", "Domains"] + "required": [ + "Classes", + "Domains" + ] }, { - "required": ["Data Structures"] + "required": [ + "Data Structures" + ] }, { - "required": ["Entities"] + "required": [ + "Entities" + ] } ], "type": "object" @@ -623,7 +699,9 @@ } }, "then": { - "required": ["Grouping_Variables"] + "required": [ + "Grouping_Variables" + ] }, "type": "object" } diff --git a/resources/schema/rule-merged/MetaVariables.json b/resources/schema/rule-merged/MetaVariables.json index c2cdb863c..aa4b44d3e 100644 --- a/resources/schema/rule-merged/MetaVariables.json +++ b/resources/schema/rule-merged/MetaVariables.json @@ -134,6 +134,38 @@ "const": "define_vlm_ccode", "markdownDescription": "\nValueListDef.ItemDef.CodeList.Alias.Name\n" }, + { + "const": "define_vlm_ccode_matches_library_all", + "markdownDescription": "\nBoolean indicating whether all VLM items' codelist codes match the library standard codelist code for this variable (all non-empty define_vlm_ccodes equal library_variable_ccode)\n" + }, + { + "const": "define_vlm_ccode_matches_library_any", + "markdownDescription": "\nBoolean indicating whether at least one VLM item's codelist code matches the library standard codelist code for this variable (any define_vlm_ccode equals library_variable_ccode)\n" + }, + { + "const": "define_vlm_ccode_missing_any", + "markdownDescription": "\nBoolean indicating whether at least one VLM item has an empty or missing codelist code (ValueListDef.ItemDef.CodeList.Alias.Name is empty)\n" + }, + { + "const": "define_vlm_ccodes", + "markdownDescription": "\nList of distinct non-empty codelist codes from all VLM items for this variable. Derived from ValueListDef.ItemDef.CodeList.Alias.Name entries\n" + }, + { + "const": "define_vlm_has_codelist_all", + "markdownDescription": "\nBoolean indicating whether all VLM items have a CodeListRef (all ValueListDef.ItemDef.CodeListRef exist)\n" + }, + { + "const": "define_vlm_has_codelist_any", + "markdownDescription": "\nBoolean indicating whether at least one VLM item has a CodeListRef (ValueListDef.ItemDef.CodeListRef exists)\n" + }, + { + "const": "define_vlm_item_count", + "markdownDescription": "\nCount of VLM items (ValueListDef.ItemDef entries) for this variable\n" + }, + { + "const": "define_vlm_present", + "markdownDescription": "\nBoolean indicating whether this variable has one or more VLM (Value Level Metadata) items defined in Define-XML ValueListDef.ItemDef\n" + }, { "const": "define_vlm_codelist_coded_values", "markdownDescription": "\nValueListDef.ItemDef.CodeList.[CodeListItem/EnumeratedItem].CodedValue\n" diff --git a/resources/schema/rule-merged/Operations.json b/resources/schema/rule-merged/Operations.json index 6bceb8ebc..d8f634b4b 100644 --- a/resources/schema/rule-merged/Operations.json +++ b/resources/schema/rule-merged/Operations.json @@ -10,7 +10,10 @@ "markdownDescription": "\nReturns a Series indicating whether a specified codelist is extensible. Used in conjunction with codelist_terms to determine if values outside the codelist are acceptable. From the above example, $extensible will contain a bool if the codelist PKUDUG is extensible in all rows of the column.\n\nIf ct_package_type, version, and codelist_code parameters are provided, it will instead attach a new column containing the extensible value for each combination provided in the source dataset.\n\nFor example, given the current dataset:\n\n```\nid \tcodeSystemVersion \t$codelist_code\n1 \t2024-09-27 \tC201264\n2 \t2024-09-27 \tC201265\n3 \t2023-03-29 \tC127262\n```\n\nand the following operation:\n\n```yaml\n- id: $codelist_extensible\n operator: codelist_extensible\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n```\n\nThis will result in the following dataset:\n\n```\nid \tcodeSystemVersion \t$codelist_code \t$codelist_extensible\n1 \t2024-09-27 \tC201264 \tfalse\n2 \t2024-09-27 \tC201265 \tfalse\n3 \t2023-03-29 \tC127262 \ttrue\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -20,7 +23,10 @@ "markdownDescription": "\nReturns a list of valid codelist/term values. Used for evaluating whether NCI codes, submission values or NCI preferred terms are valid based on controlled terminology. Expects three parameters: `codelists` which is a list of the codelist submission value(s) to retrieve, `level` which is the level of data (either \"codelist\" or \"term\") at which to return data from, and `returntype` which is the type of values to return: \"code\" for NCI Code(s), \"value\" for submission value(s), or \"pref_term\" for NCI preferred term(s).\n\n```yaml\n- Check:\n - all:\n - name: PPSTRESU\n operator: is_not_contained_by\n value: $terms\n - name: $extensible\n operator: equal_to\n value: true\n- Operations:\n - id: $terms\n operator: codelist_terms\n codelists:\n - PKUDUG\n level: term\n returntype: value\n - id: $extensible\n codelist: PKUDUG\n operator: codelist_extensible\n```\n\nIf `ct_package_type`, `version`, and `codelist_code` parameters are provided, it will instead attach a new column containing the term for each combination provided in the source dataset. If a column name is provided as:\n\n- `term_code`, it will find term information using the term codes in the specified column.\n- `term_value`, it will find term information using the term submission values in the specified column.\n- `term_pref_term`, it will find term information using the term preferred terms in the specified column.\n\nOnly one of `term_code`, `term_value` or `term_pref_term` can be provided. The term information returned will depend on the value of the `returntype` parameter, as described above. If `returntype` is not specified, specifying `term_code` will return the term submission value and specifying either `term_value` or `term_pref_term` will return the term code.\n\nFor example, given the current dataset:\n\n```\nid \tcodeSystemVersion $codelist_code code decode\n1 \t2024-09-27 C201264 C201356 After\n2 \t2024-09-27 C201265 C201352 End to End\n3 \t2023-03-29 C127262 C51282 CLINIC\n```\n\nand the following operations:\n\n```yaml\n- id: $found_term_value\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_code: code\n- id: $found_term_pref_term\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_code: code\n returntype: pref_term\n```\n\nThis will result in the following dataset:\n\n```\n id codeSystemVersion $codelist_code code decode $found_term_value $found_term_pref_term\n 1 2024-09-27 C201264 C201356 After After After Timing Type\n 2 2024-09-27 C201265 C201352 End to End End to End End to End\n 3 2023-03-31 C127262 C51282 CLINIC CLINIC Clinic\n```\n\nConversely, if given the same dataset, and the following operations:\n\n```yaml\n- id: $found_term_code1\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_value: decode\n- id: $found_term_code2\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_pref_term: decode\n```\n\nThis will result in the following dataset:\n\n```\n id codeSystemVersion $codelist_code code decode $found_term_code1 $found_term_code2\n 1 2024-09-27 C201264 C201356 After C201356\n 2 2024-09-27 C201265 C201352 End to End C201352 C201352\n 3 2023-03-31 C127262 C51282 CLINIC C51282 C51282\n```\n\nNote that `$found_term_code2` is:\n\n- `null` for the first record because \"After\" does not match any NCI preferred term in the C201264 codelist.\n- populated for the third record because matching is case-insensitive (i.e., \"CLINIC\" matches \"Clinic\").\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -30,7 +36,11 @@ "markdownDescription": "\nReturns a list of valid extensible codelist term's submission values. Used for evaluating whether submission values are valid based on controlled terminology. Expects the parameter codelists which is a list of the codelist submission value(s) to retrieve. If the codelist argument is [\"All\"] will return all extensible terms for the CT in a list.\n\n```yaml\n{\n \"id\": \"$ext_value\",\n \"codelist\": [\"ALL\"],\n \"operator\": \"define_extensible_codelists\",\n}\n```\n" } }, - "required": ["id", "operator", "codelists"], + "required": [ + "id", + "operator", + "codelists" + ], "type": "object" }, { @@ -40,7 +50,11 @@ "markdownDescription": "\nIf a target variable name is specified, returns the specified metadata in the define for the specified target variable.\n\nInput\n\n```yaml\n- operator: define_variable_metadata\n attribute_name: define_variable_label\n name: LBTESTCD\n id: $LBTESTCD_VARIABLE_LABEL\n```\n\nOutput\n\n```\nLaboratory Test Code\n```\n\nIf no target variable name specified, returns a dictionary containing the specified metadata in the define for all variables.\n\nInput\n\n```yaml\n- operator: define_variable_metadata\n attribute_name: define_variable_label\n id: $VARIABLE_LABEL\n```\n\nOutput\n\n```\n{\n \"STUDYID\": \"Study Identifier\",\n \"USUBJID\": \"Unique Subject Identifier\",\n \"LBTESTCD\": \"Laboratory Test Code\",\n \"...\": \"...\"\n}\n```\n" } }, - "required": ["id", "operator", "attribute_name"], + "required": [ + "id", + "operator", + "attribute_name" + ], "type": "object" }, { @@ -50,7 +64,11 @@ "markdownDescription": "\nGet a distinct list of values for the given name.\n\nIf a group list is specified, the distinct value list will be grouped by the variables within group.\nIf a filter object is provided, only values for records that match the filter criteria are included in the distinct values.\nIf `value_is_reference` is set to true, the target column contains the names of other columns, and the operation will check the referenced columns to ensure they exist in the associated dataset before adding them to the distinct list.\n\nIf group is provided, group_aliases may also be provided to assign new grouping variable names so that results grouped by the values in one set of grouping variables can be merged onto a dataset according to the same grouping value(s) stored in different set of grouping variables. When both group and group_aliases are provided, columns are renamed according to corresponding list position (i.e., the 1st column in group is renamed to the 1st column in group_aliases, etc.). If there are more columns listed in group than in group_aliases, only the group columns with corresponding group_aliases columns will be renamed. If there are more columns listed in group_aliases than in group, the extra column names in group_aliases will be ignored. See record_count for an example of the use of group_aliases.\n\n```yaml\nCheck:\n all:\n - name: SSSTRESC\n operator: equal_to\n value: DEAD\n value_is_literal: true\n - name: $ds_dsdecod\n operator: does_not_contain\n value: DEATH\n value_is_literal: true\nOperations:\n - operator: distinct\n domain: DS\n name: DSDECOD\n id: $ds_dsdecod\n group:\n - USUBJID\n filter:\n CAT: \"CATEGORY 1\"\n SCAT: \"SUBCATEGORY A\"\n```\n\n> below, `IDVAR` contains column names, the operation retrieves the value from each column for that row, checks the dataset associated with that column using the CO RDOMAIN. Columns that exist are added to the returns the distinct set.\n\n```yaml\nOperations:\n - domain: CO\n id: $rdomain_variables\n name: IDVAR\n operator: distinct\n value_is_reference: true\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -60,7 +78,10 @@ "markdownDescription": "\nChecks whether the domain is in the set of domains within the provided standard.\n\nInput\n\nTarget Domain: XY\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: domain_is_custom\n id: $domain_is_custom\n```\n\nOutput\n\n```\ntrue\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -70,7 +91,10 @@ "markdownDescription": "\nChecks whether the related domain (for example, the parent domain of a SUPP or RELREC dataset) is not present in the set of standard domains for the provided standard and version. This is useful for determining whether relationships point to non-standard or custom domains.\n\nInput\n\nTarget Domain: SUPPEX\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: related_domain_is_custom\n id: $related_domain_is_custom\n```\n\nOutput\n\n```\ntrue\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -80,7 +104,10 @@ "markdownDescription": "\nReturns the label for the domain the operation is executing on within the provided standard.\n\nInput.\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: domain_label\n id: $domain_label\n```\n\nOutput\n\n```\nLaboratory Test Results\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -90,7 +117,11 @@ "markdownDescription": "\nCalculates the number of days between the DTC and RFSTDTC. The Study Day value is incremented by 1 for each date following RFSTDTC. Dates prior to RFSTDTC are decreased by 1, with the date preceding RFSTDTC designated as Study Day -1 (there is no Study Day 0). All Study Day values are integers. Thus, to calculate Study Day:\n\n- --DY = (date portion of --DTC) - (date portion of RFSTDTC) + 1 if --DTC is on or after RFSTDTC\n- --DY = (date portion of --DTC) - (date portion of RFSTDTC) if --DTC precedes RFSTDTC\n\nThis algorithm should be used across all domains.\n\n```yaml\nCheck:\n all:\n - name: --DY\n operator: non_empty\n - name: --DTC\n operator: is_complete_date\n - name: RFSTDTC\n operator: is_complete_date\n - name: --DY\n operator: not_equal_to\n value: $dy\nOperations:\n - name: --DTC\n operator: dy\n id: $dy\nMatch Datasets:\n - Name: DM\n Keys:\n - USUBJID\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -100,7 +131,11 @@ "markdownDescription": "\nReturns the requested dataset level metadata value for the current dataset. Possible name values are:\n\n- dataset_size\n- dataset_location\n- dataset_name\n- dataset_label\n- domain\n- is_ap\n- ap_suffix\n\nExample\n\nInput:\n\nTarget domain: LB\n\n```yaml\n- name: dataset_label\n operator: extract_metadata\n id: $dataset_label\n```\n\nOutput:\n\n```\nLaboratory Test Results\n```\n\nExample: ap_suffix\n\nExtracts the domain suffix (characters 3-4) from AP-related domains. For example, \"FA\" from \"APFA\" DOMAIN value.\n\nInput:\n\nTarget domain: APFA\n\n```yaml\n- name: ap_suffix\n operator: extract_metadata\n id: $ap_suffix\n```\n\nOutput:\n\n```\nFA\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -110,7 +145,10 @@ "markdownDescription": "\nReturns the expected (\"Core\" = Exp ) variables for the domain in the current standard Variable Metadata for custom domains will pull from the model while non-custom domains will be from the IG and Model.\n\nInput:\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: expected_variables\n id: $expected_variables\n```\n\nOutput:\n\n```\n[\"LBCAT\", \"LBORRES\", \"LBORRESU\", \"...\"]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -120,7 +158,13 @@ "markdownDescription": "\nFetches controlled terminology attribute values from CT packages based on row-specific CT package and version references. The operation constructs CT package names based on the standard being validated and the values in the `name` and `version` columns (e.g., SDTMIG \u2192 \"sdtmct-{version}\"). When the `name` column contains \"CDISC\" or \"CDISC CT\", it uses the validation run's standard to determine the package prefix and the version found in the cell of the specified column. The operation extracts all codes matching the specified ct_attribute from the package.\n\n**Required Parameters:**\n\n- `ct_attribute`: Attribute to extract - `\"Term CCODE\"`, `\"Codelist CCODE\"`, `\"Term Value\"`, `\"Codelist Value\"`, or `\"Term Preferred Term\"`\n- `name`: Column containing CT reference (e.g., \"TSVCDREF\") - identifies which terminology system is referenced\n- `version`: Column containing CT version (e.g., \"TSVCDVER\")\n\n```yaml\n- id: $VALID_TERM_CODES\n name: TSVCDREF\n operator: get_codelist_attributes\n ct_attribute: Term CCODE\n version: TSVCDVER\n```\n\n**Note:** if using this operator with excel data, you must put the ctpackage versions contained within your data in the library tab for it work properly.\n" } }, - "required": ["id", "operator", "name", "ct_attribute", "version"], + "required": [ + "id", + "operator", + "name", + "ct_attribute", + "version" + ], "type": "object" }, { @@ -130,7 +174,10 @@ "markdownDescription": "\nReturns list of dataset columns in order\n\n```yaml\nCheck:\n all:\n - name: $column_order_from_dataset\n operator: is_not_ordered_by\n value: $column_order_from_library\nOperations:\n - id: $column_order_from_library\n operator: get_column_order_from_library\n - id: $column_order_from_dataset\n operator: get_column_order_from_dataset\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -140,7 +187,10 @@ "markdownDescription": "\nFetches column order for a given domain from the CDISC library. The lists with column names are sorted in accordance to \"ordinal\" key of library metadata.\nOptionally Filters variables based on specified metadata criteria.\n\nRule Type: Variable Metadata Check\n\n```yaml\nCheck:\n all:\n - name: variable_name\n operator: is_not_contained_by\n value: $ig_variables\nOperations:\n - id: $ig_variables\n operator: get_column_order_from_library\n key_name: \"role\" # role, core, etc\n key_value: \"Exp\" # Timing, Req, Exp, Perm, etc\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -150,7 +200,10 @@ "markdownDescription": "\nReturns the list of domains for a given class from the CDISC Library Implementation Guide. This operation retrieves all domains that belong to a specified class (e.g., \"TRIAL DESIGN\", \"FINDINGS\", \"EVENTS\") based on the current standard and version. The operation uses the standard and version from the validation context as well as the optional `domain_class` parameter which is the name of the class to filter by (e.g., \"TRIAL DESIGN\", \"FINDINGS\", \"EVENTS\", \"INTERVENTIONS). NOTE: Class names are case-sensitive and should match the Library metadata format. If no `domain_class` parameter is provided, the operation returns all domains across all classes in the Implementation Guide:\n\n```yaml\n- operator: get_library_class_domains\n id: $trial_design_domains\n domain_class: \"TRIAL DESIGN\"\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -160,7 +213,10 @@ "markdownDescription": "\nFetches column order for a given model class from the CDISC library. The lists with column names are sorted in accordance to \"ordinal\" key of library metadata.\n\nRule Type: Variable Metadata Check\n\n```yaml\nCheck:\n all:\n - name: variable_name\n operator: is_not_contained_by\n value: $model_variables\nOperations:\n - id: $model_variables\n operator: get_model_column_order\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -170,7 +226,12 @@ "markdownDescription": "\nFetches variable level library model properties filtered by the provided key_name and key_value\n\nExample\n\nInput\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: get_model_filtered_variables\n id: $model_filtered_variables\n key_name: \"role\"\n key_value: \"Timing\"\n```\n\nOutput\n\n```\n[\"VISITNUM\", \"VISIT\", \"VISITDY\", \"TAETORD\", \"...\"]\n```\n" } }, - "required": ["id", "operator", "key_name", "key_value"], + "required": [ + "id", + "operator", + "key_name", + "key_value" + ], "type": "object" }, { @@ -180,7 +241,10 @@ "markdownDescription": "\nFetches column order for a given SUPP's parent model class from the CDISC library. The lists with column names are sorted in accordance to \"ordinal\" key of library metadata.\n\n```yaml\nCheck:\n all:\n - operator: is_not_contained_by\n value: $parent_model_variables\nOperations:\n - id: $parent_model_variables\n operator: get_parent_model_column_order\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -190,7 +254,12 @@ "markdownDescription": "\nFilters variables from the dataset based on specified metadata criteria. Returns a list of variable names that exist in the dataset and match the filter criteria.\n\n```yaml\n- operator: get_dataset_filtered_variables\n id: $timing_variables\n key_name: \"role\"\n key_value: \"Timing\"\n```\n" } }, - "required": ["id", "operator", "key_name", "key_value"], + "required": [ + "id", + "operator", + "key_name", + "key_value" + ], "type": "object" }, { @@ -200,7 +269,11 @@ "markdownDescription": "\nGenerates a dataframe where each record in the dataframe is the library ig variable metadata corresponding with the variable label found in the column provided in name. The metadata column names are prefixed with the string provided in `id`.\n\nInput\n\nTarget Dataset: SUPPLB\n\nProduct: sdtmig\n\nVersion: 3-4\n\nDataset:\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QLABEL\": [\"Toxicity\", \"Viscosity\", \"Analysis Method\"]\n}\n```\n\nRule:\n\n```yaml\n- operator: label_referenced_variable_metadata\n id: $qlabel_referenced_variable_metadata\n name: \"QLABEL\"\n```\n\nOutput\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QLABEL\": [\"Toxicity\", \"Viscosity\", \"Analysis Method\"],\n \"$qlabel_referenced_variable_metadata_name\": [\"LBTOX\", null, \"LBANMETH\"],\n \"$qlabel_referenced_variable_metadata_role\": [\n \"Variable Qualifier\",\n null,\n \"Record Qualifier\"\n ],\n \"$qlabel_referenced_variable_metadata_ordinal\": [44, null, 38],\n \"$qlabel_referenced_variable_metadata_core\": [\"Req\", \"Req\", \"Req\"],\n \"$qlabel_referenced_variable_metadata_label\": [\"Toxicity\", null, \"Analysis Method\"]\n}\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -210,7 +283,11 @@ "markdownDescription": "\nAllows the creation of a lookup table to take the values from multiple input columns and map them to values in an output column. The map parameter contains a list of objects. Each dictionary contains column names as properties that match the column names in the source dataset and an output property that will be returned as a result.\n\nIf map has a single object and output is the only property specified on that object, this will function as a direct assignment.\n\nFor example, given the following current dataset:\n\n```\nid \tparent_entity \tparent_rel\n1 \tTiming \trelativeToFrom\n2 \tSomething \trelativeToFrom\n3 \tTiming \ttype\n```\n\nand the following operation:\n\n```yaml\nOperations:\n - id: $codelist_code\n operator: map\n map:\n - parent_entity: Timing\n parent_rel: type\n output: C201264\n - parent_entity: Timing\n parent_rel: relativeToFrom\n output: C201265\n```\n\nThis will result in the following dataset:\n\n```\nid \tparent_entity \tparent_rel \t$codelist_code\n1 \tTiming \trelativeToFrom \tC201265\n2 \tSomething \trelativeToFrom \tNone\n3 \tTiming \ttype \tC201264\n```\n\nThe following operation:\n\n```yaml\nOperations:\n - id: $codelist_code\n operator: map\n map:\n - output: C201264\n```\n\nWill result in the following dataset:\n\n```\nid \tparent_entity \tparent_rel \t$codelist_code\n1 \tTiming \trelativeToFrom \tC201264\n2 \tSomething \trelativeToFrom \tC201264\n3 \tTiming \ttype \tC201264\n```\n" } }, - "required": ["id", "operator", "map"], + "required": [ + "id", + "operator", + "map" + ], "type": "object" }, { @@ -220,7 +297,11 @@ "markdownDescription": "\nIf no group is provided, returns the max value in name. If group is provided, returns the max value in name, within each unique set of the grouping variables.\n\n```yaml\nCheck:\n all:\n - name: \"$max_age\"\n operator: \"greater_than\"\n value: \"MAXAGE\"\nOperations:\n - operator: \"max\"\n domain: \"DM\"\n name: \"AGE\"\n id: \"$max_age\"\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -230,7 +311,11 @@ "markdownDescription": "\nIf no group is provided, returns the max date value in name. If group is provided, returns the max date value in name, within each unique set of the grouping variables.\n\n```yaml\nCheck:\n all:\n - name: USUBJID\n operator: is_contained_by\n value: $ex_usubjid\n - name: RFXENDTC\n operator: not_equal_to\n value: $max_ex_exstdtc\n - name: RFXENDTC\n operator: not_equal_to\n value: $max_ex_exendtc\nOperations:\n - operator: distinct\n domain: EX\n name: USUBJID\n id: $ex_usubjid\n - operator: max_date\n domain: EX\n name: EXSTDTC\n id: $max_ex_exstdtc\n group:\n - USUBJID\n - operator: max_date\n domain: EX\n name: EXENDTC\n id: $max_ex_exendtc\n group:\n - USUBJID\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -240,7 +325,11 @@ "markdownDescription": "\nExample: AAGE > mean(DM.AGE), where AAGE is a fictitious NSV\n\n```yaml\nCheck:\n all:\n - name: \"AAGE\"\n operator: \"greater_than\"\n value: \"$average_age\"\nOperations:\n - operator: \"mean\"\n domain: \"DM\"\n name: \"AGE\"\n id: \"$average_age\"\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -250,7 +339,11 @@ "markdownDescription": "\nIf no group is provided, returns the min value in name. If group is provided, returns the min value in name, within each unique set of the grouping variables.\n\n```yaml\nCheck:\n all:\n - name: \"$min_age\"\n operator: \"less_than\"\n value: \"MINAGE\"\nOperations:\n - operator: \"min\"\n domain: \"DM\"\n name: \"AGE\"\n id: \"$min_age\"\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -260,7 +353,11 @@ "markdownDescription": "\nIf no group is provided, returns the min date value in name. If group is provided, returns the min date value in name, within each unique set of the grouping variables.\n\nExample: RFSTDTC is greater than min AE.AESTDTC for the current USUBJID\n\n```yaml\nCheck:\n all:\n - name: \"RFSTDTC\"\n operator: \"date_greater_than\"\n value: \"$ae_aestdtc\"\nOperations:\n - operator: \"min_date\"\n domain: \"AE\"\n name: \"AESTDTC\"\n id: \"$ae_aestdtc\"\n group:\n - USUBJID\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -270,7 +367,12 @@ "markdownDescription": "\nComputes set difference: elements in `name` that are not in `subtract`. By default a standard [set difference]() semantics (A \u2216 B) is applied. Optional `order_insensitive` property allows to have the element order to be taken into consideration and only those `name` elements are removed which follow the same order as in `subtract` . Preserves order from the first list. Both `name` and `subtract` must reference other operation results (e.g., `$expected_variables`, `$dataset_variables`). When `subtract` is empty or missing, returns all elements from `name`. Can be computed and added to output variables to display missing elements in error results.\n\n```yaml\nOperations:\n - id: $expected_variables\n operator: expected_variables\n - id: $dataset_variables\n operator: get_column_order_from_dataset\n - id: $expected_minus_dataset\n name: $expected_variables\n operator: minus\n subtract: $dataset_variables\n order_insensitive: false\n```\n" } }, - "required": ["id", "operator", "name", "subtract"], + "required": [ + "id", + "operator", + "name", + "subtract" + ], "type": "object" }, { @@ -280,7 +382,11 @@ "markdownDescription": "\nGenerates a dataframe where each record in the dataframe is the library ig variable metadata corresponding with the variable name found in the column provided in name. The metadata column names are prefixed with the string provided in `id`.\n\nInput\n\nTarget Dataset: SUPPLB\n\nProduct: sdtmig\n\nVersion: 3-4\n\nDataset:\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QNAM\": [\"Toxicity\", \"LBVISCOS\", \"Analysis Method\"]\n}\n```\n\nRule:\n\n```yaml\n- operator: name_referenced_variable_metadata\n id: $qnam_referenced_variable_metadata\n name: \"QNAM\"\n```\n\nOutput\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QNAM\": [\"LBTOX\", \"LBVISCOS\", \"LBANMETH\"],\n \"$qnam_referenced_variable_metadata_name\": [\"LBTOX\", null, \"LBANMETH\"],\n \"$qnam_referenced_variable_metadata_role\": [\n \"Variable Qualifier\",\n null,\n \"Record Qualifier\"\n ],\n \"$qnam_referenced_variable_metadata_ordinal\": [44, null, 38],\n \"$qnam_referenced_variable_metadata_core\": [\"Req\", \"Req\", \"Req\"],\n \"$qnam_referenced_variable_metadata_label\": [\"Toxicity\", null, \"Analysis Method\"]\n}\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -290,7 +396,10 @@ "markdownDescription": "\nReturns the permissible variables (\"Core\" = Perm ) for a given domain and standard Variable Metadata for custom domains will pull from the model while non-custom domains will be from the IG and Model.\n\nInput:\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: permissible_variables\n id: $permissible_variables\n```\n\nOutput:\n\n```\n[\"LBGRPID\", \"LBREFID\", \"LBSPID\", \"...\"]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -300,7 +409,10 @@ "markdownDescription": "\nIf no filter or group is provided, returns the number of records in the dataset. If filter is provided, returns the number of records in the dataset that contain the value(s) in the corresponding column(s) provided in the filter. Filter can have a wildcard `&` that when added to the end of the filter value will look for all instances of that prefix (see 4th example below). If group is provided, returns the number of rows matching each unique set of the grouping variables. These can be static column name(s) or can be derived from other operations like get_dataset_filtered_variables.\n\nIf both filter and group are provided, returns the number of records in the dataset that contain the value(s) in the corresponding column(s) provided in the filter that also match each unique set of the grouping variables.\n\n**Wildcard Filtering:** Filter values ending with % will match any records where the column value starts with the specified prefix. For example, RACE% will match RACE1, RACE2, RACE3, etc. This is useful for matching related variables with numeric or alphabetic suffixes.\n\n**Regex Transformation:** If regex is provided along with group, the regex pattern will be applied to transform grouping column values before grouping. The regex is only applied to columns where the pattern matches the data type. For example, using regex `^\\d{4}-\\d{2}-\\d{2}` on a column containing `2022-01-14T08:00` will extract `2022-01-14` for grouping purposes.\n\nIf group is provided, group_aliases may also be provided to assign new grouping variable names so that results grouped by the values in one set of grouping variables can be merged onto a dataset according to the same grouping value(s) stored in different set of grouping variables. When both group and group_aliases are provided, columns are renamed according to corresponding list position (i.e., the 1st column in group is renamed to the 1st column in group_aliases, etc.). If there are more columns listed in group than in group_aliases, only the group columns with corresponding group_aliases columns will be renamed. If there are more columns listed in group_aliases than in group, the extra column names in group_aliases will be ignored.\n\nExample: return the number of records in a dataset.\n\n```yaml\n- operator: record_count\n id: $records_in_dataset\n```\n\nExample: return the number of records where STUDYID = \"CDISC01\" and FLAGVAR = \"Y\".\n\n```yaml\n- operator: record_count\n id: $flagged_cdisc01_records_in_dataset\n filter:\n STUDYID: \"CDISC01\"\n FLAGVAR: \"Y\"\n```\n\nExample: return the number of records grouped by USUBJID and timing variables, extracting only the date portion from datetime values.\n\n```yaml\n- operator: record_count\n id: $records_per_usubjid_date\n group:\n - USUBJID\n - --TESTCD\n - $TIMING_VARIABLES\n regex: \"^\\d{4}-\\d{2}-\\d{2}\"\n```\n\nExample: return the number of records where QNAM starts with \"RACE\" (matches RACE1, RACE2, RACE3, etc.) per USUBJID.\n\n```yaml\n- operator: record_count\n id: $race_records_in_dataset\n filter:\n QNAM: \"RACE&\"\n group:\n - \"USUBJID\"\n```\n\nExample: return the number of records grouped by USUBJID.\n\n```yaml\n- operator: record_count\n id: $records_per_usubjid\n group:\n - USUBJID\n```\n\nExample: return the number of records grouped by USUBJID where FLAGVAR = \"Y\".\n\n```yaml\n- operator: record_count\n id: $flagged_records_per_usubjid\n group:\n - USUBJID\n filter:\n FLAGVAR: \"Y\"\n```\n\nExample: return the number of records grouped by USUBJID and IDVARVAL where QNAM = \"TEST1\" and IDVAR = \"GROUPID\", renaming the IDVARVAL column to GROUPID for subsequent merging.\n\n```yaml\n- operator: record_count\n id: $test1_records_per_usubjid_groupid\n group:\n - USUBJID\n - IDVARVAL\n filter:\n QNAM: \"TEST1\"\n IDVAR: \"GROUPID\"\n group_aliases:\n - USUBJID\n - GROUPID\n```\n\nExample: Group the StudyIdentifier dataset by parent_id and merge the result back to the context dataset StudyVersion using StudyVersion.id == StudyIdentifier.parent_id\n\n```yaml\nScope:\n Entities:\n Include:\n - StudyVersion\nOperations:\n - domain: StudyIdentifier\n filter:\n parent_entity: \"StudyVersion\"\n parent_rel: \"studyIdentifiers\"\n rel_type: \"definition\"\n studyIdentifierScope.organizationType.code: \"C70793\"\n studyIdentifierScope.organizationType.codeSystem: \"http://www.cdisc.org\"\n group:\n - parent_id\n group_aliases:\n - id\n id: $num_sponsor_ids\n operator: record_count\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -310,7 +422,10 @@ "markdownDescription": "\nReturns the required variables ( \"Core\" = Req ) for a given domain and standard Variable Metadata for custom domains will pull from the model while non-custom domains will be from the IG and Model.\n\nInput:\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: required_variables\n id: $required_variables\n```\n\nOutput:\n\n```\n[\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"LBSEQ\", \"LBTESTCD\", \"LBTEST\"]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -320,7 +435,12 @@ "markdownDescription": "\nSplits a dataset column by a given delimiter\n\n```yaml\nOperations:\n - name: PPSPEC\n delimiter: ;\n id: $ppspec_value\n operator: split_by\n```\n" } }, - "required": ["id", "operator", "delimiter", "name"], + "required": [ + "id", + "operator", + "delimiter", + "name" + ], "type": "object" }, { @@ -330,7 +450,10 @@ "markdownDescription": "\nReturns a list of the domains in the study\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -340,7 +463,10 @@ "markdownDescription": "\nReturns a list of the submitted dataset filenames in all uppercase\n\nex. if TS.xpt, AE.xpt, EC.xpt, and SUPPEC.xpt are submitted -> [TS, AE, EC, SUPPEC] will be returned\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -350,7 +476,10 @@ "markdownDescription": "\nReturns a list of valid SDTM domain names from the standard metadata. This can be used to compare extracted suffixes from DOMAIN values or dataset names.\n\nInput\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: standard_domains\n id: $valid_domain_names\n```\n\nOutput\n\n```\n[\"AE\", \"CM\", \"DM\", \"FA\", \"LB\", \"QS\", ...]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -360,7 +489,10 @@ "markdownDescription": "\nReturns the valid terminology package dates for a given standard.\n\nGiven a list of terminology packages:\n\n```\n[\n \"sdtmct-2023-10-26\",\n \"sdtmct-2023-12-13\",\n \"adamct-2023-12-13\",\n \"cdashct-2023-05-19\"\n]\n```\n\nand standard: sdtmig\n\nthe operation will return:\n\n```\n[\"2023-10-26\", \"2023-12-13\"]\n```\n\nBy default, the standard is as specified when running validation - as the validation runtime parameter and/or as specified in the rule header - and the list of terminology packages is obtained from the current cache. If required, the default standard may be overridden using the optional ct_package_types parameter. For example, given the same list of terminology packages, the following operation:\n\n```yaml\nOperations:\n - operator: valid_codelist_dates\n id: $valid_dates\n ct_package_types:\n - SDTM\n - CDASH\n```\n\nwill return:\n\n```\n[\"2023-05-19\", \"2023-10-26\", \"2023-12-13\"]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -370,7 +502,11 @@ "markdownDescription": "\nReturns true if the version of an external dictionary provided in the define.xml file matches the version parsed from the dictionary files.\n\nInput:\n\n```yaml\nOperations:\n - operator: valid_define_external_dictionary_version\n id: $is_valid_loinc_version\n external_dictionary_type: loinc\n```\n\nOutput:\n\n```\n[true, true, true, true]\n```\n" } }, - "required": ["id", "operator", "external_dictionary_type"], + "required": [ + "id", + "operator", + "external_dictionary_type" + ], "type": "object" }, { @@ -428,7 +564,10 @@ "markdownDescription": "\nDetermines whether the values are valid in the following variables:\n\n- --SOCCD (System Organ Class Code)\n- --HLGTCD (High Level Group Term Code)\n- --HLTCD (High Level Term Code)\n- --PTCD (Preferred Term Code)\n- --LLTCD (Lowest Level Term Code)\n\nInput:\n\n```yaml\nOperations:\n - id: $is_valid_meddra_codes\n operator: valid_meddra_code_references\n```\n\nOutput:\n\n```\n[true, false, true, true]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -438,7 +577,10 @@ "markdownDescription": "\nDetermines whether the values are valid in the following variable pairs:\n\n- --SOCCD, --SOC (System Organ Class Code and Term)\n- --HLGTCD, --HLGT (High Level Group Term Code and Term)\n- --HLTCD, --HLT (High Level Term Code and Term)\n- --PTCD, --DECOD (Preferred Term Code and Dictionary-Derived Term)\n- --LLTCD, --LLT (Lowest Level Term Code and Term)\n\nInput:\n\n```yaml\nOperations:\n - id: $is_valid_meddra_pairs\n operator: valid_meddra_code_term_pairs\n```\n\nOutput:\n\n```\n[true, true, false, true, true]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -448,7 +590,10 @@ "markdownDescription": "\nDetermines whether the values are valid in the following variables:\n\n- --SOC (System Organ Class)\n- --HLGT (High Level Group Term)\n- --HLT (High Level Term)\n- --DECOD (Dictionary-Derived Term)\n- --LLT (Lowest Level Term)\n\nInput:\n\n```yaml\nOperations:\n - id: $is_valid_meddra_terms\n operator: valid_meddra_term_references\n```\n\nOutput:\n\n```\n[true, true, false, true, true]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -458,7 +603,11 @@ "markdownDescription": "\nChecks if a reference to whodrug term in name points to the existing code in Atc Text (INA) file.\n\nInput:\n\n```yaml\nOperations:\n - id: $whodrug_refs_valid\n operator: valid_whodrug_references\n```\n\nOutput:\n\n```\n[true, false, true, true]\n```\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -468,7 +617,10 @@ "markdownDescription": "\nReturns a mapping of variable names to the number of times that variable appears in a domain within the study.\n\nInput\n\n```\n{\n \"AE\": [\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"AETERM\", \"AEENDTC\"],\n \"LB\": [\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"LBTESTCD\", \"LBENDTC\"]\n}\n```\n\nOutput\n\n```\n{\n \"STUDYID\": 2,\n \"DOMAIN\": 2,\n \"USUBJID\": 2,\n \"--TERM\": 1,\n \"--TESTCD\": 1,\n \"--ENDTC\": 2\n}\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -478,7 +630,10 @@ "markdownDescription": "\nOperation operates only on original submission datasets regardless of rule type. Flags an error if a column exists is in the submission dataset currently being evaluated.\n\nRule Type: Domain Presence Check\n\n```yaml\nCheck:\n all:\n - name: $MIDS_EXISTS\n operator: equal_to\n value: true\n - name: TM\n operator: not_exists\nOperations:\n - id: $MIDS_EXISTS\n name: MIDS\n operator: variable_exists\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -488,7 +643,10 @@ "markdownDescription": "\nReturns true if a variable is missing from the dataset or if all values within the variable are null or empty string. This operation first checks if the target variable exists in the dataset, and if it does exist, evaluates whether all its values are null or empty.\nThe operation supports two sources via the `source` parameter:\n\n- **`submission`** : checks against the raw submission dataset\n- **`evaluation`** (default): checks against the evaluation dataset built based on the rule type\n\n```yaml" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -498,7 +656,10 @@ "markdownDescription": "\nReturns the set of variable names from the library for the given standard. This operation extracts all variable names across all domains in the specified standard's library metadata.\n\nInput:\n\nValidation Standard: sdtmig\nValidation Version: 3-4\n\n```yaml\n- operator: variable_names\n id: $all_variables\n```\n\nOutput:\n\n```\n[\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"SUBJID\", \"RFSTDTC\", \"RFENDTC\", \"SITEID\", \"AGE\", \"AGEU\", \"SEX\", \"RACE\", \"ETHNIC\", \"ARMCD\", \"ARM\", \"ACTARMCD\", \"ACTARM\", \"COUNTRY\", \"DMDTC\", \"DMDY\", \"AETERM\", \"AEDECOD\", \"AECAT\", \"AESCAT\", \"AEPRESP\", \"AEBODSYS\", \"AEBDSYCD\", \"AESOC\", \"AESOCCD\", \"AELLT\", \"AELLTCD\", \"AEHLT\", \"AEHLTCD\", \"AEHLGT\", \"AEHLGTCD\", \"AEPTCD\", \"AESTDTC\", \"AEENDTC\", \"AESTDY\", \"AEENDY\", \"AEDUR\", \"AESER\", \"AESEV\", \"AEACN\", \"AEREL\", \"AEOUT\", \"AESCAN\", \"AESCONG\", \"AESDISAB\", \"AESDTH\", \"AESHOSP\", \"AESLIFE\", \"AESOD\", \"AECONTRT\", \"AETOXGR\", \"LBTESTCD\", \"LBTEST\", \"LBCAT\", \"LBSCAT\", \"LBSPEC\", \"LBMETHOD\", \"LBORRES\", \"LBORRESU\", \"LBORNRLO\", \"LBORNRHI\", \"LBSTRESC\", \"LBSTRESN\", \"LBSTRESU\", \"LBSTNRLO\", \"LBSTNRHI\", \"LBNRIND\", \"LBNAM\", \"LBSPEC\", \"LBANTREG\", \"LBFAST\", \"LBDRVFL\", \"LBTOX\", \"LBTOXGR\", \"LBSTDTC\", \"LBENDTC\", \"LBSTDY\", \"LBENDY\", \"LBTPT\", \"LBTPTNUM\", \"LBELTM\", \"LBTPTREF\", \"LBRFTDTC\", \"...\"]\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -508,7 +669,11 @@ "markdownDescription": "\nGiven a variable name, returns a mapping of variable values to the number of times that value appears in the variable within all datasets in the study.\n" } }, - "required": ["id", "operator", "name"], + "required": [ + "id", + "operator", + "name" + ], "type": "object" }, { @@ -518,7 +683,10 @@ "markdownDescription": "\nDetermines whether the values are valid and in the correct hierarchical structure in the following variables:\n\n- --DECOD\n- --CLAS\n- --CLASCD\n\nInput:\n\n```yaml\nOperations:\n - id: $valid_whodrug_codes\n operator: whodrug_code_hierarchy\n```\n" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" }, { @@ -528,7 +696,12 @@ "markdownDescription": "\nValidates XHTML fragments in the target column against the specified namespace.\n\n```yaml\nOperations:\n - id: $xhtml_errors\n name: text\n operator: get_xhtml_errors\n namespace: http://www.cdisc.org/ns/usdm/xhtml/v1.0\n```\n\nNote that a local XSD file is required for validation. The file must be stored in the folder indicated by the value of the `LOCAL_XSD_FILE_DIR` default file path and the mapping between the namespace and the local XSD file's `sub-folder/name` must be included in the value of the `LOCAL_XSD_FILE_MAP` default file path.\n" } }, - "required": ["id", "operator", "name", "namespace"], + "required": [ + "id", + "operator", + "name", + "namespace" + ], "type": "object" } ], @@ -591,7 +764,13 @@ "type": "string" }, "dictionary_term_type": { - "enum": ["LLT", "PT", "HLT", "HLGT", "SOC"] + "enum": [ + "LLT", + "PT", + "HLT", + "HLGT", + "SOC" + ] }, "domain": { "anyOf": [ @@ -604,7 +783,9 @@ ] }, "external_dictionary_type": { - "enum": ["meddra"] + "enum": [ + "meddra" + ] }, "filter": { "type": "object" @@ -649,7 +830,10 @@ }, "level": { "type": "string", - "enum": ["codelist", "term"] + "enum": [ + "codelist", + "term" + ] }, "map": { "type": "array", @@ -660,7 +844,9 @@ "type": "string" } }, - "required": ["output"] + "required": [ + "output" + ] } }, "name": { @@ -677,7 +863,11 @@ }, "returntype": { "type": "string", - "enum": ["code", "value", "pref_term"] + "enum": [ + "code", + "value", + "pref_term" + ] }, "source": { "type": "string" @@ -704,6 +894,9 @@ "type": "string" } }, - "required": ["id", "operator"], + "required": [ + "id", + "operator" + ], "type": "object" } diff --git a/resources/schema/rule-merged/Operator.json b/resources/schema/rule-merged/Operator.json index 1c1f13a64..ded87e95a 100644 --- a/resources/schema/rule-merged/Operator.json +++ b/resources/schema/rule-merged/Operator.json @@ -9,7 +9,9 @@ "const": "additional_columns_empty" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -18,7 +20,9 @@ "const": "additional_columns_not_empty" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -28,7 +32,10 @@ "markdownDescription": "\nWill return True if the value in `value` is contained within the collection/iterable in the target column, or if there's an exact match for non-iterable data.\n\nThe operator checks if every value in a column is a list or set. If yes, it compares row-by-row. If any value is blank or a different type (like a string or number), it compares each value against the entire column instead.\n\nExample:\n\n```yaml\n- name: \"--TOXGR\" # Column containing lists like ['GRADE', 'SEVERITY', 'ONSET']\n operator: \"contains\"\n value: \"GRADE\" # True if 'GRADE' is an element in the list\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -38,7 +45,9 @@ "markdownDescription": "\nTrue if all values in `value` are contained within the variable `name`.\n\n> All of ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment') in ACTARM\n\n```yaml\n- name: \"ACTARM\"\n operator: \"contains_all\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n\nThe operator also supports lists:\n\n```yaml\n- name: \"$spec_codelist\"\n operator: \"contains_all\"\n value: \"$ppspec_value\"\n```\n\nWhere:\n\n| $spec_codelist | $ppspec_value |\n| :-------------------------- | :----------------: |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\", \"CODE2\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE2\", \"CODE3\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\"] |\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -48,7 +57,10 @@ "markdownDescription": "\nTrue if the value in `value` is contained within the collection/iterable in the target column, performing case-insensitive comparison.\n\nExample:\n\n```yaml\n- name: \"--TOXGR\" # Column containing lists like ['Grade', 'Severity', 'Onset']\n operator: \"contains_case_insensitive\"\n value: \"grade\" # True if 'Grade'/'GRADE'/'grade' exists in the list\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -58,7 +70,10 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified.\n\nThe `date_component` parameter accepts: `\"year\"`, `\"month\"`, `\"day\"`, `\"hour\"`, `\"minute\"`, `\"second\"`, `\"microsecond\"`, or `\"auto\"`.\n\nWhen `date_component: \"auto\"` is used, the operator automatically detects the precision of both dates and compares at the common (less precise) level.\n\n```yaml\n- name: \"AESTDTC\"\n operator: \"date_equal_to\"\n value: \"RFSTDTC\"\n date_component: \"auto\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -68,7 +83,10 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> Year part of BRTHDTC > 2021\n\n```yaml\n- name: \"BRTHDTC\"\n operator: \"date_greater_than\"\n date_component: \"year\"\n value: \"2021\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -78,7 +96,10 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> Year part of BRTHDTC >= 2021\n\n```yaml\n- name: \"BRTHDTC\"\n operator: \"date_greater_than_or_equal_to\"\n date_component: \"year\"\n value: \"2021\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -88,7 +109,10 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> AEENDTC < AESTDTC\n\n```yaml\n- name: \"AEENDTC\"\n operator: \"date_less_than\"\n value: \"AESTDTC\"\n```\n\n> SSDTC < all DS.DSSTDTC when SSSTRESC = \"DEAD\"\n\n```yaml\nCheck:\n all:\n - name: \"SSSTRESC\"\n operator: \"equal_to\"\n value: \"DEAD\"\n - name: \"SSDTC\"\n operator: \"date_less_than\"\n value: \"$max_ds_dsstdtc\"\nOperations:\n - operator: \"max_date\"\n domain: \"DS\"\n name: \"DSSTDTC\"\n id: \"$max_ds_dsstdtc\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -98,7 +122,10 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> AEENDTC <= AESTDTC\n\n```yaml\n- name: \"AEENDTC\"\n operator: \"date_less_than_or_equal_to\"\n value: \"AESTDTC\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -108,7 +135,10 @@ "markdownDescription": "\nComplement of `date_equal_to`\n\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -118,7 +148,10 @@ "markdownDescription": "\nComplement of `contains`. Returns True when the value is NOT contained within the target collection.\n\n```yaml\n- name: \"--TOXGR\"\n operator: \"does_not_contain\"\n value: \"GRADE\" # True if 'GRADE' is NOT an element in the list\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -128,7 +161,10 @@ "markdownDescription": "\nComplement of `contains_case_insensitive`. Returns True when the value is NOT contained within the target collection (case-insensitive).\n\nExample:\n\n```yaml\n- name: \"--TOXGR\"\n operator: \"does_not_contain_case_insensitive\"\n value: \"grade\" # True if no case variation of 'grade' exists in the list\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -138,7 +174,11 @@ "markdownDescription": "\nComplement of `equals_string_part`\n" } }, - "required": ["operator", "value", "regex"], + "required": [ + "operator", + "value", + "regex" + ], "type": "object" }, { @@ -148,7 +188,12 @@ "markdownDescription": "\nComplement of `has_next_corresponding_record`\n" } }, - "required": ["operator", "ordering", "value", "within"], + "required": [ + "operator", + "ordering", + "value", + "within" + ], "type": "object" }, { @@ -158,7 +203,9 @@ "markdownDescription": "\nValue presence\n\n> --OCCUR = null\n\n```yaml\n- name: --OCCUR\n operator: empty\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -168,7 +215,10 @@ "markdownDescription": "\n> SEENDTC is not empty when it is not the last record, grouped by USUBJID, sorted by SESTDTC\n\n```yaml\n- name: SEENDTC\n operator: empty_within_except_last_row\n ordering: SESTDTC\n value: USUBJID\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -178,7 +228,10 @@ "markdownDescription": "\nSubstring matching\n\n> DOMAIN ending with 'FOOBAR'\n\n```yaml\n- name: \"DOMAIN\"\n operator: \"ends_with\"\n value: \"FOOBAR\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -197,7 +250,10 @@ "type": "boolean" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -216,7 +272,10 @@ "type": "boolean" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -226,7 +285,11 @@ "markdownDescription": "\nChecks that the values in the target column equal the result of parsing the value in the comparison column with a regex\n\n> RDOMAIN equals characters 5 and 6 of SUPP dataset name\n\n```yaml\n- name: RDOMAIN\n operator: equals_string_part\n value: dataset_name\n regex: \".{4}(..).*\"\n```\n" } }, - "required": ["operator", "value", "regex"], + "required": [ + "operator", + "value", + "regex" + ], "type": "object" }, { @@ -236,7 +299,9 @@ "markdownDescription": "\nTrue if the column exists in the current dataframe. (Works for datasets and variables)\n\n> --OCCUR is present in dataset\n\n```yaml\n- name: \"--OCCUR\"\n operator: \"exists\"\n```\n\n> Domain SJ exists\n\n```yaml\nRule Type: Domain Presence Check\nCheck:\n all:\n - name: \"SJ\"\n operator: \"exists\"\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -246,7 +311,10 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL > 0\n\n```yaml\n- name: TSVAL\n operator: greater_than\n value: 0\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -256,7 +324,10 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL >= 0\n\n```yaml\n- name: TSVAL\n operator: greater_than_or_equal_to\n value: 1\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -266,7 +337,9 @@ "markdownDescription": "\nComplement of `has_same_values`\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -276,7 +349,9 @@ "markdownDescription": "\nLength comparison\n\n> Check whether variable values has equal length of another variable.\n\n```yaml\n- name: SEENDTC\n operator: has_equal_length\n value: SESTDTC\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -286,7 +361,12 @@ "markdownDescription": "\nEnsures that a value of a variable `name` in one record is equal to the value of another variable `value` in the next corresponding record. The rows are grouped by `within` and ordered by `ordering`.\n\n> SEENDTC is equal to the SESTDTC of the next record within a USUBJID. Ordered by SESEQ\n\n```yaml\n- name: SEENDTC\n operator: has_next_corresponding_record\n value: SESTDTC\n within: USUBJID\n ordering: SESEQ\n```\n" } }, - "required": ["operator", "ordering", "value", "within"], + "required": [ + "operator", + "ordering", + "value", + "within" + ], "type": "object" }, { @@ -296,7 +376,9 @@ "markdownDescription": "\nComplement of `has_equal_length`\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -306,7 +388,9 @@ "markdownDescription": "\nTrue if all values in `name` are the same\n\n> Condition: MHCAT ^= null\n> Rule: MHCAT ^= the same value for all records\n\n```yaml\nCheck:\n all:\n - name: MHCAT\n operator: non_empty\n - name: MHCAT\n operator: has_same_values\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -316,7 +400,10 @@ "markdownDescription": "\nDuration ISO-8601 check, returns True if a duration is not in ISO-8601 format. The negative parameter must be specified to indicate if negative durations are either allowed (True) or disallowed (False)\n\n> DURVAR is invalid (negative durations disallowed)\n\n```yaml\n- name: \"DURVAR\"\n operator: \"invalid_duration\"\n negative: False\n```\n" } }, - "required": ["operator", "negative"], + "required": [ + "operator", + "negative" + ], "type": "object" }, { @@ -326,7 +413,9 @@ "markdownDescription": "\nThe operator performs date validation against complete and partial dates with uncertainty in the following order:\n\n1. Attempts to parse using [dateutil.parser.isoparse()](https://dateutil.readthedocs.io/en/stable/parser.html)\n2. If parsing fails and the string contains uncertainty indicators (`/`, `--`, `-:`), validates against an extended ISO 8601 dates regex pattern\n3. If parsing succeeds, dates are still validated against the regex pattern.\n\n```yaml\n- name: \"BRTHDTC\"\n operator: \"invalid_date\"\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -336,7 +425,9 @@ "markdownDescription": "\nDate check\n\n> DM.RFSTDTC = complete date\n\n```yaml\n- name: \"RFSTDTC\"\n operator: \"is_complete_date\"\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -346,7 +437,10 @@ "markdownDescription": "\nValue in `name` compared against a list in `value`. The list can have literal values or be a reference to a `$variable`.\n\nThis operator behaves similarly to `contains`. The key distinction: `contains` checks if comparator \u2208 target, while `is_contained_by` checks if target \u2208 comparator.\n\n> ACTARM in ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment')\n\n```yaml\n- name: \"ACTARM\"\n operator: \"is_contained_by\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -356,7 +450,10 @@ "markdownDescription": "\nValue in `name` case insensitive compared against a list in `value`. The list can have literal values or be a reference to a `$variable`.\n\n> ACTARM in ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment')\n\n```yaml\n- name: \"ACTARM\"\n operator: \"is_contained_by_case_insensitive\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -366,7 +463,9 @@ "markdownDescription": "\nComplement of `is_complete_date`\n\nDate check\n\n> DM.RFSTDTC ^= complete date\n\n```yaml\n- name: \"RFSTDTC\"\n operator: \"is_incomplete_date\"\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -376,7 +475,10 @@ "markdownDescription": "\nComplement of `is_contained_by`\n\n> ARM not in ('Screen Failure', 'Not Assigned')\n\n```yaml\n- name: \"ARM\"\n operator: \"is_not_contained_by\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -386,7 +488,10 @@ "markdownDescription": "\nComplement of `is_contained_by_case_insensitive`\n\n> ARM not in ('Screen Failure', 'Not Assigned')\n\n```yaml\n- name: \"ARM\"\n operator: \"is_not_contained_by_case_insensitive\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -396,7 +501,10 @@ "markdownDescription": "\nComplement of `is_ordered_by`\n" } }, - "required": ["operator", "order"], + "required": [ + "operator", + "order" + ], "type": "object" }, { @@ -405,7 +513,10 @@ "const": "is_not_ordered_set" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -415,7 +526,10 @@ "markdownDescription": "\nComplement of `is_unique_relationship`\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -425,7 +539,9 @@ "markdownDescription": "\nComplement of `is_unique_set`.\n\n> --SEQ is not unique within DOMAIN, USUBJID, and --TESTCD\n\n```yaml\n- name: \"--SEQ\"\n operator: is_not_unique_set\n value:\n - \"DOMAIN\"\n - \"USUBJID\"\n - \"--TESTCD\"\n```\n\n> `name` can be a variable containing a list of columns and `value` does not need to be present\n\n```yaml\nRule Type: Dataset Contents Check against Define XML\nCheck:\n all:\n - name: define_dataset_key_sequence # contains list of dataset key columns\n operator: is_not_unique_set\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -435,7 +551,10 @@ "markdownDescription": "\nTrue if the dataset rows are ordered by the values within `name`, given the ordering specified by `order`\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n operator: is_ordered_by\n order: asc\n```\n" } }, - "required": ["operator", "order"], + "required": [ + "operator", + "order" + ], "type": "object" }, { @@ -445,7 +564,10 @@ "markdownDescription": "\nTrue if the dataset rows are in ascending order of the values within `name`, grouped by the values within `value`. Value can either be a single column or multiple.\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n operator: is_ordered_set\n value: USUBJID\n```\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n operator: is_ordered_set\n value:\n - USUBJID\n - \"--TESTCD\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -455,7 +577,10 @@ "markdownDescription": "\nRelationship Integrity Check looking for a 1-1 relationship between name and value. Ensures uniqueness of both name and value.\n\n> AETERM and AEDECOD has a 1-to-1 relationship\n\n```yaml\n- name: AETERM\n operator: is_unique_relationship\n value: AEDECOD\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -465,7 +590,10 @@ "markdownDescription": "\nChecks if a variable maintains consistent values within groups defined by one or more grouping variables. Groups records by specified value(s) and validates that the target variable maintains the same value within each unique combination of grouping variables. When inconsistency is detected within a group, the operator attempts to identify a majority value. If one value appears more frequently than all others, only the minority records (those not matching the majority value) are flagged. If no single majority exists \u2014 i.e., two or more values are tied for the highest frequency \u2014 all records in that group are flagged.\n\nSingle grouping variable - true if the values of BGSTRESU differ within USUBJID:\n\nIf a regex parameter is provided, it is applied to the values of the target variable before the consistency check. The first capture group of the regex is used as the normalized value for comparison. This can be useful when only part of the value should be considered during comparison (for example, comparing only the date portion of a datetime value).\n\n- regex is optional.\n- The pattern must include at least one capture group(or whole regex will be wrapped to capture group).\n- Only the first capture group is used for comparison.\n- If the pattern does not match a value, the original value is used.\n\n```yaml\n- name: \"BGSTRESU\"\n operator: is_inconsistent_across_dataset\n value: \"USUBJID\"\n```\n\nMultiple grouping variables - true if the values of --STRESU differ within each combination of --TESTCD, --CAT, --SCAT, --SPEC, and --METHOD:\n\n```yaml\n- name: \"--STRESU\"\n operator: is_inconsistent_across_dataset\n value:\n - \"--TESTCD\"\n - \"--CAT\"\n - \"--SCAT\"\n - \"--SPEC\"\n - \"--METHOD\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -475,7 +603,9 @@ "markdownDescription": "\nRelationship Integrity Check\n\n> --SEQ is unique within DOMAIN, USUBJID, and --TESTCD\n\n```yaml\n- name: \"--SEQ\"\n operator: is_unique_set\n value:\n - \"DOMAIN\"\n - \"USUBJID\"\n - \"--TESTCD\"\n```\n\n> `name` can be a variable containing a list of columns and `value` does not need to be present\n\n> The `regex` parameter allows you to extract portions of values using a regex pattern before checking uniqueness.\n\n> Compare date only (YYYY-MM-DD) for uniqueness\n\n```yaml\n- name: \"--REPNUM\"\n operator: is_not_unique_set\n value:\n - \"USUBJID\"\n - \"--TESTCD\"\n - \"$TIMING_VARIABLES\"\n regex: '^\\d{4}-\\d{2}-\\d{2}'\n```\n\n> Compare by first N characters of a string\n\n```yaml\n- name: \"ITEM_ID\"\n operator: is_not_unique_set\n value:\n - \"USUBJID\"\n - \"CATEGORY\"\n regex: \"^.{2}\"\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -485,7 +615,10 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL < 1\n\n```yaml\n- name: TSVAL\n operator: less_than\n value: 1\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -495,7 +628,10 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL <= 1\n\n```yaml\n- name: TSVAL\n operator: less_than_or_equal_to\n value: 1\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -505,7 +641,10 @@ "markdownDescription": "\nLength comparison\n\n> SETCD value length > 8\n\n```yaml\n- name: \"SETCD\"\n operator: \"longer_than\"\n value: 8\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -515,7 +654,10 @@ "markdownDescription": "\nLength comparison\n\n> TSVAL value length >= 201\n\n```yaml\n- name: \"TSVAL\"\n operator: \"longer_than_or_equal_to\"\n value: 201\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -525,7 +667,10 @@ "markdownDescription": "\nRegular Expression value matching\n\n- Determine if each string starts with a match of a regular expression. Refer to this pandas documentation: https://pandas.pydata.org/docs/reference/api/pandas.Series.str.match.html\n- To \"search\" for a regex within the entire text, prefix the regex with `.*` and do not use anchors `^` , `$`\n- To do a \"fullmatch\" of a regex with the entire text, suffix the regex with an anchor `$` and do not prefix the regex with `.*`\n- For syntax guide, refer to this Python documentation: [Regular Expression HOWTO](https://docs.python.org/3/howto/regex.html).\n- Suggestion for an on-line regular expression logic. tester: https://regex101.com, choose the Python dialect.\n- For regex token visualization, try https://www.debuggex.com.\n\n> --DOSTXT value is non-numeric\n\n```yaml\n- name: --DOSTXT\n operator: matches_regex\n value: ^\\d*\\.?\\d*$\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -535,7 +680,9 @@ "markdownDescription": "\nComplement of `empty`\n\n> --OCCUR ^= null\n\n```yaml\n- name: --OCCUR\n operator: non_empty\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -545,7 +692,10 @@ "markdownDescription": "\nComplement of `empty_within_except_last_row`\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -555,7 +705,9 @@ "markdownDescription": "\nComplement of `contains_all`\n\n> All of ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment') not in ACTARM\n\n```yaml\n- name: \"ACTARM\"\n operator: \"not_contains_all\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n\nThe operator also supports lists:\n\n```yaml\n- name: \"$spec_codelist\"\n operator: \"not_contains_all\"\n value: \"$ppspec_value\"\n```\n\nWhere:\n\n| $spec_codelist | $ppspec_value |\n| :-------------------------- | :----------------: |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\", \"CODE2\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE2\", \"CODE3\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\"] |\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -574,7 +726,10 @@ "type": "boolean" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -593,7 +748,10 @@ "type": "boolean" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -603,7 +761,9 @@ "markdownDescription": "\nComplement of `exists`\n\n> AEOCCUR not present in dataset\n\n```yaml\n- name: \"AEOCCUR\"\n operator: \"not_exists\"\n```\n\n> Domain SJ does not exist\n\n```yaml\nRule Type: Domain Presence Check\nCheck:\n all:\n - name: \"SJ\"\n operator: \"not_exists\"\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -613,7 +773,10 @@ "markdownDescription": "\nComplement of `matches_regex`\n\n> --TESTCD <= 8 chars and contains only letters, numbers, and underscores and can not start with a number\n\n```yaml\n- name: --TESTCD\n operator: not_matches_regex\n value: ^[A-Z_][A-Z0-9_]{0,7}$\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -623,7 +786,11 @@ "markdownDescription": "\nComplement of `prefix_matches_regex`\n" } }, - "required": ["operator", "prefix", "value"], + "required": [ + "operator", + "prefix", + "value" + ], "type": "object" }, { @@ -633,7 +800,10 @@ "markdownDescription": "\nComplement of `present_on_multiple_rows_within`\n\n```yaml\n- operator: \"not_present_on_multiple_rows_within\"\n name: \"RELID\"\n value: 4 (optional)\n within: \"USUBJID\"\n```\n" } }, - "required": ["operator", "within"], + "required": [ + "operator", + "within" + ], "type": "object" }, { @@ -643,7 +813,11 @@ "markdownDescription": "\nComplement of `suffix_matches_regex`\n\n> QNAM does not end with numbers\n\n```yaml\n- name: \"QNAM\"\n operator: \"not_suffix_matches_regex\"\n suffix: 2\n value: \"\\d\\d\"\n```\n" } }, - "required": ["operator", "suffix", "value"], + "required": [ + "operator", + "suffix", + "value" + ], "type": "object" }, { @@ -653,7 +827,11 @@ "markdownDescription": "\nTrue if the `prefix` number of characters beginning a string in `name` match one of the strings in the list in `value`\n\n> Check if a variable's domain identifier exists in the study\n\n```yaml\n- name: variable_name\n operator: prefix_is_contained_by\n prefix: 2\n value: $study_domains\n```\n" } }, - "required": ["operator", "prefix", "value"], + "required": [ + "operator", + "prefix", + "value" + ], "type": "object" }, { @@ -663,7 +841,11 @@ "markdownDescription": "\nTrue if the `prefix` number of characters beginning a string in `name` match the string in `value`\n\n```yaml\n- name: dataset_name\n operator: prefix_equal_to\n prefix: 2\n value: DOMAIN\n```\n" } }, - "required": ["operator", "prefix", "value"], + "required": [ + "operator", + "prefix", + "value" + ], "type": "object" }, { @@ -673,7 +855,11 @@ "markdownDescription": "\nComplement of `prefix_is_contained_by`\n" } }, - "required": ["operator", "prefix", "value"], + "required": [ + "operator", + "prefix", + "value" + ], "type": "object" }, { @@ -683,7 +869,11 @@ "markdownDescription": "\nTrue if the `prefix` number of characters beginning a string in `name` match a regular expression in `value`\n\n```yaml\n- name: DOMAIN\n operator: prefix_matches_regex\n prefix: 2\n value: (AP|ap)\n```\n" } }, - "required": ["operator", "prefix", "value"], + "required": [ + "operator", + "prefix", + "value" + ], "type": "object" }, { @@ -693,7 +883,11 @@ "markdownDescription": "\nComplement of `prefix_equal_to`\n" } }, - "required": ["operator", "prefix", "value"], + "required": [ + "operator", + "prefix", + "value" + ], "type": "object" }, { @@ -703,7 +897,10 @@ "markdownDescription": "\nTrue if the same value of `name` is present on multiple rows, grouped by `within`. A maximum allowed number of occurrences can be specified in the value attribute. In this instance the value: 4 means that an error will be flagged if the same value appears more than 4 times within a USUBJID. By default the operator will flag any time a value appears more than once.\n\n```yaml\n- operator: \"present_on_multiple_rows_within\"\n name: \"RELID\"\n value: 4 (optional)\n within: \"USUBJID\"\n```\n" } }, - "required": ["operator", "within"], + "required": [ + "operator", + "within" + ], "type": "object" }, { @@ -713,7 +910,10 @@ "markdownDescription": "\nWill raise an issue if at least one of the values in `name` is the same as one of the values in `value`. See [shares_no_elements_with](#shares_no_elements_with).\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -723,7 +923,10 @@ "markdownDescription": "\nWill raise an issue if exactly one of the values in `name` is the same as one of the values in `value`. See [shares_no_elements_with](#shares_no_elements_with).\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -733,7 +936,10 @@ "markdownDescription": "\nWill raise an issue if the values in `name` do not share any of the values in `value`\n\n> Check if $dataset_variables shares no elements with $timing_variables\n\n```yaml\nRule Type: Dataset Metadata Check # One record per dataset\nCheck:\n - all:\n name: $dataset_variables\n operator: shares_no_elements_with\n value: $timing_variables\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -743,7 +949,10 @@ "markdownDescription": "\nLength comparison\n\n> SETCD value length < 9\n\n```yaml\n- name: \"SETCD\"\n operator: \"shorter_than\"\n value: 9\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -753,7 +962,10 @@ "markdownDescription": "\nLength comparison\n\n> TSVAL value length <= 200\n\n```yaml\n- name: \"TSVAL\"\n operator: \"shorter_than_or_equal_to\"\n value: 201\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -763,7 +975,9 @@ "markdownDescription": "\nSplits a string by a separator and checks if both parts have equal length. Generic operator for validating paired data formats where both parts must have the same level of detail or precision.\n\nParameters:\n\n- `separator`: The delimiter to split on (default: \"/\")\n\n> Check that string parts separated by a delimiter have equal length\n\n```yaml\n- name: --DTC\n operator: split_parts_have_equal_length\n separator: \"/\"\n```\n\nUse cases:\n\n- **Date/time intervals**: `2003-12-15T10:00/2003-12-15T10:30` \u2192 True (both 16 characters)\n- **Date ranges**: `2003-12-01/2003-12-10` \u2192 True (both 10 characters)\n- **Version ranges**: `1.2.3/2.0.0` \u2192 True (both 5 characters)\n- **Product codes**: `ABC-123/XYZ-789` \u2192 True (both 7 characters)\n\nInvalid example:\n\n- `2003-12-15T10:00/2003-12-15T10:30:15` \u2192 False (16 vs 19 characters - different precision)\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -773,7 +987,9 @@ "markdownDescription": "\nComplement of `split_parts_have_equal_length`. Returns True when parts have unequal lengths (indicates a violation).\n\n```yaml\n- name: --DTC\n operator: split_parts_have_unequal_length\n separator: \"/\"\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -783,7 +999,10 @@ "markdownDescription": "\nSubstring matching\n\n> DOMAIN beginning with 'AP'\n\n```yaml\n- name: \"DOMAIN\"\n operator: \"starts_with\"\n value: \"AP\"\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -793,7 +1012,11 @@ "markdownDescription": "\nTrue if the `suffix` number of characters ending a string in `name` match the string in `value`\n\n```yaml\n- name: dataset_name\n operator: suffix_equal_to\n prefix: 2\n value: DOMAIN\n```\n" } }, - "required": ["operator", "suffix", "value"], + "required": [ + "operator", + "suffix", + "value" + ], "type": "object" }, { @@ -803,7 +1026,11 @@ "markdownDescription": "\nTrue if the `suffix` number of characters ending a string in `name` match one of the strings in the list in `value`\n\n> Check if a supp's parent domain exists in the study\n\n```yaml\n- name: dataset_name\n operator: suffix_is_contained_by\n prefix: 2\n value: $study_domains\n```\n" } }, - "required": ["operator", "suffix", "value"], + "required": [ + "operator", + "suffix", + "value" + ], "type": "object" }, { @@ -813,7 +1040,11 @@ "markdownDescription": "\nComplement of `suffix_is_contained_by`\n" } }, - "required": ["operator", "suffix", "value"], + "required": [ + "operator", + "suffix", + "value" + ], "type": "object" }, { @@ -823,7 +1054,11 @@ "markdownDescription": "\nTrue if the `suffix` number of characters ending a string in `name` match a regular expression in `value`\n\n> QNAM ends with numbers\n\n```yaml\n- name: \"QNAM\"\n operator: \"suffix_matches_regex\"\n suffix: 2\n value: \"\\d\\d\"\n```\n" } }, - "required": ["operator", "suffix", "value"], + "required": [ + "operator", + "suffix", + "value" + ], "type": "object" }, { @@ -833,7 +1068,11 @@ "markdownDescription": "\nComplement of `suffix_equal_to`\n" } }, - "required": ["operator", "suffix", "value"], + "required": [ + "operator", + "suffix", + "value" + ], "type": "object" }, { @@ -843,7 +1082,11 @@ "markdownDescription": "\nComplement of `target_is_sorted_by`\n" } }, - "required": ["operator", "value", "within"], + "required": [ + "operator", + "value", + "within" + ], "type": "object" }, { @@ -853,7 +1096,11 @@ "markdownDescription": "\nTrue if the values in name are ordered according to the values specified by value\nin ascending/descending order, grouped by the values in within. Each value entry\nrequires a variable name, a sort_order of asc or desc, and an optional\nnull_position of first or last (defaults to last) which controls where null/empty\ncomparator values are placed in the expected ordering. Within accepts either a\nsingle column or an ordered list of columns. Columns can be either number or Char\nDates in ISO8601 YYYY-MM-DD format. Date value(s) with different precisions that\noverlap (e.g. 2005-10, 2005-10-3 and 2005-10-08) are all flagged as not sorted as\ntheir order cannot be inferred.\n\nOptionally supports a `regex` parameter that extracts a portion of the target\nvalue for sorting. The regex must contain at least one capturing group. The first\ncaptured group is extracted and converted to numeric if possible, allowing proper\nsorting of sequence numbers (e.g., \"MIDS1\", \"MIDS2\", ..., \"MIDS10\" with regex\n`.*?(\\\\d+)$`). This is particularly useful for variables that end with sequence\nnumbers that may or may not be zero-padded.\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n within:\n - USUBJID\n - MIDSTYPE\n operator: target_is_sorted_by\n value:\n - name: --STDTC\n sort_order: asc\n null_position: last\n```\n\nExample with regex for extracting sequence numbers:\n\n```yaml\nCheck:\n all:\n - name: MIDS\n operator: target_is_sorted_by\n regex: \".*?(\\\\d+)$\" # Extract trailing digits, convert to numeric\n value:\n - name: SMSTDTC\n sort_order: asc\n within:\n - USUBJID\n - MIDSTYPE\n```\n" } }, - "required": ["operator", "value", "within"], + "required": [ + "operator", + "value", + "within" + ], "type": "object" }, { @@ -863,7 +1110,10 @@ "markdownDescription": "\nComplement of `value_has_multiple_references`\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -873,7 +1123,10 @@ "markdownDescription": "\nTrue if the value in `name` has more than one count in the dictionary defined in `value`\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -883,7 +1136,10 @@ "markdownDescription": "\nChecks for inconsistencies in enumerated columns of a DataFrame. Starting with the smallest/largest enumeration of the given variable, returns True if VARIABLE(N+1) is populated but VARIABLE(N) is not populated. Repeats for all variables belonging to the enumeration. Note that the initial variable will not have an index (VARIABLE) and the next enumerated variable has index 1 (VARIABLE1).\n\nex: Check if there are inconsistencies in the TSVAL columns (TSVAL, TSVAL1, TSVAL2, etc.)\n\n```yaml\nCheck:\n all:\n - name: \"TSVAL\"\n operator: \"inconsistent_enumerated_columns\"\n```\n" } }, - "required": ["operator", "name"], + "required": [ + "operator", + "name" + ], "type": "object" }, { @@ -893,7 +1149,10 @@ "markdownDescription": "\nChecks if elements in the target list appear in the same relative order in the comparator list.\n\n> Check if dataset column order is a correctly ordered subset of library column order\n\n```yaml\n- name: $column_order_from_dataset\n operator: is_ordered_subset_of\n value: $column_order_from_library\n```\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -903,7 +1162,10 @@ "markdownDescription": "\nComplement of `is_ordered_subset_of`\n" } }, - "required": ["operator", "value"], + "required": [ + "operator", + "value" + ], "type": "object" }, { @@ -913,7 +1175,9 @@ "markdownDescription": "\nValidates that variable labels follow proper title case formatting rules using the titlecase PyPi library. Title case capitalizes the first word and all major words, while keeping articles (a, an, the), conjunctions (and, but, or), and prepositions (in, of, for) in lowercase unless they are the first word. \nNOTE: The titlecase library may produce false positives or false negatives in syntactic edge cases (e.g. hyphenated words, slash-separated terms, uncommon prepositions).\n\n> Check that AELABEL values are in proper title case\n\n```yaml\n- name: AELABEL\n operator: is_title_case\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" }, { @@ -923,13 +1187,18 @@ "markdownDescription": "\nComplement of `is_title_case`. Returns True when values are NOT in proper title case.\n\n> Flag AELABEL values that violate title case rules\n\n```yaml\n- name: AELABEL\n operator: is_not_title_case\n```\n" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" } ], "properties": { "comparator": { - "type": ["number", "string"] + "type": [ + "number", + "string" + ] }, "context": { "type": "string" @@ -967,18 +1236,27 @@ "type": "boolean" }, "codelistcheck": { - "enum": ["code", "value"], + "enum": [ + "code", + "value" + ], "type": "string" }, "codelistlevel": { - "enum": ["term", "codelist"], + "enum": [ + "term", + "codelist" + ], "type": "string" }, "operator": { "type": "string" }, "order": { - "enum": ["asc", "dsc"], + "enum": [ + "asc", + "dsc" + ], "type": "string" }, "ordering": { @@ -996,17 +1274,25 @@ "value": { "oneOf": [ { - "type": ["boolean", "number", "string"] + "type": [ + "boolean", + "number", + "string" + ] }, { "items": { - "type": ["number"] + "type": [ + "number" + ] }, "type": "array" }, { "items": { - "type": ["string"] + "type": [ + "string" + ] }, "type": "array" }, @@ -1017,7 +1303,10 @@ "$ref": "Operator.json#/properties/name" }, "null_position": { - "enum": ["first", "last"], + "enum": [ + "first", + "last" + ], "type": "string" }, "order": { @@ -1060,6 +1349,8 @@ "type": "string" } }, - "required": ["operator"], + "required": [ + "operator" + ], "type": "object" } diff --git a/resources/schema/rule-merged/Organization_CDISC.json b/resources/schema/rule-merged/Organization_CDISC.json index db1041921..9aaef8a76 100644 --- a/resources/schema/rule-merged/Organization_CDISC.json +++ b/resources/schema/rule-merged/Organization_CDISC.json @@ -22,7 +22,9 @@ "const": "Failure" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -38,7 +40,9 @@ "type": "object" }, "Version": { - "enum": ["5.0"] + "enum": [ + "5.0" + ] } }, "type": "object" @@ -47,7 +51,12 @@ "type": "array" }, "Version": { - "enum": ["1.0", "1.1", "1.2", "1.3"] + "enum": [ + "1.0", + "1.1", + "1.2", + "1.3" + ] } }, "type": "object" @@ -66,7 +75,9 @@ "const": "Success" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -79,13 +90,19 @@ "type": "string" }, "Version": { - "enum": ["1", "2", "3"] + "enum": [ + "1", + "2", + "3" + ] } }, "type": "object" }, "Version": { - "enum": ["2.0"] + "enum": [ + "2.0" + ] } }, "type": "object" @@ -94,7 +111,11 @@ "type": "array" }, "Version": { - "enum": ["3.2", "3.3", "3.4"] + "enum": [ + "3.2", + "3.3", + "3.4" + ] } }, "type": "object" @@ -113,7 +134,9 @@ "const": "Success" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -129,7 +152,9 @@ "type": "object" }, "Version": { - "enum": ["5.0"] + "enum": [ + "5.0" + ] } }, "type": "object" @@ -138,7 +163,11 @@ "type": "array" }, "Version": { - "enum": ["3.0", "3.1", "3.1.1"] + "enum": [ + "3.0", + "3.1", + "3.1.1" + ] } }, "type": "object" @@ -157,7 +186,9 @@ "const": "Success" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -173,7 +204,9 @@ "type": "object" }, "Version": { - "enum": ["5.0"] + "enum": [ + "5.0" + ] } }, "type": "object" @@ -182,7 +215,10 @@ "type": "array" }, "Version": { - "enum": ["1.1", "1.2"] + "enum": [ + "1.1", + "1.2" + ] } }, "type": "object" @@ -201,7 +237,9 @@ "const": "Success" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -217,7 +255,9 @@ "type": "object" }, "Version": { - "enum": ["5.0"] + "enum": [ + "5.0" + ] } }, "type": "object" @@ -226,7 +266,9 @@ "type": "array" }, "Version": { - "enum": ["1.0"] + "enum": [ + "1.0" + ] } }, "type": "object" @@ -245,7 +287,9 @@ "const": "Success" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -261,7 +305,9 @@ "type": "object" }, "Version": { - "enum": ["1.0"] + "enum": [ + "1.0" + ] } }, "type": "object" @@ -270,13 +316,24 @@ "type": "array" }, "Version": { - "enum": ["1.0"] + "enum": [ + "1.0" + ] }, "Substandard": { - "enum": ["SDTM", "SEND", "ADaM", "CDASH"] + "enum": [ + "SDTM", + "SEND", + "ADaM", + "CDASH" + ] } }, - "required": ["Name", "Version", "Substandard"], + "required": [ + "Name", + "Version", + "Substandard" + ], "type": "object" }, { @@ -297,13 +354,17 @@ "type": "string" }, "Version": { - "enum": ["1"] + "enum": [ + "1" + ] } }, "type": "object" }, "Version": { - "enum": ["1.0"] + "enum": [ + "1.0" + ] } }, "type": "object" @@ -312,7 +373,10 @@ "type": "array" }, "Version": { - "enum": ["3.0", "4.0"] + "enum": [ + "3.0", + "4.0" + ] } }, "type": "object" diff --git a/resources/schema/rule-merged/Organization_Custom.json b/resources/schema/rule-merged/Organization_Custom.json index bf5bd7276..c5f591394 100644 --- a/resources/schema/rule-merged/Organization_Custom.json +++ b/resources/schema/rule-merged/Organization_Custom.json @@ -9,7 +9,10 @@ "type": "string", "description": "Name of your custom organization", "not": { - "enum": ["CDISC", "FDA"] + "enum": [ + "CDISC", + "FDA" + ] } }, "Standards": { @@ -45,7 +48,9 @@ "description": "Version of the rule" } }, - "required": ["Id"], + "required": [ + "Id" + ], "type": "object" }, "Version": { @@ -55,7 +60,10 @@ "Criteria": { "properties": { "Type": { - "enum": ["Failure", "Success"], + "enum": [ + "Failure", + "Success" + ], "type": "string" }, "Plain Language Expression": { @@ -70,30 +78,46 @@ "type": "string" } }, - "required": ["Rule"], + "required": [ + "Rule" + ], "type": "object" } }, - "required": ["Type"], + "required": [ + "Type" + ], "anyOf": [ { - "required": ["Logical Expression"] + "required": [ + "Logical Expression" + ] }, { - "required": ["Plain Language Expression"] + "required": [ + "Plain Language Expression" + ] } ], "type": "object" } }, - "required": ["Origin", "Rule Identifier", "Version"], + "required": [ + "Origin", + "Rule Identifier", + "Version" + ], "type": "object" }, "minItems": 1, "type": "array" } }, - "required": ["Name", "References", "Version"], + "required": [ + "Name", + "References", + "Version" + ], "type": "object" }, "minItems": 1, @@ -141,7 +165,10 @@ }, "OutputType": { "type": "string", - "enum": ["Check", "Listing"], + "enum": [ + "Check", + "Listing" + ], "description": "Output type of the rule validation result" }, "Keywords": { @@ -155,7 +182,11 @@ "additionalProperties": true } }, - "required": ["Organization", "Standards", "Category"], + "required": [ + "Organization", + "Standards", + "Category" + ], "type": "object", "$defs": { "metadata": { diff --git a/resources/schema/rule-merged/Organization_FDA.json b/resources/schema/rule-merged/Organization_FDA.json index b0f7de783..94af54bc4 100644 --- a/resources/schema/rule-merged/Organization_FDA.json +++ b/resources/schema/rule-merged/Organization_FDA.json @@ -41,7 +41,10 @@ } } ], - "required": ["Document", "Cited Guidance"], + "required": [ + "Document", + "Cited Guidance" + ], "type": "object" }, "type": "array" @@ -52,7 +55,9 @@ "const": "Success" } }, - "required": ["Type"], + "required": [ + "Type" + ], "type": "object" }, "Origin": { @@ -68,7 +73,9 @@ "type": "object" }, "Version": { - "enum": ["1.5"] + "enum": [ + "1.5" + ] } }, "type": "object" @@ -84,7 +91,11 @@ "const": "SDTMIG" }, "Version": { - "enum": ["3.2", "3.3", "3.4"] + "enum": [ + "3.2", + "3.3", + "3.4" + ] } }, "type": "object" @@ -95,7 +106,11 @@ "const": "SENDIG" }, "Version": { - "enum": ["3.0", "3.1", "3.1.1"] + "enum": [ + "3.0", + "3.1", + "3.1.1" + ] } }, "type": "object" @@ -106,7 +121,9 @@ "const": "SENDIG-AR" }, "Version": { - "enum": ["1.0"] + "enum": [ + "1.0" + ] } }, "type": "object" @@ -117,7 +134,10 @@ "const": "SENDIG-DART" }, "Version": { - "enum": ["1.1", "1.2"] + "enum": [ + "1.1", + "1.2" + ] } }, "type": "object" @@ -128,7 +148,9 @@ "const": "SENDIG-GENETOX" }, "Version": { - "enum": ["1.0"] + "enum": [ + "1.0" + ] } }, "type": "object" diff --git a/resources/schema/rule-merged/Rule_Type.json b/resources/schema/rule-merged/Rule_Type.json index cd4e761fa..3e65d71cc 100644 --- a/resources/schema/rule-merged/Rule_Type.json +++ b/resources/schema/rule-merged/Rule_Type.json @@ -20,7 +20,7 @@ { "const": "Define Item Metadata Check against Library Metadata", "title": "Define xml metadata at variable level and corresponding library variable metadata", - "markdownDescription": "\n#### Columns\n\n- `define_variable_name`\n- `define_variable_label`\n- `define_variable_data_type`\n- `define_variable_role`\n- `define_variable_size`\n- `define_variable_ccode`\n- `define_variable_format`\n- `define_variable_allowed_terms`\n- `define_variable_origin_type`\n- `define_variable_is_collected`\n- `define_variable_has_no_data`\n- `define_variable_order_number`\n- `define_variable_has_codelist`\n- `define_variable_codelist_coded_values`\n- `define_variable_codelist_coded_codes`\n- `define_variable_mandatory`\n- `define_variable_has_comment`\n- `define_variable_has_method`\n- `library_variable_name`\n- `library_variable_order_number`\n- `library_variable_label`\n- `library_variable_data_type`\n- `library_variable_role`\n- `library_variable_core`\n- `library_variable_has_codelist`\n- `library_variable_ccode`\n\n#### Rule Macro\n\nChecks variable-level metadata, codelists, and codelist terms from Define-XML against the corresponding standard variable definitions from the CDISC Library.\n" + "markdownDescription": "\n#### Columns\n\n- `define_variable_name`\n- `define_variable_label`\n- `define_variable_data_type`\n- `define_variable_role`\n- `define_variable_size`\n- `define_variable_ccode`\n- `define_variable_format`\n- `define_variable_allowed_terms`\n- `define_variable_origin_type`\n- `define_variable_is_collected`\n- `define_variable_has_no_data`\n- `define_variable_order_number`\n- `define_variable_has_codelist`\n- `define_variable_codelist_coded_values`\n- `define_variable_codelist_coded_codes`\n- `define_variable_mandatory`\n- `define_variable_has_comment`\n- `define_variable_has_method`\n- `define_vlm_ccode_matches_library_all`\n- `define_vlm_ccode_matches_library_any`\n- `define_vlm_ccode_missing_any`\n- `define_vlm_ccodes`\n- `define_vlm_has_codelist_all`\n- `define_vlm_has_codelist_any`\n- `define_vlm_item_count`\n- `define_vlm_present`\n- `library_variable_name`\n- `library_variable_order_number`\n- `library_variable_label`\n- `library_variable_data_type`\n- `library_variable_role`\n- `library_variable_core`\n- `library_variable_has_codelist`\n- `library_variable_ccode`\n\n#### Rule Macro\n\nChecks variable-level metadata, codelists, and codelist terms from Define-XML against the corresponding standard variable definitions from the CDISC Library.\n" }, { "const": "Domain Presence Check", @@ -79,7 +79,8 @@ }, { "const": "Variable Metadata Check against Define XML and Library Metadata", - "title": "Combines metadata at the variable level with corresponding define-xml metadata at variable level and corresponding library variable metadata" + "title": "Combines metadata at the variable level with corresponding define-xml metadata at variable level and corresponding library variable metadata", + "markdownDescription": "\n#### Columns\n\n- `variable_name`\n- `variable_label`\n- `variable_size`\n- `variable_order_number`\n- `variable_data_type`\n- `define_variable_name`\n- `define_variable_label`\n- `define_variable_data_type`\n- `define_variable_is_collected`\n- `define_variable_role`\n- `define_variable_size`\n- `define_variable_ccode`\n- `define_variable_format`\n- `define_variable_allowed_terms`\n- `define_variable_origin_type`\n- `define_variable_has_no_data`\n- `define_variable_order_number`\n- `define_variable_length`\n- `define_variable_has_codelist`\n- `define_variable_codelist_coded_values`\n- `define_variable_codelist_coded_codes`\n- `define_variable_mandatory`\n- `define_variable_has_comment`\n- `define_variable_has_method`\n- `define_vlm_ccode_matches_library_all`\n- `define_vlm_ccode_matches_library_any`\n- `define_vlm_ccode_missing_any`\n- `define_vlm_ccodes`\n- `define_vlm_has_codelist_all`\n- `define_vlm_has_codelist_any`\n- `define_vlm_item_count`\n- `define_vlm_present`\n- `library_variable_name`\n- `library_variable_role`\n- `library_variable_label`\n- `library_variable_core`\n- `library_variable_order_number`\n- `library_variable_data_type`\n- `library_variable_ccode`\n- `variable_has_empty_values`\n\n#### Rule Macro\n\nCombines variable-level metadata from submission dataset contents against both Define-XML variable metadata and CDISC Library standard variable metadata simultaneously.\n" }, { "const": "Value Check with Dataset Metadata", diff --git a/resources/schema/rule/MetaVariables.json b/resources/schema/rule/MetaVariables.json index 1d7ea933f..f452f7198 100644 --- a/resources/schema/rule/MetaVariables.json +++ b/resources/schema/rule/MetaVariables.json @@ -95,6 +95,30 @@ { "const": "define_vlm_ccode" }, + { + "const": "define_vlm_ccode_matches_library_all" + }, + { + "const": "define_vlm_ccode_matches_library_any" + }, + { + "const": "define_vlm_ccode_missing_any" + }, + { + "const": "define_vlm_ccodes" + }, + { + "const": "define_vlm_has_codelist_all" + }, + { + "const": "define_vlm_has_codelist_any" + }, + { + "const": "define_vlm_item_count" + }, + { + "const": "define_vlm_present" + }, { "const": "define_vlm_codelist_coded_values" }, diff --git a/resources/schema/rule/MetaVariables.md b/resources/schema/rule/MetaVariables.md index 8da17739a..fd0e0fd5b 100644 --- a/resources/schema/rule/MetaVariables.md +++ b/resources/schema/rule/MetaVariables.md @@ -138,6 +138,38 @@ ValueListDef.ItemDef.CodeList.CodeListItem.Decode.TranslatedText ValueListDef.ItemDef.CodeList.Alias.Name +## define_vlm_ccode_matches_library_all + +Boolean indicating whether all VLM items' codelist codes match the library standard codelist code for this variable (all non-empty define_vlm_ccodes equal library_variable_ccode) + +## define_vlm_ccode_matches_library_any + +Boolean indicating whether at least one VLM item's codelist code matches the library standard codelist code for this variable (any define_vlm_ccode equals library_variable_ccode) + +## define_vlm_ccode_missing_any + +Boolean indicating whether at least one VLM item has an empty or missing codelist code (ValueListDef.ItemDef.CodeList.Alias.Name is empty) + +## define_vlm_ccodes + +List of distinct non-empty codelist codes from all VLM items for this variable. Derived from ValueListDef.ItemDef.CodeList.Alias.Name entries + +## define_vlm_has_codelist_all + +Boolean indicating whether all VLM items have a CodeListRef (all ValueListDef.ItemDef.CodeListRef exist) + +## define_vlm_has_codelist_any + +Boolean indicating whether at least one VLM item has a CodeListRef (ValueListDef.ItemDef.CodeListRef exists) + +## define_vlm_item_count + +Count of VLM items (ValueListDef.ItemDef entries) for this variable + +## define_vlm_present + +Boolean indicating whether this variable has one or more VLM (Value Level Metadata) items defined in Define-XML ValueListDef.ItemDef + ## define_vlm_codelist_coded_values ValueListDef.ItemDef.CodeList.[CodeListItem/EnumeratedItem].CodedValue diff --git a/resources/schema/rule/Rule_Type.md b/resources/schema/rule/Rule_Type.md index 00100c64e..f52f3d261 100644 --- a/resources/schema/rule/Rule_Type.md +++ b/resources/schema/rule/Rule_Type.md @@ -313,6 +313,14 @@ all: - `define_variable_mandatory` - `define_variable_has_comment` - `define_variable_has_method` +- `define_vlm_ccode_matches_library_all` +- `define_vlm_ccode_matches_library_any` +- `define_vlm_ccode_missing_any` +- `define_vlm_ccodes` +- `define_vlm_has_codelist_all` +- `define_vlm_has_codelist_any` +- `define_vlm_item_count` +- `define_vlm_present` - `library_variable_name` - `library_variable_order_number` - `library_variable_label` @@ -579,7 +587,7 @@ Combines variable-level metadata from submission dataset contents against the ma Combines variable-level metadata from submission dataset contents against the corresponding CDISC Library standard variable metadata. -## Variables Metadata Check against Define XML and Library Metadata +## Variable Metadata Check against Define XML and Library Metadata #### Columns @@ -607,6 +615,14 @@ Combines variable-level metadata from submission dataset contents against the co - `define_variable_mandatory` - `define_variable_has_comment` - `define_variable_has_method` +- `define_vlm_ccode_matches_library_all` +- `define_vlm_ccode_matches_library_any` +- `define_vlm_ccode_missing_any` +- `define_vlm_ccodes` +- `define_vlm_has_codelist_all` +- `define_vlm_has_codelist_any` +- `define_vlm_item_count` +- `define_vlm_present` - `library_variable_name` - `library_variable_role` - `library_variable_label` diff --git a/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py b/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py index 341ddb0f0..575d5d3d9 100644 --- a/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py +++ b/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py @@ -179,6 +179,14 @@ def test_build_combined_metadata( "define_variable_mandatory", "define_variable_has_comment", "define_variable_has_method", + "define_vlm_present", + "define_vlm_item_count", + "define_vlm_ccodes", + "define_vlm_has_codelist_any", + "define_vlm_has_codelist_all", + "define_vlm_ccode_missing_any", + "define_vlm_ccode_matches_library_any", + "define_vlm_ccode_matches_library_all", "library_variable_name", "library_variable_label", "library_variable_data_type", @@ -218,6 +226,14 @@ def test_build_combined_metadata( assert not usubjid_row["variable_is_empty"] aeterm_row = result[result["variable_name"] == "AETERM"].iloc[0] + assert aeterm_row["define_vlm_present"] == True + assert aeterm_row["define_vlm_item_count"] == 2 + assert aeterm_row["define_vlm_ccodes"] == [] # no codelists on either VLM item + assert aeterm_row["define_vlm_has_codelist_any"] == False + assert aeterm_row["define_vlm_has_codelist_all"] == False + assert aeterm_row["define_vlm_ccode_missing_any"] == True # both ccodes are empty + assert aeterm_row["define_vlm_ccode_matches_library_any"] == False + assert aeterm_row["define_vlm_ccode_matches_library_all"] == False assert aeterm_row["variable_size"] == 200.0 assert aeterm_row["variable_order_number"] == 9.0 assert aeterm_row["variable_data_type"] == "Char" @@ -228,6 +244,17 @@ def test_build_combined_metadata( assert len(result) == 3 + for var in ["STUDYID", "USUBJID"]: + row = result[result["variable_name"] == var].iloc[0] + assert row["define_vlm_present"] == False + assert row["define_vlm_item_count"] == 0 + assert row["define_vlm_ccodes"] == [] + assert row["define_vlm_has_codelist_any"] == False + assert row["define_vlm_has_codelist_all"] == False + assert row["define_vlm_ccode_missing_any"] == False + assert row["define_vlm_ccode_matches_library_any"] == False + assert row["define_vlm_ccode_matches_library_all"] == False + for _, row in result.iterrows(): assert row["library_variable_name"] != "" assert row["library_variable_role"] in ["Identifier", "Topic"] From 5011df789e679e65409a59577c36a7599fbfbee6 Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Thu, 16 Jul 2026 16:27:50 -0400 Subject: [PATCH 02/13] Adjusted to add test rule and test files --- .../test_Issues/test_CoreIssue1443.py | 101 ++++++++++++++++++ tests/resources/CoreIssue1443/Dataset.json | 59 ++++++++++ tests/resources/CoreIssue1443/Rule.yml | 57 ++++++++++ 3 files changed, 217 insertions(+) create mode 100644 tests/QARegressionTests/test_Issues/test_CoreIssue1443.py create mode 100644 tests/resources/CoreIssue1443/Dataset.json create mode 100644 tests/resources/CoreIssue1443/Rule.yml diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py new file mode 100644 index 000000000..55f20a427 --- /dev/null +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py @@ -0,0 +1,101 @@ +import os +import subprocess +import openpyxl +import pytest +from conftest import get_python_executable +from QARegressionTests.globals import ( + dataset_details_sheet, + issue_datails_sheet, + rules_report_sheet, + issue_sheet_variable_column, + issue_sheet_coreid_column, +) + + +@pytest.mark.regression +def test_vlm_fallback_codelist_check(): + """ + Test for GitHub Issue #1443: Rule blocked: SEND49 + Validates that rules can use VLM (Value Level Metadata) columns as fallback + when variable-level codelist is not available. + + Scenario: + - VSORRESU variable has NO variable-level CodeListRef (empty ccode) + - VSORRESU has VLM items with CodeListRef that match library standard + - Rule should detect this mismatch and report ISSUE using VLM fallback columns + """ + command = [ + f"{get_python_executable()}", + "-m", + "core", + "validate", + "-s", + "sdtmig", + "-v", + "3-4", + "-dp", + os.path.join( + "tests", + "resources", + "CoreIssue1443", + "Dataset.json", + ), + "-lr", + os.path.join("tests", "resources", "CoreIssue1443", "Rule.yml"), + "-dxp", + os.path.join("tests", "resources", "CoreIssue1443", "Define.xml"), + ] + subprocess.run(command, check=True) + + # Get the latest created Excel file + files = os.listdir() + excel_files = [ + file + for file in files + if file.startswith("CORE-Report-") and file.endswith(".xlsx") + ] + excel_file_path = sorted(excel_files)[-1] + + # Open the Excel file + workbook = openpyxl.load_workbook(excel_file_path) + + # Go to the "Issue Details" sheet + sheet = workbook[issue_datails_sheet] + + # Check Variable(s) column (H) + variables_names_column = sheet["H"] + variables_names_values = [ + cell.value for cell in variables_names_column[1:] if cell.value is not None + ] + + # Verify that VSORRESU issue is detected + assert len(variables_names_values) >= 1, "Expected at least one variable issue" + assert any("VSORRESU" in str(val) for val in variables_names_values), \ + "Expected VSORRESU to be in issue variables" + + # Check Core ID + core_id_column = sheet[issue_sheet_coreid_column] + core_id_column_values = [ + cell.value for cell in core_id_column[1:] if cell.value is not None + ] + assert set(core_id_column_values) == {"CDISC.SDTMIG.CG0011"}, \ + "Expected rule CDISC.SDTMIG.CG0011 to be in issues" + + # Go to the "Rules Report" sheet + rules_values = [ + row for row in workbook[rules_report_sheet].iter_rows(values_only=True) + ][1:] + rules_values = [row for row in rules_values if any(row)] + + # Verify rule execution + assert len(rules_values) > 0, "Expected rule results in Rules Report" + rule_ids = [row[0] for row in rules_values if row] + assert "CDISC.SDTMIG.CG0011" in rule_ids, \ + "Expected CG0011 rule in Rules Report" + + # Verify rule reported an issue + for row in rules_values: + if row and row[0] == "CDISC.SDTMIG.CG0011": + assert "ISSUE REPORTED" in str(row), \ + "Expected CG0011 to report an ISSUE" + break \ No newline at end of file diff --git a/tests/resources/CoreIssue1443/Dataset.json b/tests/resources/CoreIssue1443/Dataset.json new file mode 100644 index 000000000..5fe3828cd --- /dev/null +++ b/tests/resources/CoreIssue1443/Dataset.json @@ -0,0 +1,59 @@ +{ + "datasets": [ + { + "filename": "vs.xpt", + "label": "Vital Signs", + "domain": "VS", + "variables": [ + { + "name": "STUDYID", + "label": "Study Identifier", + "type": "char", + "length": 12 + }, + { + "name": "DOMAIN", + "label": "Domain Abbreviation", + "type": "char", + "length": 2 + }, + { + "name": "USUBJID", + "label": "Unique Subject Identifier", + "type": "char", + "length": 8 + }, + { + "name": "VSSEQ", + "label": "Sequence Number", + "type": "num", + "length": 8 + }, + { + "name": "VSTESTCD", + "label": "Vital Sign Test Code", + "type": "char", + "length": 8 + }, + { + "name": "VSTEST", + "label": "Vital Sign Test Name", + "type": "char", + "length": 40 + }, + { + "name": "VSORRESU", + "label": "Original Result Units", + "type": "char", + "length": 20 + }, + { + "name": "VSSTRESC", + "label": "Character Result/Finding in Std Format", + "type": "char", + "length": 8 + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/resources/CoreIssue1443/Rule.yml b/tests/resources/CoreIssue1443/Rule.yml new file mode 100644 index 000000000..eaf3d07e4 --- /dev/null +++ b/tests/resources/CoreIssue1443/Rule.yml @@ -0,0 +1,57 @@ +Authorities: + - Organization: CDISC + Standards: + - Name: SDTMIG + References: + - Citations: + - Cited Guidance: xxx. + Document: IG v3.4 + Item: Item 3.b. + Section: '2.6' + Origin: SDTM and SDTMIG Conformance Rules + Rule Identifier: + Id: CG0011 + Version: '1' + Version: '2.0' + Version: '3.4' +Check: + any: + - all: + # Case 1: Variable lacks variable-level codelist + - name: define_variable_ccode + operator: empty + # BUT has VLM items with codelists that match library + - name: define_vlm_has_codelist_any + operator: equal_to + value: true + - name: define_vlm_ccode_matches_library_any + operator: equal_to + value: true +Core: + Id: CDISC.SDTMIG.CG0011 + Status: Draft + Version: '1' +Description: Variable has no variable-level codelist but has Value Level Metadata (VLM) with codelists that match the library standard. This indicates potential metadata inconsistency where codelist is defined at VLM level rather than variable level. +Executability: Fully Executable +Outcome: + Message: + Variable {{variable_name}} lacks variable-level CodeList but has VLM items + with CodeList matching library standard {{library_variable_ccode}}. + Consider defining codelist at variable level. + Output Variables: + - variable_name + - define_variable_ccode + - library_variable_ccode + - define_vlm_ccodes + - define_vlm_ccode_matches_library_any + +Rule Type: Variable Metadata Check against Define XML and Library Metadata +Scope: + Domains: + Include: + - VS + Classes: + Include: + - STUDY REFERENCE +Sensitivity: Record + \ No newline at end of file From 3ae700105dffcf4a2a64835c7209b660dd6d4e1d Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Mon, 20 Jul 2026 11:03:44 -0400 Subject: [PATCH 03/13] Added regression test for the case where VSORRESU is flagged and has no variable level codelist and test where VSORRESU is not flagged when it has a variable level codelist --- ...with_define_and_library_dataset_builder.py | 2 +- .../test_Issues/test_CoreIssue1443.py | 82 +- tests/resources/CoreIssue1443/Dataset.json | 83 +- tests/resources/CoreIssue1443/Define.xml | 11893 ++++++++++++++++ .../CoreIssue1443/Define_with_codelist.xml | 11893 ++++++++++++++++ tests/resources/CoreIssue1443/Rule.yml | 141 +- .../unit-test-coreid-SENDIG_49.xlsx | Bin 0 -> 13788 bytes 7 files changed, 23995 insertions(+), 99 deletions(-) create mode 100644 tests/resources/CoreIssue1443/Define.xml create mode 100644 tests/resources/CoreIssue1443/Define_with_codelist.xml create mode 100644 tests/resources/CoreIssue1443/unit-test-coreid-SENDIG_49.xlsx diff --git a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py index 1493386b5..1fa770ea7 100644 --- a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py +++ b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py @@ -158,7 +158,7 @@ def build(self): how="left", on="variable_name", ) - final_dataframe.drop(columns=["define_variable_name_y"], errors="ignore", inplace=True) + final_dataframe = final_dataframe.drop(columns=["define_variable_name_y"], errors="ignore") final_dataframe["define_vlm_present"] = ( final_dataframe["define_vlm_present"].fillna(False) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py index 55f20a427..0046b95a5 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py @@ -15,7 +15,7 @@ @pytest.mark.regression def test_vlm_fallback_codelist_check(): """ - Test for GitHub Issue #1443: Rule blocked: SEND49 + Test for GitHub Issue #1443: Rule blocked: CDISC.SENDIG.49 Validates that rules can use VLM (Value Level Metadata) columns as fallback when variable-level codelist is not available. @@ -30,9 +30,9 @@ def test_vlm_fallback_codelist_check(): "core", "validate", "-s", - "sdtmig", + "sendig", "-v", - "3-4", + "3-1", "-dp", os.path.join( "tests", @@ -62,12 +62,19 @@ def test_vlm_fallback_codelist_check(): # Go to the "Issue Details" sheet sheet = workbook[issue_datails_sheet] - # Check Variable(s) column (H) - variables_names_column = sheet["H"] + # Check Variable(s) column + variables_names_column = sheet[issue_sheet_variable_column] variables_names_values = [ cell.value for cell in variables_names_column[1:] if cell.value is not None ] + # DEBUG: print all issue details rows + print("\n=== Issue Details (first 10 rows) ===") + for row in sheet.iter_rows(min_row=1, max_row=11, values_only=True): + if any(row): + print(row) + print(f"\nColumn I values: {variables_names_values}") + # Verify that VSORRESU issue is detected assert len(variables_names_values) >= 1, "Expected at least one variable issue" assert any("VSORRESU" in str(val) for val in variables_names_values), \ @@ -78,8 +85,8 @@ def test_vlm_fallback_codelist_check(): core_id_column_values = [ cell.value for cell in core_id_column[1:] if cell.value is not None ] - assert set(core_id_column_values) == {"CDISC.SDTMIG.CG0011"}, \ - "Expected rule CDISC.SDTMIG.CG0011 to be in issues" + assert any("SEND49" in str(val) or "CDISC.SENDIG.49" in str(val) for val in core_id_column_values), \ + f"Expected SEND49 rule to report issues. Found: {core_id_column_values}" # Go to the "Rules Report" sheet rules_values = [ @@ -90,12 +97,63 @@ def test_vlm_fallback_codelist_check(): # Verify rule execution assert len(rules_values) > 0, "Expected rule results in Rules Report" rule_ids = [row[0] for row in rules_values if row] - assert "CDISC.SDTMIG.CG0011" in rule_ids, \ - "Expected CG0011 rule in Rules Report" + assert any("SEND49" in str(rid) or "CDISC.SENDIG.49" in str(rid) for rid in rule_ids), \ + f"Expected SEND49 rule in Rules Report. Found: {rule_ids}" # Verify rule reported an issue for row in rules_values: - if row and row[0] == "CDISC.SDTMIG.CG0011": + if row and ("SEND49" in str(row[0]) or "CDISC.SENDIG.49" in str(row[0])): assert "ISSUE REPORTED" in str(row), \ - "Expected CG0011 to report an ISSUE" - break \ No newline at end of file + "Expected SEND49 to report an ISSUE" + break + +@pytest.mark.regression +def test_vlm_with_variable_level_codelist(): + """ + Test for GitHub Issue #1443 - Passing scenario + Validates that rule does NOT flag VSORRESU when it HAS a variable-level codelist. + """ + command = [ + f"{get_python_executable()}", + "-m", + "core", + "validate", + "-s", + "sendig", + "-v", + "3-1", + "-dp", + os.path.join( + "tests", + "resources", + "CoreIssue1443", + "Dataset.json", + ), + "-lr", + os.path.join("tests", "resources", "CoreIssue1443", "Rule.yml"), + "-dxp", + os.path.join("tests", "resources", "CoreIssue1443", "Define_with_codelist.xml"), + ] + subprocess.run(command, check=True) + + # Get the latest created Excel file + files = os.listdir() + excel_files = [ + file + for file in files + if file.startswith("CORE-Report-") and file.endswith(".xlsx") + ] + excel_file_path = sorted(excel_files)[-1] + + workbook = openpyxl.load_workbook(excel_file_path) + sheet = workbook[issue_datails_sheet] + + # Check Variable(s) column + variables_names_column = sheet[issue_sheet_variable_column] + variables_names_values = [ + cell.value for cell in variables_names_column[1:] if cell.value is not None + ] + + # Verify that VSORRESU is NOT flagged when variable-level codelist is present + assert not any("VSORRESU" in str(val) for val in variables_names_values), \ + "Expected VSORRESU NOT to be flagged when variable-level codelist is present" \ No newline at end of file diff --git a/tests/resources/CoreIssue1443/Dataset.json b/tests/resources/CoreIssue1443/Dataset.json index 5fe3828cd..68fc9c7ba 100644 --- a/tests/resources/CoreIssue1443/Dataset.json +++ b/tests/resources/CoreIssue1443/Dataset.json @@ -1,59 +1,30 @@ { - "datasets": [ - { - "filename": "vs.xpt", - "label": "Vital Signs", - "domain": "VS", - "variables": [ - { - "name": "STUDYID", - "label": "Study Identifier", - "type": "char", - "length": 12 - }, - { - "name": "DOMAIN", - "label": "Domain Abbreviation", - "type": "char", - "length": 2 - }, - { - "name": "USUBJID", - "label": "Unique Subject Identifier", - "type": "char", - "length": 8 - }, - { - "name": "VSSEQ", - "label": "Sequence Number", - "type": "num", - "length": 8 - }, - { - "name": "VSTESTCD", - "label": "Vital Sign Test Code", - "type": "char", - "length": 8 - }, - { - "name": "VSTEST", - "label": "Vital Sign Test Name", - "type": "char", - "length": 40 - }, - { - "name": "VSORRESU", - "label": "Original Result Units", - "type": "char", - "length": 20 - }, - { - "name": "VSSTRESC", - "label": "Character Result/Finding in Std Format", - "type": "char", - "length": 8 - } - ] - } + "datasetJSONCreationDateTime": "2026-07-17T00:00:00", + "datasetJSONVersion": "1.1.0", + "studyOID": "STUDY001", + "metaDataVersionOID": "MDV.STUDY001", + "itemGroupOID": "IG.VS", + "records": 8, + "name": "VS", + "label": "Vital Signs", + "columns": [ + {"itemOID": "IT.VS.STUDYID", "name": "STUDYID", "label": "Study Identifier", "dataType": "string", "length": 12}, + {"itemOID": "IT.VS.DOMAIN", "name": "DOMAIN", "label": "Domain Abbreviation", "dataType": "string", "length": 2}, + {"itemOID": "IT.VS.USUBJID", "name": "USUBJID", "label": "Unique Subject Identifier", "dataType": "string", "length": 8}, + {"itemOID": "IT.VS.VSSEQ", "name": "VSSEQ", "label": "Sequence Number", "dataType": "integer", "length": 8}, + {"itemOID": "IT.VS.VSTESTCD", "name": "VSTESTCD", "label": "Vital Sign Test Code", "dataType": "string", "length": 8}, + {"itemOID": "IT.VS.VSTEST", "name": "VSTEST", "label": "Vital Sign Test Name", "dataType": "string", "length": 40}, + {"itemOID": "IT.VS.VSORRESU", "name": "VSORRESU", "label": "Original Result Units", "dataType": "string", "length": 20}, + {"itemOID": "IT.VS.VSSTRESC", "name": "VSSTRESC", "label": "Character Result/Finding in Std Format", "dataType": "string", "length": 8} + ], + "rows": [ + ["STUDY001", "VS", "001", 1, "SYSBP", "Systolic Blood Pressure", "mmHg", "120"], + ["STUDY001", "VS", "001", 2, "DIABP", "Diastolic Blood Pressure", "mmHg", "80"], + ["STUDY001", "VS", "001", 3, "HEIGHT", "Height", "cm", "175"], + ["STUDY001", "VS", "001", 4, "WEIGHT", "Weight", "kg", "75"], + ["STUDY001", "VS", "001", 5, "PULSE", "Pulse Rate", "beats/min", "72"], + ["STUDY001", "VS", "001", 6, "TEMP", "Temperature", "C", "37"], + ["STUDY001", "VS", "002", 1, "SYSBP", "Systolic Blood Pressure", "mmHg", "118"], + ["STUDY001", "VS", "002", 2, "HEIGHT", "Height", "cm", "182"] ] } \ No newline at end of file diff --git a/tests/resources/CoreIssue1443/Define.xml b/tests/resources/CoreIssue1443/Define.xml new file mode 100644 index 000000000..911fdfb66 --- /dev/null +++ b/tests/resources/CoreIssue1443/Define.xml @@ -0,0 +1,11893 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDISCPILOT01 + Study Data Tabulation Model Metadata Submission Guidelines Sample Study + CDISCPILOT01 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INJECTION SITE REACTION + + + + + INJECTION SITE REACTION + + + + + AVL0201 + AVL0202 + AVL0203 + AVL0204 + AVL0205 + AVL0206 + AVL0207 + AVL0208 + AVL0209 + AVL0210 + AVL0211 + AVL0212 + AVL0213 + AVL0214 + AVL0215 + + + + + AVL0216 + AVL0217 + + + + + AVL0218 + AVL0219 + AVL0220 + AVL0221 + AVL0222 + AVL0223 + AVL0224 + AVL0225 + AVL0226 + AVL0227 + AVL0228 + AVL0229 + AVL0230 + AVL0231 + AVL0232 + + + + + AVL0233 + AVL0234 + + + + + DIABP + SYSBP + + + + + + + + + + + + + + + + + + + + + + + + + ECREASOC + + + + + OCCUR + + + + + SEV + + + + + HAMD101 + + + + + HAMD101 + + + + + HAMD102 + + + + + HAMD102 + + + + + HAMD103 + + + + + HAMD103 + + + + + HAMD104 + + + + + HAMD104 + + + + + HAMD105 + + + + + HAMD105 + + + + + HAMD106 + + + + + HAMD106 + + + + + HAMD107 + + + + + HAMD107 + + + + + HAMD108 + + + + + HAMD108 + + + + + HAMD109 + + + + + HAMD109 + + + + + HAMD110 + + + + + HAMD110 + + + + + HAMD111 + + + + + HAMD111 + + + + + HAMD112 + + + + + HAMD112 + + + + + HAMD113 + + + + + HAMD113 + + + + + HAMD114 + + + + + HAMD114 + + + + + HAMD115 + + + + + HAMD115 + + + + + HAMD116A + + + + + HAMD116A + + + + + HAMD116B + + + + + HAMD116B + + + + + HAMD117 + + + + + HAMD117 + + + + + HAMD118 + + + + + HAMD118 + + + + + HEIGHT + + + + + HEIGHT + + + + + ALB + + + + + ALP + + + + + ALT + + + + + AST + + + + + BASO + + + + + BILI + + + + + CA + + + + + CHOL + + + + + CK + + + + + CL + + + + + CREAT + + + + + EOS + + + + + GGT + + + + + GLUC + + + + + HCT + + + + + HGB + + + + + K + + + + + LYM + + + + + MCH + + + + + MCHC + + + + + MCV + + + + + MONO + + + + + PHOS + + + + + PLAT + + + + + PROT + + + + + RBC + + + + + SODIUM + + + + + TSH + + + + + URATE + + + + + UREAN + + + + + VITB12 + + + + + WBC + + + + + COLOR + + + + + GLUC + + + + + ALB + BILI + CA + CREAT + K + PHOS + PROT + URATE + + + + + HCT + HGB + + + + + BASO + EOS + LYM + MONO + RBC + TSH + WBC + + + + + ANISO + KETONES + MACROCY + PH + POIKILO + UROBIL + + + + + ALT + AST + GGT + MCH + MCHC + MCV + UREAN + + + + + ALP + CHOL + CK + CL + PLAT + SODIUM + VITB12 + + + + + SPGRAV + + + + + BILI + + + + + CK + + + + + COLOR + + + + + CREAT + + + + + GLUC + + + + + HGB + + + + + K + + + + + MCHC + + + + + RBC + + + + + BASO + EOS + LYM + MONO + RBC + TSH + WBC + + + + + SPGRAV + UREAN + + + + + CA + CHOL + MCH + PHOS + + + + + ANISO + KETONES + MACROCY + PH + POIKILO + UROBIL + + + + + ALB + ALT + AST + GGT + PROT + + + + + ALP + CL + MCV + PLAT + SODIUM + + + + + URATE + + + + + VITB12 + + + + + ALB + + + + + ALP + + + + + ALT + + + + + AST + + + + + BASO + + + + + BILI + + + + + CA + + + + + CHOL + + + + + CK + + + + + CL + + + + + CREAT + + + + + EOS + + + + + GGT + + + + + GLUC + + + + + HGB + + + + + K + + + + + LYM + + + + + MCHC + + + + + MCH + + + + + MCV + + + + + MONO + + + + + PHOS + + + + + PLAT + + + + + PROT + + + + + RBC + + + + + SODIUM + + + + + TSH + + + + + URATE + + + + + UREAN + + + + + VITB12 + + + + + WBC + + + + + NVCLSIG + + + + + OECLSIG + + + + + INTP + + + + + ABDETAIL + + + + + PHQ0101 + PHQ0102 + PHQ0103 + PHQ0104 + PHQ0105 + PHQ0106 + PHQ0107 + PHQ0108 + PHQ0109 + + + + + PHQ0101 + PHQ0102 + PHQ0103 + PHQ0104 + PHQ0105 + PHQ0106 + PHQ0107 + PHQ0108 + PHQ0109 + + + + + PHQ0110 + + + + + PHQ0110 + + + + + PHQ0111 + + + + + PHQ0111 + + + + + PULSE + + + + + PULSE + + + + + MULTIPLE + + + + + RACE1 + + + + + RACE2 + + + + + RACE3 + + + + + RACE4 + + + + + RACE5 + + + + + MULTIPLE + + + + + TEMP + + + + + TEMP + + + + + TBLIND + + + + + TCNTRL + + + + + FCNTRY + + + + + DCUTDTC + SENDTC + SSTDTC + + + + + TS_DURATION + + + + + TS_FLOAT + + + + + DOSFRQ + + + + + DOSFRM + + + + + INDIC + + + + + ACTSUB + AGEMAX + AGEMIN + DOSE + NARMS + PLANSUB + + + + + INTTYPE + + + + + INTMODEL + + + + + OBJPRIM + + + + + OBJSEC + + + + + OUTMSPRI + + + + + PCLAS + + + + + TPHASE + + + + + REGID + + + + + ROUTE + + + + + SDTIGVER + SDTMVER + + + + + SEXPOP + + + + + SPONSOR + + + + + STOPRULE + + + + + STYPE + + + + + TDIGRP + + + + + TINDTP + + + + + TITLE + + + + + TRT + + + + + TTYPE + + + + + DOSU + + + + + ADAPT + ADDON + HLTSUBJI + RANDOM + + + + + WEIGHT + + + + + WEIGHT + + + + + + + + + + + + Trial Arms + + + + + + + + + + + + + + ta.xpt + + + + + + Trial Elements + + + + + + + + + + te.xpt + + + + + + Trial Inclusion/Exclusion Criteria + + + + + + + + + + ti.xpt + + + + + + Trial Summary + + + + + + + + + + + + + + + ts.xpt + + + + + + Trial Visits + + + + + + + + + + + tv.xpt + + + + + + Demographics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dm.xpt + + + + + + Subject Elements + + + + + + + + + + + + + + + se.xpt + + + + + + Subject Visits + + + + + + + + + + + + + + sv.xpt + + + + + + Concomitant Medications + + + + + + + + + + + + + + + + + + + + + cm.xpt + + + + + + Exposure as Collected + + + + + + + + + + + + + + + + + + + + + + + + + ec.xpt + + + + + + Exposure + + + + + + + + + + + + + + + + + + + + + ex.xpt + + + + + + Adverse Events + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ae.xpt + + + + + + Disposition + + + + + + + + + + + + + + + + ds.xpt + + + + + + Medical History + + + + + + + + + + + + mh.xpt + + + + + + Death Details + + + + + + + + + + + + + + + + dd.xpt + + + + + + Functional Tests + + + + + + + + + + + + + + + + + + + + + + + + + + ft.xpt + + + + + + Inclusion/Exclusion Criteria Not Met + + + + + + + + + + + + + + + + ie.xpt + + + + + + Laboratory Test Results + + + + + + + + + + + + + + + + + + + + + + + + + + + lb.xpt + + + + + + Nervous System Findings + + + + + + + + + + + + + + + + + + + Ophthalmic Examinations + + + + + + + + + + + + + + + + + + + + + + oe.xpt + + + + + + Questionnaires (PHQ-9) + + + + + + + + + + + + + + + + + + + + + + qsph.xpt + + + + + + Questionnaires (SQLS) + + + + + + + + + + + + + + + + + + + + + qssl.xpt + + + + + + Disease Response and Clin Classification + + + + + + + + + + + + + + + + + + + + + rs.xpt + + + + + + Vital Signs + + + + + + + + + + + + + + + + + + + + + + + + + vs.xpt + + + + + + Findings About Events or Interventions + + + + + + + + + + + + + + + + + + + + fa.xpt + + + + + + Related Records + + + + + + + + + + + relrec.xpt + + + + + + Supplemental Qualifiers for DM + + + + + + + + + + + + + + + suppdm.xpt + + + + + + Supplemental Qualifiers for EC + + + + + + + + + + + + + + + suppec.xpt + + + + + + Supplemental Qualifiers for NV + + + + + + + + + + + + + + + + + + Supplemental Qualifiers for OE + + + + + + + + + + + + + + + + + + Device Identifiers + + + + + + + + + + + di.xpt + + + + + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link ID + + + + + + + + + + Reported Term for the Adverse Event + + + + + + Lowest Level Term + + + + + + + Lowest Level Term Code + + + + + + + Dictionary-Derived Term + + + + + + + Preferred Term Code + + + + + + + High Level Term + + + + + + + High Level Term Code + + + + + + + High Level Group Term + + + + + + + High Level Group Term Code + + + + + + + Body System or Organ Class + + + + + + + Body System or Organ Class Code + + + + + + + Primary System Organ Class + + + + + + + Primary System Organ Class Code + + + + + + + Severity/Intensity + + + + + + + + + + + Serious Event + + + + + + + + + + + Action Taken with Study Treatment + + + + + + + + + + + Causality + + + + + + + + + + + Outcome of Adverse Event + + + + + + + + + + + Involves Cancer + + + + + + + + + + + Congenital Anomaly or Birth Defect + + + + + + + + + + + Persist or Signif Disability/Incapacity + + + + + + + + + + + Results in Death + + + + + + + + + + + Requires or Prolongs Hospitalization + + + + + + + + + + + Is Life Threatening + + + + + + + + + + + Occurred with Overdose + + + + + + + + + + + Epoch + + + + + + + Start Date/Time of Adverse Event + + + + + + + + + + End Date/Time of Adverse Event + + + + + + + + + + Study Day of Start of Adverse Event + + + + + + + Study Day of Start of Adverse Event + + + + + + Study Day of End of Adverse Event + + + + + + End Relative to Reference Time Point + + + + + + + + + + + End Reference Time Point + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Reported Name of Drug, Med, or Therapy + + + + + + + + + + Indication + + + + + + + + + + Dose per Administration + + + + + + + + + + Dose Units + + + + + + + + + + + Dosing Frequency per Interval + + + + + + + + + + + Route of Administration + + + + + + + + + + + Epoch + + + + + + + Start Date/Time of Medication + + + + + + + + + + End Date/Time of Medication + + + + + + + + + + Study Day of Start of Medication + + + + + + Study Day of End of Medication + + + + + + End Relative to Reference Time Point + + + + + + + + + + + End Reference Time Point + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Sponsor Device Identifier + + + + + + Sequence Number + + + + + + Device Identifier Element Short Name + + + + + + + Device Identifier Element Name + + + + + + + Device Identifier Element Value + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Subject Identifier for the Study + + + + + + Subject Reference Start Date/Time + + + + + + Subject Reference End Date/Time + + + + + + Date/Time of First Study Treatment + + + + + + Date/Time of Last Study Treatment + + + + + + Date/Time of Informed Consent + + + + + + + + + + Date/Time of End of Participation + + + + + + Date/Time of Death + + + + + + + + + + Subject Death Flag + + + + + + + Study Site Identifier + + + + + + + Date/Time of Birth + + + + + + + + + + Age + + + + + + + + + + Age Units + + + + + + + Sex + + + + + + + + + + + Race + + + + + + Ethnicity + + + + + + + + + + + Planned Arm Code + + + + + + + Description of Planned Arm + + + + + + + Actual Arm Code + + + + + + + Description of Actual Arm + + + + + + + Reason Arm and/or Actual Arm is Null + + + + + + + Description of Unplanned Actual Arm + + + + + + Country + + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link ID + + + + + + + + + + Reported Term for the Disposition Event + + + + + + Standardized Disposition Term + + + + + + Category for Disposition Event + + + + + + + + + + + Subcategory for Disposition Event + + + + + + + + + + + Epoch + + + + + + + Start Date/Time of Disposition Event + + + + + + + + + + Study Day of Start of Disposition Event + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sponsor Device Identifier + + + + + + Sequence Number + + + + + + Name of Treatment + + + + + + + Pre-Specified + + + + + + + Occurrence + + + + + + + + + + + Dose + + + + + + + + + + Dose Units + + + + + + + + + + + Dose Form + + + + + + + Dosing Frequency per Interval + + + + + + + Route of Administration + + + + + + + Lot Number + + + + + + + + + + Pharmaceutical Strength + + + + + + Pharmaceutical Strength Units + + + + + + + Epoch + + + + + + + Start Date/Time of Treatment + + + + + + + + + + End Date/Time of Treatment + + + + + + + + + + Study Day of Start of Treatment + + + + + + Study Day of End of Treatment + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sponsor Device Identifier + + + + EC.SPDEVID + + + + + + Sequence Number + + + + + + Name of Treatment + + + + + ECTRT + + + + + + Dose + + + + + + Dose Units + + + + + + + Dose Form + + + + + ECDOSFRM + + + + + + Dosing Frequency per Interval + + + + + ECDOSFRQ + + + + + + Route of Administration + + + + + ECROUTE + + + + + + Lot Number + + + + ECLOT + + + + + + Epoch + + + + + EC.EPOCH + + + + + + Start Date/Time of Treatment + + + + ECSTDTC + + + + + + End Date/Time of Treatment + + + + ECENDTC + + + + + + Study Day of Start of Treatment + + + + ECSTDY + + + + + + Study Day of End of Treatment + + + + ECENDY + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link Group ID + + + + + + + + + + Findings About Test Short Name + + + + + + + Findings About Test Name + + + + + + + Object of the Observation + + + + + + + + + + + Category for Findings About + + + + + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + FAORRES + + + + + + + Location of the Finding About + + + + + + + Visit Number + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Short Name of Test + + + + + + + Name of Test + + + + + + + Category + + + + + + + + + + + Subcategory + + + + + + + + + + Result or Finding in Original Units + + + + + + Result or Finding in Standard Format + + + + FTORRES + + + + + + Numeric Result/Finding in Standard Units + + + + + + Last Observation Before Exposure Flag + + + + + + + Repetition Number + + + + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Test + + + + + + + + + + Study Day of Test + + + + + + Planned Time Point Name + + + + + + Planned Time Point Number + + + + + + Planned Elapsed Time from Time Point Ref + + + + + + + + + + Time Point Reference + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Inclusion/Exclusion Criterion Short Name + + + + + + + + + + + Inclusion/Exclusion Criterion + + + + + + + Inclusion/Exclusion Category + + + + + + + + + + + I/E Criterion Original Result + + + + + + + + + + + I/E Criterion Result in Std Format + + + + + IEORRES + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Question Short Name + + + + + + + Question Name + + + + + + + Category of Question + + + + + + + + + + + Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + + Numeric Finding in Standard Units + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Finding + + + + + + Study Day of Finding + + + + + + Evaluation Interval + + + + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Question Short Name + + + + + + + Question Name + + + + + + + Category of Question + + + + + + + + + + + Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + + + + + + + Numeric Finding in Standard Units + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Finding + + + + + + Study Day of Finding + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Relationship Type + + + + + + + Relationship Identifier + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Assessment Short Name + + + + + + + Assessment Name + + + + + + + Category for Assessment + + + + + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + + + Numeric Result/Finding in Standard Units + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Assessment + + + + + + Study Day of Assessment + + + + + + Evaluation Interval + + + + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Element Code + + + + + + + Description of Element + + + + + + + Epoch + + + + + + + Start Date/Time of Element + + + + + + End Date/Time of Element + + + + + + Study Day of Start of Element + + + + + + Study Day of End of Element + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Visit Number + + + + + + Visit Name + + + + + + Start Date/Time of Visit + + + + + + End Date/Time of Visit + + + + + + Study Day of Start of Visit + + + + + + Study Day of End of Visit + + + + + + Description of Unplanned Visit + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Planned Arm Code + + + + + + + Description of Planned Arm + + + + + + + Planned Order of Element within Arm + + + + + + Element Code + + + + + + + Description of Element + + + + + + + Branch + + + + + + Transition Rule + + + + + + Epoch + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Element Code + + + + + + + Description of Element + + + + + + + Rule for Start of Element + + + + + + Rule for End of Element + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Incl/Excl Criterion Short Name + + + + + + + Inclusion/Exclusion Criterion + + + + + + + Inclusion/Exclusion Category + + + + + + + Protocol Criteria Versions + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Sequence Number + + + + + + Group ID + + + + + + Trial Summary Parameter Short Name + + + + + + + Trial Summary Parameter + + + + + + + Parameter Value + + + + + + Parameter Null Flavor + + + + + + + Parameter Value Code + + + + + + Name of the Reference Terminology + + + + + + Version of the Reference Terminology + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Planned Arm Code + + + + + + + Visit Start Rule + + + + + + Visit End Rule + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Vital Signs Test Short Name + + + + + + + Vital Signs Test Name + + + + + + + Vital Signs Position of Subject + + + + + + + + + + + Result or Findings as Collected + + + + + + Unit of the Original Result + + + + + + + + Standardized Result in Character Format + + + + + + Standardized Result in Numeric Format + + + + + + Unit of the Standardized Result + + + + + + + + Completion Status + + + + + + + + + + + Location of Vital Signs Measurement + + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Repetition Number + + + + + + + + + + Visit Number + + + + + + Visit Name + + + + + + + + + + Epoch + + + + + + + Date/Time of Measurement + + + + + + + + + + Study Day of Vital Signs Measurement + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Short Name of Nervous System Test + + + + + + + Name of Nervous System Test + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + NVORRES + + + + + + Visit Number + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Visit/Collection/Exam + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Reported Term for the Medical History + + + + + + + Medical History Event Date Type + + + + + + + + + + + Start Date/Time of Medical History Event + + + + + + + + + + Study Day of Start of Observation + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link ID + + + + + + + + + + Death Detail Assessment Short Name + + + + + + + Death Detail Assessment Name + + + + + + + Result or Finding as Collected + + + + + + + + + + Character Result/Finding in Std Format + + + + DDORRES + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Lab Test or Examination Short Name + + + + + + + Lab Test or Examination Name + + + + + + + Category for Lab Test + + + + + + + Result or Finding in Original Units + + + + + + + Original Units + + + + + + + Reference Range Lower Limit in Orig Unit + + + + + + Reference Range Upper Limit in Orig Unit + + + + + + Character Result/Finding in Std Format + + + + + + + Numeric Result/Finding in Standard Units + + + + + + Standard Units + + + + + + + Reference Range Lower Limit-Std Units + + + + + + Reference Range Upper Limit-Std Units + + + + + + Reference Range Indicator + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Specimen Collection + + + + + + Study Day of Specimen Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Focus of Study-Specific Interest + + + + + + + + + + + Sequence Number + + + + + + Short Name of Ophthalmic Test or Exam + + + + + + + Name of Ophthalmic Test or Exam + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + OEORRES + + + + + + Location Used for the Measurement + + + + + + + + + + + Laterality + + + + + + + + + + + Method of Test or Examination + + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Visit/Collection/Exam + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Reported Term for the Adverse Event + + + + + + + + + + Reported Term for the Adverse Event + + + + + + + + + + Standardized Disposition Term + + + + + + + + + + + Standardized Disposition Term + + + + + + + + + + + Reported Term for the Disposition Event + + + + + + + + + + Reported Term for the Disposition Event + + + + + + + + + + Result or Finding in Original Units + + + + + + Result or Finding in Original Units + + + + + + Character Result/Finding in Std Format + + + + + + Character Result/Finding in Std Format + + + + + + AVLT-REY List A Item 1-15 + + + + + + + + + + + AVLT-REY List A Item 16-17 + + + + + + + + + + AVLT-REY List B Item 18-32 + + + + + + + + + + + AVLT-REY List B Item 33-34 + + + + + + + + + + Lab Result or Finding in Original Units - Set 1 + + + + + Lab Result or Finding in Original Units - Set 2 + + + + + Lab Result or Finding in Original Units - Set 3 + + + + + Lab Result or Finding in Original Units - Specific Gravity + + + + + Lab Result or Finding in Original Units - Set 4 + + + + + Lab Result or Finding in Original Units - Set 5 + + + + + Lab Result or Finding in Original Units - Set 6 + + + + + Lab Result or Finding in Original Units - Color + + + + + Lab Result or Finding in Original Units - Glucose + + + + + Lab Result Units - ALT + + + + + + Lab Result Units - ALB + + + + + + Lab Result Units - ALP + + + + + + Lab Result Units - AST + + + + + + Lab Result Units - BASO + + + + + + Lab Result Units - BILI + + + + + + Lab Result Units - CA + + + + + + Lab Result Units - CL + + + + + + Lab Result Units - CHOL + + + + + + Lab Result Units - CK + + + + + + Lab Result Units - CREAT + + + + + + Lab Result Units - EOS + + + + + + Lab Result Units - MCH + + + + + + Lab Result Units - MCHC + + + + + + Lab Result Units - MCV + + + + + + Lab Result Units - RBC + + + + + + Lab Result Units - GGT + + + + + + Lab Result Units - GLUC + + + + + + Lab Result Units - HCT + + + + + + Lab Result Units - HGB + + + + + + Lab Result Units - WBC + + + + + + Lab Result Units - LYM + + + + + + Lab Result Units - MONO + + + + + + Lab Result Units - PHOS + + + + + + Lab Result Units - PLAT + + + + + + Lab Result Units - K + + + + + + Lab Result Units - PROT + + + + + + Lab Result Units - SODIUM + + + + + + Lab Result Units - TSH + + + + + + Lab Result Units - URATE + + + + + + Lab Result Units - UREAN + + + + + + Lab Result Units - VITB12 + + + + + + Character Result/Finding in Std Format - K + + + + + Character Result/Finding in Std Format - RBC + + + + + Character Result/Finding in Std Format - Set 1 + + + + + Character Result/Finding in Std Format - BILI + + + + + Character Result/Finding in Std Format - Set 2 + + + + + Character Result/Finding in Std Format - CREAT + + + + + Character Result/Finding in Std Format - URATE + + + + + Character Result/Finding in Std Format - MCHC + + + + + Character Result/Finding in Std Format - Set 3 + + + + + Character Result/Finding in Std Format - VITB12 + + + + + Character Result/Finding in Std Format - HGB + + + + + Character Result/Finding in Std Format - Set 4 + + + + + Character Result/Finding in Std Format - Set 5 + + + + + Character Result/Finding in Std Format - Set 6 + + + + + Character Result/Finding in Std Format - CK + + + + + Character Result/Finding in Std Format - COLOR + + + + + + Character Result/Finding in Std Format - GLUC + + + + + Lab Result Standard Units - ALT + + + + + + Lab Result Standard Units - ALB + + + + + + Lab Result Standard Units - ALP + + + + + + Lab Result Standard Units - AST + + + + + + Lab Result Standard Units - BASO + + + + + + Lab Result Standard Units - BILI + + + + + + Lab Result Standard Units - CA + + + + + + Lab Result Standard Units - CL + + + + + + Lab Result Standard Units - CHOL + + + + + + Lab Result Standard Units - CK + + + + + + Lab Result Standard Units - CREAT + + + + + + Lab Result Standard Units - EOS + + + + + + Lab Result Standard Units - MCH + + + + + + Lab Result Standard Units - MCHC + + + + + + Lab Result Standard Units - MCV + + + + + + Lab Result Standard Units - RBC + + + + + + Lab Result Standard Units - GGT + + + + + + Lab Result Standard Units - GLUC + + + + + + Lab Result Standard Units - HGB + + + + + + Lab Result Standard Units - WBC + + + + + + Lab Result Standard Units - LYM + + + + + + Lab Result Standard Units - MONO + + + + + + Lab Result Standard Units - PHOS + + + + + + Lab Result Standard Units - PLAT + + + + + + Lab Result Standard Units - K + + + + + + Lab Result Standard Units - PROT + + + + + + Lab Result Standard Units - SODIUM + + + + + + Lab Result Standard Units - TSH + + + + + + Lab Result Standard Units - URATE + + + + + + Lab Result Standard Units - UREAN + + + + + + Lab Result Standard Units - VITB12 + + + + + + Result or Finding in Original Units + + + + + + Result or Finding in Original Units + + + + + PHQ-9 Questions 1-9 + + + + + + PHQ-9 Question 10 + + + + + + PHQ-9 Question Total + + + + + PHQ-9 Questions 1-9, Standardized + + + + + + + + + + + PHQ-9 Question 10, Standardized + + + + + + + + + + + PHQ-9 Question Total, Standardized + + + + QSORRES where QSTESTCD EQ PHQ0111 + + + + + + + + + Race + + + + + + + + + + + Race + + + + + + + + + + + HAMD-17 Question 1 + + + + + + + + + + + HAMD-17 Question 2 + + + + + + + + + + + HAMD-17 Question 3 + + + + + + + + + + + HAMD-17 Question 4 + + + + + + + + + + + HAMD-17 Question 5 + + + + + + + + + + + HAMD-17 Question 6 + + + + + + + + + + + HAMD-17 Question 7 + + + + + + + + + + + HAMD-17 Question 8 + + + + + + + + + + + HAMD-17 Question 9 + + + + + + + + + + + HAMD-17 Question 10 + + + + + + + + + + + HAMD-17 Question 11 + + + + + + + + + + + HAMD-17 Question 12 + + + + + + + + + + + HAMD-17 Question 13 + + + + + + + + + + + HAMD-17 Question 14 + + + + + + + + + + + HAMD-17 Question 15 + + + + + + + + + + + HAMD-17 Question 16A + + + + + + + + + + + HAMD-17 Question 16B + + + + + + + + + + + HAMD-17 Question 17 + + + + + + + + + + + HAMD-17 Question 18 + + + + + + + + + + HAMD-17 Question 1 Standardized + + + + + + + + + + + HAMD-17 Question 2 Standardized + + + + + + + + + + + HAMD-17 Question 3 Standardized + + + + + + + + + + + HAMD-17 Question 4 Standardized + + + + + + + + + + + HAMD-17 Question 5 Standardized + + + + + + + + + + + HAMD-17 Question 6 Standardized + + + + + + + + + + + HAMD-17 Question 7 Standardized + + + + + + + + + + + HAMD-17 Question 8 Standardized + + + + + + + + + + + HAMD-17 Question 9 Standardized + + + + + + + + + + + HAMD-17 Question 10 Standardized + + + + + + + + + + + HAMD-17 Question 11 Standardized + + + + + + + + + + + HAMD-17 Question 12 Standardized + + + + + + + + + + + HAMD-17 Question 13 Standardized + + + + + + + + + + + HAMD-17 Question 14 Standardized + + + + + + + + + + + HAMD-17 Question 15 Standardized + + + + + + + + + + + HAMD-17 Question 16A Standardized + + + + + + + + + + + HAMD-17 Question 16B Standardized + + + + + + + + + + + HAMD-17 Question 17 Standardized + + + + + + + + + + + HAMD-17 Question 18 Standardized + + + + + + + + + + Race 1 + + + + + + + + + + + Race 2 + + + + + + + + + + + Race 3 + + + + + + + + + + + Race 4 + + + + + + + + + + + Race 5 + + + + + + + + + + + Reason for Occur Value + + + + + + + + + + Clinically Significant + + + + + + + + + + + Clinically Significant + + + + + + + + + + + Trial Summary Yes No Responses + + + + + + + Planned Maximum Age of Subjects + + + + + + Trial Summary Date Responses + + + + + + Dose Form + + + + + + + Dosing Frequency + + + + + + + Dose Units + + + + + + + Planned Country of Investigational Sites + + + + + + + Trial Disease/Condition Indication + + + + + + + Intervention Model + + + + + + + Intervention Type + + + + + + + Trial Length + + + + + + Trial Primary Objective + + + + + + Trial Secondary Objective + + + + + + Primary Outcome Measure + + + + + + Pharmacologic Class + + + + + + Randomization Quotient + + + + + + Registry Identifier + + + + + + Route of Administration + + + + + + + SDTM IG Version + + + + + + Sex of Participants + + + + + + + Clinical Study Sponsor + + + + + + Study Stop Rules + + + + + + Study Type + + + + + + + Trial Blinding Schema + + + + + + + Control Type + + + + + + + Diagnosis Group + + + + + + + Trial Intent Type + + + + + + + Trial Title + + + + + + Trial Phase Classification + + + + + + + Investigational Therapy or Treatment + + + + + + Trial Type + + + + + + + Blood Pressure + + + + + + + + + + Height + + + + + + + + + + Pulse Rate + + + + + + + + + + Temperature + + + + + + + + + + Weight + + + + + + + + + + Blood Pressure Units + + + + + + + + + + + Height Units + + + + + + + + + + + Pulse Rate Units + + + + + + + + + + + Temperature Units + + + + + + + + + + + Weight Units + + + + + + + + + + + Blood Pressure Units Std + + + + + + Height Units Std + + + + + + Pulse Rate Units Std + + + + + + Temperature Units Std + + + + + + Weight Units Std + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dose Increased + + + + + + Dose Not Changed + + + + + + Dose Reduced + + + + + + Drug Interrupted + + + + + + Drug Withdrawn + + + + + + Not Applicable + + + + + + Unknown + + + + + + + + + Related + + + + + Unlikely Related + + + + + Possibly Related + + + + + Not Related + + + + + + + Mild + + + + + + Moderate + + + + + + Severe + + + + + + + + + Years + + + + + + + + + + + + + + Placebo + + + + + Zanomaline Low Dose (54 mg) + + + + + Zanomaline High Dose (81 mg) + + + + + + + Trial Screen Failure + + + + + + + + + AVLT-REY - List A Word 1 + + + + + + AVLT-REY - List A Word 2 + + + + + + AVLT-REY - List A Word 3 + + + + + + AVLT-REY - List A Word 4 + + + + + + AVLT-REY - List A Word 5 + + + + + + AVLT-REY - List A Word 6 + + + + + + AVLT-REY - List A Word 7 + + + + + + AVLT-REY - List A Word 8 + + + + + + AVLT-REY - List A Word 9 + + + + + + AVLT-REY - List A Word 10 + + + + + + AVLT-REY - List A Word 11 + + + + + + AVLT-REY - List A Word 12 + + + + + + AVLT-REY - List A Word 13 + + + + + + AVLT-REY - List A Word 14 + + + + + + AVLT-REY - List A Word 15 + + + + + + AVLT-REY - List A Total + + + + + + AVLT-REY - List A Intrusions + + + + + + AVLT-REY - List B Word 1 + + + + + + AVLT-REY - List B Word 2 + + + + + + AVLT-REY - List B Word 3 + + + + + + AVLT-REY - List B Word 4 + + + + + + AVLT-REY - List B Word 5 + + + + + + AVLT-REY - List B Word 6 + + + + + + AVLT-REY - List B Word 7 + + + + + + AVLT-REY - List B Word 8 + + + + + + AVLT-REY - List B Word 9 + + + + + + AVLT-REY - List B Word 10 + + + + + + AVLT-REY - List B Word 11 + + + + + + AVLT-REY - List B Word 12 + + + + + + AVLT-REY - List B Word 13 + + + + + + AVLT-REY - List B Word 14 + + + + + + AVLT-REY - List B Word 15 + + + + + + AVLT-REY - List B Total + + + + + + AVLT-REY - List B Intrusions + + + + + + + + + Recalled + + + + + Not Recalled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Primary Cause of Death + + + + + + + + + + + + + + + + + + Device Type + + + + + + Serial Number + + + + + + + + + Adverse Events + + + + + + + + + Concomitant/Prior Medications + + + + + + + + + Death Details + + + + + + + + + Device Identifiers + + + + + + + + + Demographics + + + + + + + + + Disposition + + + + + + + + + Exposure as Collected + + + + + + + + + Exposure + + + + + + + + + Findings About Events or Interventions + + + + + + + + + Functional Tests + + + + + + + + + Inclusion/Exclusion Criteria Not Met + + + + + + + + + Laboratory Test Results + + + + + + + + + Medical History + + + + + + + + + Nervous Sysytem Findings + + + + + + + + + Ophthalmic Examinations + + + + + + + + + Questionnaires + + + + + + + + + Disease Response and Clin Classification + + + + + + + + + Subject Elements + + + + + + + + + Subject Visits + + + + + + + + + Trial Arms + + + + + + + + + Trial Elements + + + + + + + + + Trial Inclusion + + + + + + + + + Trial Summary + + + + + + + + + Trial Visits + + + + + + + + + Vital Signs + + + + + + + + + Disposition Event + + + + + + Protocol Milestone + + + + + + + + + Study Treatment + + + + + Study Participation + + + + + + + + + + + + + + Ongoing + + + + + + + + + Screening + + + + + + Treatment + + + + + + + + + Zanomaline 81 mg + + + + + Zanomaline 54 mg + + + + + Placebo + + + + + Screening + + + + + Zanomaline 54 mg Titration + + + + + + + Hispanic or Latino + + + + + + Not Hispanic or Latino + + + + + + + + + Placebo + + + + + Zanomaline + + + + + + + Injection Site Reaction + + + + + + + Erythema + + + + + Pain + + + + + Induration + + + + + Pruritus + + + + + Edema + + + + + + + No + + + + + + Yes + + + + + + + + + Mild + + + + + + Moderate + + + + + + Severe + + + + + + + + + + + + + Occurrence Indicator + + + + + Severity/Intensity + + + + + + + Daily + + + + + + As Needed + + + + + + Twice Daily + + + + + + Every Four Hours + + + + + + Four Times Daily + + + + + + Every Six Hours + + + + + + + + + Daily + + + + + + + + + Injectable Dosage Form + + + + + + + + + Rey Auditory Verbal Learning Functional Test + + + + + + + + + + + + + + + + Absent. + + + + + These feeling states indicated only on questioning. + + + + + These feeling states spontaneously reported verbally. + + + + + Communicates feeling states non-verbally, i.e. through facial expression, posture, voice and tendency to weep. + + + + + Patient reports virtually only these feeling states in his/her spontaneous verbal and non-verbal communication. + + + + + + + + + + + + + + Absent. + + + + + Self reproach, feels he/she has let people down. + + + + + Ideas of guilt or rumination over past errors or sinful deeds. + + + + + Present illness is a punishment. Delusions of guilt. + + + + + Hears accusatory or denunciatory voices and/or experiences threatening visual hallucinations. + + + + + + + + + + + + + + Absent. + + + + + Feels life is not worth living. + + + + + Wishes he/she were dead or any thoughts of possible death to self. + + + + + Ideas or gestures of suicide. + + + + + Attempts at suicide (any serious attempt rate 4). + + + + + + + + + + + + No difficulty falling asleep. + + + + + Complains of occasional difficulty falling asleep, i.e. more than 1/2 hour + + + + + Complains of nightly difficulty falling asleep. + + + + + + + + + + + + No difficulty. + + + + + Patient complains of being restless and disturbed during the night. + + + + + Waking during the night - any getting out of bed rates 2 (except for purposes of voiding). + + + + + + + + + + + + No difficulty. + + + + + Waking in early hours of the morning but goes back to sleep. + + + + + Unable to fall asleep again if he/she gets out of bed. + + + + + + + + + + + + + + No difficulty. + + + + + Thoughts and feelings of incapacity, fatigue or weakness related to activities, work or hobbies. + + + + + Loss of interest in activity, hobbies or work - either directly reported by the patient or indirect in listlessness, indecision and vacillation (feels he/she has to push self to work or activities). + + + + + Decrease in actual time spent in activities or decrease in productivity. Rate 3 if the patient does not spend at least three hours a day in activities (job or hobbies) excluding routine chores. + + + + + Stopped working because of present illness. Rate 4 if patient engages in no activities except routine chores, or if patient fails to perform routine chores unassisted. + + + + + + + + + + + + + + Normal speech and thought. + + + + + Slight retardation during the interview. + + + + + Obvious retardation during the interview. + + + + + Interview difficult. + + + + + Complete stupor. + + + + + + + + + + + + + + None. + + + + + Fidgetiness. + + + + + Playing with hands, hair, etc. + + + + + Moving about, cannot sit still. + + + + + Hand wringing, nail biting, hair-pulling, biting of lips. + + + + + + + + + + + + + + No difficulty. + + + + + Subjective tension and irritability. + + + + + Worrying about minor matters. + + + + + Apprehensive attitude apparent in face or speech. + + + + + Fears expressed without questioning. + + + + + + + + + + + + + + Absent. + + + + + Mild. + + + + + Moderate. + + + + + Severe. + + + + + Incapacitating. + + + + + + + + + + + + None. + + + + + Loss of appetite but eating without staff encouragement. Heavy feelings in abdomen. + + + + + Difficulty eating without staff urging. Requests or requires laxatives or medication for bowels or medication for gastro-intestinal symptoms. + + + + + + + + + + + + None. + + + + + Heaviness in limbs, back or head. Backaches, headaches, muscle aches. Loss of energy and fatigability. + + + + + Any clear-cut symptom rates 2. + + + + + + + + + + + + Absent. + + + + + Mild. + + + + + Severe. + + + + + + + + + + + + + + Not present. + + + + + Self-absorption (bodily). + + + + + Preoccupation with health. + + + + + Frequent complaints, requests for help, etc. + + + + + Hypochondriacal delusions. + + + + + + + + + + + + + No weight loss. + + + + + Probable weight loss associated with present illness. + + + + + Definite (according to patient) weight loss. + + + + + Not assessed. + + + + + + + + + + + + + Less than 1 lb weight loss in week. + + + + + Greater than 1 lb weight loss within week. + + + + + Greater than 2 lb weight loss in week. + + + + + Not assessed. + + + + + + + + + + + + Acknowledges being depressed and ill. + + + + + Acknowledges illness but attributes cause to bad food, climate, overwork, virus, need for rest, etc. + + + + + Denies being ill at all. + + + + + + + HAMD1-Depressed Mood + + + + + + HAMD1-Feelings of Guilt + + + + + + HAMD1-Suicide + + + + + + HAMD1-Insomnia Early - Early Night + + + + + + HAMD1-Insomnia Middle - Middle Night + + + + + + HAMD1-Insomnia Early Hours - Morning + + + + + + HAMD1-Work and Activities + + + + + + HAMD1-Retardation + + + + + + HAMD1-Agitation + + + + + + HAMD1-Anxiety Psychic + + + + + + HAMD1-Anxiety Somatic + + + + + + HAMD1-Somatic Symptoms GI + + + + + + HAMD1-General Somatic Symptoms + + + + + + HAMD1-Genital Symptoms + + + + + + HAMD1-Hypochondriasis + + + + + + HAMD1-Loss of WT According to Patient + + + + + + HAMD1-Loss of WT According to WK Meas + + + + + + HAMD1-Insight + + + + + + HAMD1-Total Score + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Exclusion + + + + + + Inclusion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Males and postmenopausal females at least 50 years of age. + + + + + Diagnosis of probable AD as defined by NINCDS and the ADRDA guidelines. + + + + + MMSE score of 10 to 23. + + + + + Modified Hachinski Ischemic Scale score of <= 4. + + + + + CNS imaging (CT scan or MRI of brain) compatible with AD within past 1 year. (See Protocol for incompatible findings.) + + + + + Investigator has obtained informed consent signed by the patient (and/or legal representative) and by the caregiver. + + + + + Geographic proximity to investigator's site that allows adequate follow-up. + + + + + Caregiver will monitor administration of prescribed medications, and will be responsible for the overall care of the patient at home. + + + + + Persons who have previously completed or withdrawn from this study or any other investigating xanomeline TTS or the oral formulation of Zanomaline. + + + + + Use of any investigational agent or approved Alzheimer's therapeutic medication within 30 days prior to enrollment into the study. + + + + + Serious illness which required hospitalization within 3 months of screening. + + + + + Diagnosis of serious neurological conditions + + + + + Episode of depression meeting DSM-IV criteria within 3 months of screening. + + + + + A history within the last 5 years of the following: a) Schizophrenia b) Bipolar Disease c) Ethanol or psychoactive drug abuse or dependence. + + + + + A history of syncope within the last 5 years. + + + + + Evidence from ECG recording at screening of any of the following conditions: a) Left bundle branch block b) Bradycardia <50 beats per minute c) Sinus pauses >2 seconds (See Protocol for Remainder) + + + + + A history within the last 5 years of a serious cardiovascular disorder, including a) Clinically significant arrhythmia (See Protocol for Remainder) + + + + + A history within the last 5 years of a serious gastrointestinal disorder, including +a) Chronic peptic/duodenal/gastric/esophageal ulcer that are untreated or refractory to treatment(See Protocol) + + + + + A history within the last 5 years of a serious endocrine disorder, including +a) Uncontrolled Insulin Dependent Diabetes Mellitus (IDDM) (See Protocol for other excluded disorders) + + + + + A history within the last 5 years of a serious respiratory disorder, including a) Asthma with bronchospasm refractory to treatment b) Decompensated chronic obstructive pulmonary disease. + + + + + A history within the last 5 years of a serious genitourinary disorder, including a) Renal failure b) Uncontrolled urinary retention + + + + + A history within the last 5 years of a serious rheumatologic disorder, including a) Lupus b) Temporal arteritis c) Severe rheumatoid arthritis + + + + + A known history of human immunodeficiency virus (HIV) within the last 5 years. + + + + + A history within the last 5 years of a serious infectious disease including a) Neurosyphilis b) Meningitis c) Encephalitis + + + + + A history within the last 5 years of a primary or recurrent malignant disease (See Exceptions in Protocol). + + + + + Visual, hearing, or communication disabilities impairing the ability to participate in the study; (for example, inability to speak or understand English, illiteracy). + + + + + Laboratory test values exceeding the Reference Range III for the patient's age in any of the following analytes: creatinine, total bilirubin, SGOT, SGPT, (See Protocol for Additional Analytes) + + + + + Central laboratory test values below reference range for folate, and vitamin B12, and outside reference range for thyroid function tests. + + + + + Positive syphilis screening with confirmatory testing. + + + + + Central laboratory test value above reference range for glycosylated hemoglobin (A1C) (insulin dependent diabetes mellitus patients only). + + + + + Treatment with medications within 1 month prior to enrollment a) Anticonvulsants b) Alpha receptor blockers c) Calcium channel blockers that are CNS active + + + + + Diagnosis of serious neurological conditions (Amend 1) + + + + + Treatment with medications within 1 month prior to enrollment a) Anticonvulsants b) Alpha receptor blockers c) Calcium channel blockers that are CNS active (Amend 1) + + + + + + + Parallel + + + + + + + + + Drug + + + + + + + + + Left + + + + + + Right + + + + + + + + + Chemistry + + + + + Hematology + + + + + Urinalysis + + + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Albumin Measurement + + + + + + Alkaline Phosphatase Measurement + + + + + + Alanine Aminotransferase Measurement + + + + + + Anisocyte Measurement + + + + + + Aspartate Aminotransferase Measurement + + + + + + Total Basophil Count + + + + + + Total Bilirubin Measurement + + + + + + Calcium Measurement + + + + + + Cholesterol Measurement + + + + + + Creatine Kinase Measurement + + + + + + Chloride Measurement + + + + + + Color Assessment + + + + + + Creatinine Measurement + + + + + + Eosinophil Count + + + + + + Gamma Glutamyl Transpeptidase Measurement + + + + + + Glucose Measurement + + + + + + Hematocrit Measurement + + + + + + Hemoglobin Measurement + + + + + + Potassium Measurement + + + + + + Ketone Measurement + + + + + + Lymphocyte Count + + + + + + Macrocyte Count + + + + + + Erythrocyte Mean Corpuscular Hemoglobin + + + + + + Erythrocyte Mean Corpuscular Hemoglobin Concentration + + + + + + Erythrocyte Mean Corpuscular Volume + + + + + + Monocyte Count + + + + + + pH + + + + + + Phosphate Measurement + + + + + + Platelet Count + + + + + + Poikilocyte Measurement + + + + + + Total Protein Measurement + + + + + + Erythrocyte Count + + + + + + Sodium Measurement + + + + + + Specific Gravity + + + + + + Thyrotropin Measurement + + + + + + Urate Measurement + + + + + + Urea Nitrogen Measurement + + + + + + Urobilinogen Measurement + + + + + + Vitamin B12 Measurement + + + + + + Leukocyte Count + + + + + + + + + + + + + + + Conjunctiva + + + + + + Eye + + + + + + Anterior Chamber of the Eye + + + + + + Iris + + + + + + Cornea + + + + + + + + + Ear + + + + + + Oral Cavity + + + + + + + + + Symptom Onset + + + + + + + + + Alzheimer's Disease + + + + + + + Adverse Event + + + + + + Completed + + + + + + Death + + + + + + Lack of Efficacy + + + + + + Lost to Follow-Up + + + + + + Other + + + + + + Physician Decision + + + + + + Pregnancy + + + + + + Protocol Deviation + + + + + + Screen Failure + + + + + + Study Terminated By Sponsor + + + + + + Withdrawal By Parent/Guardian + + + + + + Withdrawal By Subject + + + + + + + + + Not Done + + + + + + + + + Abnormal + + + + + + Normal + + + + + + + + + Abnormal + + + + + + High + + + + + + Low + + + + + + Normal + + + + + + + + + + + + + Interpretation + + + + + + + + No + + + + + + Yes + + + + + + + + + Yes + + + + + + + + + Right Eye + + + + + + Left Eye + + + + + + + + + Slit-lamp Examination + + + + + + + + + + + + + + + + Abnormality Detail + + + + + Interpretation + + + + + + + + + Fatal + + + + + + Not Recovered/Not Resolved + + + + + + Recovered/Resolved + + + + + + Recovered/Resolved With Sequelae + + + + + + Recovering/Resolving + + + + + + Unknown + + + + + + + + + PHQ01-Little Interest/Pleasure in Things + + + + + + PHQ01-Feeling Down Depressed or Hopeless + + + + + + PHQ01-Trouble Falling or Staying Asleep + + + + + + PHQ01-Feeling Tired or Little Energy + + + + + + PHQ01-Poor Appetite or Overeating + + + + + + PHQ01-Feeling Bad About Yourself + + + + + + PHQ01-Trouble Concentrating on Things + + + + + + PHQ01-Moving Slowly or Fidgety/Restless + + + + + + PHQ01-Thoughts You Be Better Off Dead + + + + + + PHQ01-Difficult to Work/Take Care Things + + + + + + PHQ01-Total Score + + + + + + + + + + + + + + + + + + + + + Not at all + + + + + Several days + + + + + More than half the days + + + + + Nearly every day + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Standing + + + + + + Supine + + + + + + + + + Informed Consent + + + + + + + + + Patient Health Questionnaire - 9 Item + + + + + + + + + Satisfaction With Life Scale Questionnaire + + + + + + + + + American Indian Or Alaska Native + + + + + + Asian + + + + + + Black Or African American + + + + + + Native Hawaiian Or Other Pacific Islander + + + + + + White + + + + + + + + + Multiple + + + + + + + Adverse Events + + + + + + Disposition + + + + + + Death Details + + + + + + Findings About Events or Interventions + + + + + + + + + Many + + + + + + One + + + + + + + + + Oral + + + + + + Topical + + + + + + Intravenous + + + + + + Nasal + + + + + + Inhalation Route of Administration + + + + + + Transdermal + + + + + + + + + Subcutaneous Route of Administration + + + + + + + + + Hamilton Depression Rating Scale 17 Item Clinical Classification + + + + + + + + + Female + + + + + + Male + + + + + + + + + + + + + + + + + Interventional + + + + + + + + + SWLS01-Have Gotten Important Things + + + + + + SWLS01-I Am Satisfied with My Life + + + + + + SWLS01-Live Life Over Change Nothing + + + + + + SWLS01-My Life Conditions are Excellent + + + + + + SWLS01-My Life is Close to Ideal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Strongly disagree + + + + + Disagree + + + + + Slightly disagree + + + + + Neither agree nor disagree + + + + + Slightly agree + + + + + Agree + + + + + Strongly agree + + + + + + + Double Blind + + + + + + + + + Placebo + + + + + + + + + Treatment + + + + + + + + + Phase II Trial + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Actual Subject Number + + + + + + Adaptive Study Design Indicator + + + + + + Test Product Added to Existing Treatment + + + + + + Planned Maximum Age of Subjects + + + + + + Planned Minimum Age of Subjects + + + + + + Data Cutoff Date Description + + + + + + Data Cutoff Date + + + + + + Dose + + + + + + Pharmaceutical Dosage Form + + + + + + Dose Frequency + + + + + + Dosage Form Unit + + + + + + Planned Country of Investigational Site + + + + + + Healthy Subject Indicator + + + + + + Trial Indication + + + + + + Intervention Model + + + + + + Intervention Type + + + + + + Trial Length + + + + + + Planned Number of Arms + + + + + + Trial Primary Objective + + + + + + Trial Secondary Objective + + + + + + Primary Outcome Measure + + + + + + Secondary Outcome Measure + + + + + + Pharmacological Class of Investigational Therapy + + + + + + Planned Subject Number + + + + + + Randomization + + + + + + Randomization Quotient + + + + + + Clinical Trial Registry Identifier + + + + + + Route of Administration + + + + + + Study Data Tabulation Model Implementation Guide Version + + + + + + Study Data Tabulation Model Version + + + + + + Clinical Study End Date + + + + + + Sex of Study Group + + + + + + Clinical Study Sponsor + + + + + + Study Start Date + + + + + + Study Stop Rule + + + + + + Study Type + + + + + + Trial Blinding Schema + + + + + + Control Type + + + + + + Diagnosis Group + + + + + + Clinical Study by Intent + + + + + + Trial Title + + + + + + Trial Phase + + + + + + Protocol Agent + + + + + + Trial Type + + + + + + + + + Efficacy + + + + + + Pharmacokinetic + + + + + + Safety + + + + + + + + + Milligram + + + + + + Nanogram + + + + + + Tablet + + + + + + + + + Milliliter + + + + + + + + + Gram per Liter + + + + + + + + + Milligram + + + + + + + + + Million per Microliter + + + + + + + + + Billion per Liter + + + + + + + + + Percentage + + + + + + + + + Unit per Liter + + + + + + + + + Femtoliter + + + + + + + + + Femtomole + + + + + + + + + Femtomole + + + + + + + + + Gram per Deciliter + + + + + + + + + Milliequivalent Per Liter + + + + + + + + + Microinternational Unit per Milliliter + + + + + + + + + Microunit per Milliliter + + + + + + + + + Milligram per Deciliter + + + + + + + + + Millimole per Liter + + + + + + + + + Nanogram per Liter + + + + + + + + + Picogram + + + + + + + + + Picomole per Liter + + + + + + + + + Micromole per Liter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Diastolic Blood Pressure + + + + + + Pulse Rate + + + + + + Height + + + + + + Systolic Blood Pressure + + + + + + Temperature + + + + + + Weight + + + + + + + + + Millimeter of Mercury + + + + + + + + + Millimeter of Mercury + + + + + + + + + Inch + + + + + + + + + Centimeter + + + + + + + + + Beats per Minute + + + + + + + + + Beats per Minute + + + + + + + + + Degree Fahrenheit + + + + + + + + + Degree Celsius + + + + + + + + + Pound + + + + + + + + + Kilogram + + + + + + + + + + + + + + + + + + + + + + + + + + If AEENRTPT is populated, AEENTPT is DM.RFPENDTC for the subject. + + + + + If CMENRTPT is populated, CMENTPT is DM.RFPENDTC for the subject. + + + + + Study day relative to RFSTDTC. Date - RFSTDTC + 1 if on or after RFSTDTC. Date - RFSTDTC if date precedes RFSTDTC. + + + + + Starts at "1" for first device identifier and increments by one for each DIPARM + + + + + If DTHDTC is populated then DTHFL='Y' + + + + + EPOCH from SE where date >= SESTDTC and date < SEENDTC + + + + + EXDOSE = ECDOSE * ECPSTRG expressed in mg. + + + + + If FTSTRESC is numeric then FTSTRESN=FTSTRESC in numeric format, else null. + + + + + If IECAT=INCLUSION then IEORRES=N, else if IECAT=EXCLUSION then IEORRES=Y + + + + + LBSTRESC is equal to LBORRES or the value in standard units if a conversion is necessary. + + + + + Set to "Y" for last record with non-null original result on or before the first dose date (RFXSTDTC). Null otherwise. + + + + + If QSORRES="Not at all" then 0 +If QSORRES="Several days" then 1 +If QSORRES="More than half the days" then 2 +If QSORRES="Nearly every day" then 3 + + + + + QSSTRESC=QSORRES + + + + + If QSORRES="Strongly disagree" then 1 +If QSORRES="Disagree" then 2 +If QSORRES="Slightly disagree" then 3 +If QSORRES="Neither agree nor disagree" then 4 +If QSORRES="Slightly agree" then 5 +If QSORRES="Agree" then 6 +If QSORRES="Strongly agree" then 7 + + + + + If QSSTRESC is numeric then QSSTRESN=QSSTRESC in numeric format, else null. + + + + + The Date of Study Completion or Early Termination. Null for screen failures. + + + + + The latest date of assessment for the subject as determined by the End of Study Form, any scheduled assessments, Adverse Events, or Concomitant Medications. + + + + + The first date/time of study drug. Null for screen failures. + + + + + The last date/time of study drug administration. Null for subjects with no treatment data. + + + + + The first date/time of study drug administration. Null for subjects with no treatment data. + + + + + RSSTRESC is the corresponding numeric value of RSORRES according the values shown on the HAMD-17 CRF page. + + + + + SEENDTC is set to the start of the next Element, or RFPENDTC for the last Element. + + + + + Unique sequence number within a subject, restarting at 1 for every subject, applied to sorted data. + + + + + SESTDTC if set to the --DTC for that subject which exists in the data for the defined start of the Element, such as DSSTDTC when DSDECOD=INFORMED CONSENT OBTAINED for Screening Elements or min(EXSTDTC) for Dosing Elements. + + + + + If --STRESC represents a numeric value then --STRESN is the numeric version of --STRESC, else null. "--" represents the domain code. + + + + + For each scheduled visit, SVENDTC = the last (max) date associated with a subject for that visit. For unplanned visits, SVENDTC is the date of the visit. + + + + + For each scheduled visit, SVSTDTC = the first (min) date associated with a subject for that visit. For unplanned visits, SVSTDTC is the date of the visit. + + + + + Unique sequence number within each TSPARM, restarting at 1 for per TSPARM, applied to sorted data. + + + + + Data collected in conventional units (i.e. F, lbs, inches) is converted using standard conversion factors to standard units (C, kg, cm). + + + + + + + + + + + Even though the variable is 'Assigned' an annotation has been added to page 23 to clarify the assignment. + + + + + Coding variables are not populated due to the proprietary coding dictionary, but the variables are included as they are Expected or Required. + + + + + Coding variables are not populated due to the proprietary coding dictionary, but the variables are included as they are Expected or Required. Note CDISC Conformance Rule CG0014 would fire for this variable due to the decision not to populate coding variables. + + + + + Subject CDISC003 had an AE of Epistaxis on 2013-09-30 with AESER set to 'Y' without any of the individual serious qualifiers set to 'Y' also. The site was queried several times but the data were not updated. Note Conformance Rule CG0041 would fire for this subject. + + + + + If the CM is not taken for a 'Primary Study Condition' then CMINDC would be 'Prophylaxis or Non-therapeutic use' + + + + + Since no collected data was subjective then QEVAL was not populated. It is an 'Expected' variable and so is included. + + + + + Since no subjects had more than 3 Races, RACE4 was not used. + + + + + Since no subjects had more than 3 Races, RACE5 was not used. + + + + + Variable is Assigned but there are annotations to help understand the data and so references to the proper pages are included + + + + + DataType is 'partialDatetime' instead of 'datetime' since datetime values are planned to be collected without seconds for this study. + + + + + All values are null as the findings are not visit based. The variable is Expected and so is included. + + + + + The FA domain contains Findings About Injection Site Reaction Adverse Events + + + + + IEDY is needed if IEDTC is included. Note RFSTDTC is not populated for not randomized subjects then IEDY could not be populated in those cases. + + + + + Please see Appendix 1 of the cSDRG for complete versions of IETESTCD and IETEST. + + + + + Standard's Conformance Notes: +1) The SDTM v1.7/SDTMIG v3.3 datasets were evaluated manually and programmatically by the CDISC SDS MSG Team. At the completion of the SDTM-MSG v2.0, the CDISC SDTM v1.7/SDTMIG v3.3 conformance rules were recently published, but not available by any validation tools to validate. +2) The Define-XML document was evaluated manually and programmatically by the CDISC SDS MSG Team. At the completion of the SDTM-MSG v2.0, the CDISC +Define-XML v2.1 conformance rules were not published, nor available by any validation tools to validate. Please ensure that any official regulatory submission of an Define-XML v2.1 document and accompanying data is done in accordance to the respective regulatory health authorities requirements/guidance. + + + + + Per protocol, electroencephalograms are only performed after such an event were to occur. No subjects within the trial had an occurrence of an electroencephalogram event. Therefore, no data exists for the NV dataset and as such was not submitted. + + + + + Per protocol, electroencephalograms are only performed after such an event were to occur. No subjects within the trial had an occurrence of an electroencephalogram event. Therefore, no data exists for the NV dataset and as such SUPPNV was not submitted. + + + + + No subjects within the trial had an ophthalmic examination of clinical significance to report. Therefore, no data exists for the SUPPOE dataset and as such was not submitted. + + + + + QSPH contains the PATIENT HEALTH QUESTIONNAIRE-9 (PHQ-9) questionnaire data. + + + + + QSSL contains the SATISFACTION WITH LIFE SURVEY (SWLS) questionnaire data. + + + + + Study Data Tabulation Model Implementation Guide: Human Clinical Trials Version 3.3 + + + + + Study Data Tabulation Model Implementation Guide for Medical Devices Version 1.0 + + + + + This was the latest release of CDISC CT available when this sample submission was completed. + + + + + This was the CDISC CT Package associated to the CDISC Define-XML Specification Version 2.1 when this sample submission was completed. + + + + + All vital signs were performed as expected, so VSSTAT was never populated. The variable is included as it was possible to populate it in this study. + + + + + + + + + + Annotated CRF + + + + Reviewers Guide + + + + + + + + + + diff --git a/tests/resources/CoreIssue1443/Define_with_codelist.xml b/tests/resources/CoreIssue1443/Define_with_codelist.xml new file mode 100644 index 000000000..ca96f0da1 --- /dev/null +++ b/tests/resources/CoreIssue1443/Define_with_codelist.xml @@ -0,0 +1,11893 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDISCPILOT01 + Study Data Tabulation Model Metadata Submission Guidelines Sample Study + CDISCPILOT01 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INJECTION SITE REACTION + + + + + INJECTION SITE REACTION + + + + + AVL0201 + AVL0202 + AVL0203 + AVL0204 + AVL0205 + AVL0206 + AVL0207 + AVL0208 + AVL0209 + AVL0210 + AVL0211 + AVL0212 + AVL0213 + AVL0214 + AVL0215 + + + + + AVL0216 + AVL0217 + + + + + AVL0218 + AVL0219 + AVL0220 + AVL0221 + AVL0222 + AVL0223 + AVL0224 + AVL0225 + AVL0226 + AVL0227 + AVL0228 + AVL0229 + AVL0230 + AVL0231 + AVL0232 + + + + + AVL0233 + AVL0234 + + + + + DIABP + SYSBP + + + + + + + + + + + + + + + + + + + + + + + + + ECREASOC + + + + + OCCUR + + + + + SEV + + + + + HAMD101 + + + + + HAMD101 + + + + + HAMD102 + + + + + HAMD102 + + + + + HAMD103 + + + + + HAMD103 + + + + + HAMD104 + + + + + HAMD104 + + + + + HAMD105 + + + + + HAMD105 + + + + + HAMD106 + + + + + HAMD106 + + + + + HAMD107 + + + + + HAMD107 + + + + + HAMD108 + + + + + HAMD108 + + + + + HAMD109 + + + + + HAMD109 + + + + + HAMD110 + + + + + HAMD110 + + + + + HAMD111 + + + + + HAMD111 + + + + + HAMD112 + + + + + HAMD112 + + + + + HAMD113 + + + + + HAMD113 + + + + + HAMD114 + + + + + HAMD114 + + + + + HAMD115 + + + + + HAMD115 + + + + + HAMD116A + + + + + HAMD116A + + + + + HAMD116B + + + + + HAMD116B + + + + + HAMD117 + + + + + HAMD117 + + + + + HAMD118 + + + + + HAMD118 + + + + + HEIGHT + + + + + HEIGHT + + + + + ALB + + + + + ALP + + + + + ALT + + + + + AST + + + + + BASO + + + + + BILI + + + + + CA + + + + + CHOL + + + + + CK + + + + + CL + + + + + CREAT + + + + + EOS + + + + + GGT + + + + + GLUC + + + + + HCT + + + + + HGB + + + + + K + + + + + LYM + + + + + MCH + + + + + MCHC + + + + + MCV + + + + + MONO + + + + + PHOS + + + + + PLAT + + + + + PROT + + + + + RBC + + + + + SODIUM + + + + + TSH + + + + + URATE + + + + + UREAN + + + + + VITB12 + + + + + WBC + + + + + COLOR + + + + + GLUC + + + + + ALB + BILI + CA + CREAT + K + PHOS + PROT + URATE + + + + + HCT + HGB + + + + + BASO + EOS + LYM + MONO + RBC + TSH + WBC + + + + + ANISO + KETONES + MACROCY + PH + POIKILO + UROBIL + + + + + ALT + AST + GGT + MCH + MCHC + MCV + UREAN + + + + + ALP + CHOL + CK + CL + PLAT + SODIUM + VITB12 + + + + + SPGRAV + + + + + BILI + + + + + CK + + + + + COLOR + + + + + CREAT + + + + + GLUC + + + + + HGB + + + + + K + + + + + MCHC + + + + + RBC + + + + + BASO + EOS + LYM + MONO + RBC + TSH + WBC + + + + + SPGRAV + UREAN + + + + + CA + CHOL + MCH + PHOS + + + + + ANISO + KETONES + MACROCY + PH + POIKILO + UROBIL + + + + + ALB + ALT + AST + GGT + PROT + + + + + ALP + CL + MCV + PLAT + SODIUM + + + + + URATE + + + + + VITB12 + + + + + ALB + + + + + ALP + + + + + ALT + + + + + AST + + + + + BASO + + + + + BILI + + + + + CA + + + + + CHOL + + + + + CK + + + + + CL + + + + + CREAT + + + + + EOS + + + + + GGT + + + + + GLUC + + + + + HGB + + + + + K + + + + + LYM + + + + + MCHC + + + + + MCH + + + + + MCV + + + + + MONO + + + + + PHOS + + + + + PLAT + + + + + PROT + + + + + RBC + + + + + SODIUM + + + + + TSH + + + + + URATE + + + + + UREAN + + + + + VITB12 + + + + + WBC + + + + + NVCLSIG + + + + + OECLSIG + + + + + INTP + + + + + ABDETAIL + + + + + PHQ0101 + PHQ0102 + PHQ0103 + PHQ0104 + PHQ0105 + PHQ0106 + PHQ0107 + PHQ0108 + PHQ0109 + + + + + PHQ0101 + PHQ0102 + PHQ0103 + PHQ0104 + PHQ0105 + PHQ0106 + PHQ0107 + PHQ0108 + PHQ0109 + + + + + PHQ0110 + + + + + PHQ0110 + + + + + PHQ0111 + + + + + PHQ0111 + + + + + PULSE + + + + + PULSE + + + + + MULTIPLE + + + + + RACE1 + + + + + RACE2 + + + + + RACE3 + + + + + RACE4 + + + + + RACE5 + + + + + MULTIPLE + + + + + TEMP + + + + + TEMP + + + + + TBLIND + + + + + TCNTRL + + + + + FCNTRY + + + + + DCUTDTC + SENDTC + SSTDTC + + + + + TS_DURATION + + + + + TS_FLOAT + + + + + DOSFRQ + + + + + DOSFRM + + + + + INDIC + + + + + ACTSUB + AGEMAX + AGEMIN + DOSE + NARMS + PLANSUB + + + + + INTTYPE + + + + + INTMODEL + + + + + OBJPRIM + + + + + OBJSEC + + + + + OUTMSPRI + + + + + PCLAS + + + + + TPHASE + + + + + REGID + + + + + ROUTE + + + + + SDTIGVER + SDTMVER + + + + + SEXPOP + + + + + SPONSOR + + + + + STOPRULE + + + + + STYPE + + + + + TDIGRP + + + + + TINDTP + + + + + TITLE + + + + + TRT + + + + + TTYPE + + + + + DOSU + + + + + ADAPT + ADDON + HLTSUBJI + RANDOM + + + + + WEIGHT + + + + + WEIGHT + + + + + + + + + + + + Trial Arms + + + + + + + + + + + + + + ta.xpt + + + + + + Trial Elements + + + + + + + + + + te.xpt + + + + + + Trial Inclusion/Exclusion Criteria + + + + + + + + + + ti.xpt + + + + + + Trial Summary + + + + + + + + + + + + + + + ts.xpt + + + + + + Trial Visits + + + + + + + + + + + tv.xpt + + + + + + Demographics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dm.xpt + + + + + + Subject Elements + + + + + + + + + + + + + + + se.xpt + + + + + + Subject Visits + + + + + + + + + + + + + + sv.xpt + + + + + + Concomitant Medications + + + + + + + + + + + + + + + + + + + + + cm.xpt + + + + + + Exposure as Collected + + + + + + + + + + + + + + + + + + + + + + + + + ec.xpt + + + + + + Exposure + + + + + + + + + + + + + + + + + + + + + ex.xpt + + + + + + Adverse Events + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ae.xpt + + + + + + Disposition + + + + + + + + + + + + + + + + ds.xpt + + + + + + Medical History + + + + + + + + + + + + mh.xpt + + + + + + Death Details + + + + + + + + + + + + + + + + dd.xpt + + + + + + Functional Tests + + + + + + + + + + + + + + + + + + + + + + + + + + ft.xpt + + + + + + Inclusion/Exclusion Criteria Not Met + + + + + + + + + + + + + + + + ie.xpt + + + + + + Laboratory Test Results + + + + + + + + + + + + + + + + + + + + + + + + + + + lb.xpt + + + + + + Nervous System Findings + + + + + + + + + + + + + + + + + + + Ophthalmic Examinations + + + + + + + + + + + + + + + + + + + + + + oe.xpt + + + + + + Questionnaires (PHQ-9) + + + + + + + + + + + + + + + + + + + + + + qsph.xpt + + + + + + Questionnaires (SQLS) + + + + + + + + + + + + + + + + + + + + + qssl.xpt + + + + + + Disease Response and Clin Classification + + + + + + + + + + + + + + + + + + + + + rs.xpt + + + + + + Vital Signs + + + + + + + + + + + + + + + + + + + + + + + + + vs.xpt + + + + + + Findings About Events or Interventions + + + + + + + + + + + + + + + + + + + + fa.xpt + + + + + + Related Records + + + + + + + + + + + relrec.xpt + + + + + + Supplemental Qualifiers for DM + + + + + + + + + + + + + + + suppdm.xpt + + + + + + Supplemental Qualifiers for EC + + + + + + + + + + + + + + + suppec.xpt + + + + + + Supplemental Qualifiers for NV + + + + + + + + + + + + + + + + + + Supplemental Qualifiers for OE + + + + + + + + + + + + + + + + + + Device Identifiers + + + + + + + + + + + di.xpt + + + + + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link ID + + + + + + + + + + Reported Term for the Adverse Event + + + + + + Lowest Level Term + + + + + + + Lowest Level Term Code + + + + + + + Dictionary-Derived Term + + + + + + + Preferred Term Code + + + + + + + High Level Term + + + + + + + High Level Term Code + + + + + + + High Level Group Term + + + + + + + High Level Group Term Code + + + + + + + Body System or Organ Class + + + + + + + Body System or Organ Class Code + + + + + + + Primary System Organ Class + + + + + + + Primary System Organ Class Code + + + + + + + Severity/Intensity + + + + + + + + + + + Serious Event + + + + + + + + + + + Action Taken with Study Treatment + + + + + + + + + + + Causality + + + + + + + + + + + Outcome of Adverse Event + + + + + + + + + + + Involves Cancer + + + + + + + + + + + Congenital Anomaly or Birth Defect + + + + + + + + + + + Persist or Signif Disability/Incapacity + + + + + + + + + + + Results in Death + + + + + + + + + + + Requires or Prolongs Hospitalization + + + + + + + + + + + Is Life Threatening + + + + + + + + + + + Occurred with Overdose + + + + + + + + + + + Epoch + + + + + + + Start Date/Time of Adverse Event + + + + + + + + + + End Date/Time of Adverse Event + + + + + + + + + + Study Day of Start of Adverse Event + + + + + + + Study Day of Start of Adverse Event + + + + + + Study Day of End of Adverse Event + + + + + + End Relative to Reference Time Point + + + + + + + + + + + End Reference Time Point + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Reported Name of Drug, Med, or Therapy + + + + + + + + + + Indication + + + + + + + + + + Dose per Administration + + + + + + + + + + Dose Units + + + + + + + + + + + Dosing Frequency per Interval + + + + + + + + + + + Route of Administration + + + + + + + + + + + Epoch + + + + + + + Start Date/Time of Medication + + + + + + + + + + End Date/Time of Medication + + + + + + + + + + Study Day of Start of Medication + + + + + + Study Day of End of Medication + + + + + + End Relative to Reference Time Point + + + + + + + + + + + End Reference Time Point + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Sponsor Device Identifier + + + + + + Sequence Number + + + + + + Device Identifier Element Short Name + + + + + + + Device Identifier Element Name + + + + + + + Device Identifier Element Value + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Subject Identifier for the Study + + + + + + Subject Reference Start Date/Time + + + + + + Subject Reference End Date/Time + + + + + + Date/Time of First Study Treatment + + + + + + Date/Time of Last Study Treatment + + + + + + Date/Time of Informed Consent + + + + + + + + + + Date/Time of End of Participation + + + + + + Date/Time of Death + + + + + + + + + + Subject Death Flag + + + + + + + Study Site Identifier + + + + + + + Date/Time of Birth + + + + + + + + + + Age + + + + + + + + + + Age Units + + + + + + + Sex + + + + + + + + + + + Race + + + + + + Ethnicity + + + + + + + + + + + Planned Arm Code + + + + + + + Description of Planned Arm + + + + + + + Actual Arm Code + + + + + + + Description of Actual Arm + + + + + + + Reason Arm and/or Actual Arm is Null + + + + + + + Description of Unplanned Actual Arm + + + + + + Country + + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link ID + + + + + + + + + + Reported Term for the Disposition Event + + + + + + Standardized Disposition Term + + + + + + Category for Disposition Event + + + + + + + + + + + Subcategory for Disposition Event + + + + + + + + + + + Epoch + + + + + + + Start Date/Time of Disposition Event + + + + + + + + + + Study Day of Start of Disposition Event + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sponsor Device Identifier + + + + + + Sequence Number + + + + + + Name of Treatment + + + + + + + Pre-Specified + + + + + + + Occurrence + + + + + + + + + + + Dose + + + + + + + + + + Dose Units + + + + + + + + + + + Dose Form + + + + + + + Dosing Frequency per Interval + + + + + + + Route of Administration + + + + + + + Lot Number + + + + + + + + + + Pharmaceutical Strength + + + + + + Pharmaceutical Strength Units + + + + + + + Epoch + + + + + + + Start Date/Time of Treatment + + + + + + + + + + End Date/Time of Treatment + + + + + + + + + + Study Day of Start of Treatment + + + + + + Study Day of End of Treatment + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sponsor Device Identifier + + + + EC.SPDEVID + + + + + + Sequence Number + + + + + + Name of Treatment + + + + + ECTRT + + + + + + Dose + + + + + + Dose Units + + + + + + + Dose Form + + + + + ECDOSFRM + + + + + + Dosing Frequency per Interval + + + + + ECDOSFRQ + + + + + + Route of Administration + + + + + ECROUTE + + + + + + Lot Number + + + + ECLOT + + + + + + Epoch + + + + + EC.EPOCH + + + + + + Start Date/Time of Treatment + + + + ECSTDTC + + + + + + End Date/Time of Treatment + + + + ECENDTC + + + + + + Study Day of Start of Treatment + + + + ECSTDY + + + + + + Study Day of End of Treatment + + + + ECENDY + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link Group ID + + + + + + + + + + Findings About Test Short Name + + + + + + + Findings About Test Name + + + + + + + Object of the Observation + + + + + + + + + + + Category for Findings About + + + + + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + FAORRES + + + + + + + Location of the Finding About + + + + + + + Visit Number + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Short Name of Test + + + + + + + Name of Test + + + + + + + Category + + + + + + + + + + + Subcategory + + + + + + + + + + Result or Finding in Original Units + + + + + + Result or Finding in Standard Format + + + + FTORRES + + + + + + Numeric Result/Finding in Standard Units + + + + + + Last Observation Before Exposure Flag + + + + + + + Repetition Number + + + + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Test + + + + + + + + + + Study Day of Test + + + + + + Planned Time Point Name + + + + + + Planned Time Point Number + + + + + + Planned Elapsed Time from Time Point Ref + + + + + + + + + + Time Point Reference + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Inclusion/Exclusion Criterion Short Name + + + + + + + + + + + Inclusion/Exclusion Criterion + + + + + + + Inclusion/Exclusion Category + + + + + + + + + + + I/E Criterion Original Result + + + + + + + + + + + I/E Criterion Result in Std Format + + + + + IEORRES + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Question Short Name + + + + + + + Question Name + + + + + + + Category of Question + + + + + + + + + + + Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + + Numeric Finding in Standard Units + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Finding + + + + + + Study Day of Finding + + + + + + Evaluation Interval + + + + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Question Short Name + + + + + + + Question Name + + + + + + + Category of Question + + + + + + + + + + + Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + + + + + + + Numeric Finding in Standard Units + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Finding + + + + + + Study Day of Finding + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Relationship Type + + + + + + + Relationship Identifier + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Assessment Short Name + + + + + + + Assessment Name + + + + + + + Category for Assessment + + + + + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + + + Numeric Result/Finding in Standard Units + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Assessment + + + + + + Study Day of Assessment + + + + + + Evaluation Interval + + + + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Element Code + + + + + + + Description of Element + + + + + + + Epoch + + + + + + + Start Date/Time of Element + + + + + + End Date/Time of Element + + + + + + Study Day of Start of Element + + + + + + Study Day of End of Element + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Visit Number + + + + + + Visit Name + + + + + + Start Date/Time of Visit + + + + + + End Date/Time of Visit + + + + + + Study Day of Start of Visit + + + + + + Study Day of End of Visit + + + + + + Description of Unplanned Visit + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Planned Arm Code + + + + + + + Description of Planned Arm + + + + + + + Planned Order of Element within Arm + + + + + + Element Code + + + + + + + Description of Element + + + + + + + Branch + + + + + + Transition Rule + + + + + + Epoch + + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Element Code + + + + + + + Description of Element + + + + + + + Rule for Start of Element + + + + + + Rule for End of Element + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Incl/Excl Criterion Short Name + + + + + + + Inclusion/Exclusion Criterion + + + + + + + Inclusion/Exclusion Category + + + + + + + Protocol Criteria Versions + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Sequence Number + + + + + + Group ID + + + + + + Trial Summary Parameter Short Name + + + + + + + Trial Summary Parameter + + + + + + + Parameter Value + + + + + + Parameter Null Flavor + + + + + + + Parameter Value Code + + + + + + Name of the Reference Terminology + + + + + + Version of the Reference Terminology + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Planned Arm Code + + + + + + + Visit Start Rule + + + + + + Visit End Rule + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Vital Signs Test Short Name + + + + + + + Vital Signs Test Name + + + + + + + Vital Signs Position of Subject + + + + + + + + + + + Result or Findings as Collected + + + + + + Unit of the Original Result + + + + + + + + Standardized Result in Character Format + + + + + + Standardized Result in Numeric Format + + + + + + Unit of the Standardized Result + + + + + + + + Completion Status + + + + + + + + + + + Location of Vital Signs Measurement + + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Repetition Number + + + + + + + + + + Visit Number + + + + + + Visit Name + + + + + + + + + + Epoch + + + + + + + Date/Time of Measurement + + + + + + + + + + Study Day of Vital Signs Measurement + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Short Name of Nervous System Test + + + + + + + Name of Nervous System Test + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + + NVORRES + + + + + + Visit Number + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Visit/Collection/Exam + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Reported Term for the Medical History + + + + + + + Medical History Event Date Type + + + + + + + + + + + Start Date/Time of Medical History Event + + + + + + + + + + Study Day of Start of Observation + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Link ID + + + + + + + + + + Death Detail Assessment Short Name + + + + + + + Death Detail Assessment Name + + + + + + + Result or Finding as Collected + + + + + + + + + + Character Result/Finding in Std Format + + + + DDORRES + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Sequence Number + + + + + + Lab Test or Examination Short Name + + + + + + + Lab Test or Examination Name + + + + + + + Category for Lab Test + + + + + + + Result or Finding in Original Units + + + + + + + Original Units + + + + + + + Reference Range Lower Limit in Orig Unit + + + + + + Reference Range Upper Limit in Orig Unit + + + + + + Character Result/Finding in Std Format + + + + + + + Numeric Result/Finding in Standard Units + + + + + + Standard Units + + + + + + + Reference Range Lower Limit-Std Units + + + + + + Reference Range Upper Limit-Std Units + + + + + + Reference Range Indicator + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + Epoch + + + + + + + Date/Time of Specimen Collection + + + + + + Study Day of Specimen Collection + + + + + + Study Identifier + + + + + + Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Focus of Study-Specific Interest + + + + + + + + + + + Sequence Number + + + + + + Short Name of Ophthalmic Test or Exam + + + + + + + Name of Ophthalmic Test or Exam + + + + + + + Result or Finding in Original Units + + + + + + + + + + + Character Result/Finding in Std Format + + + + OEORRES + + + + + + Location Used for the Measurement + + + + + + + + + + + Laterality + + + + + + + + + + + Method of Test or Examination + + + + + + + + + + + Last Observation Before Exposure Flag + + + + + + + Visit Number + + + + + + Visit Name + + + + + + + + + + Epoch + + + + + + + Date/Time of Collection + + + + + + + + + + Study Day of Visit/Collection/Exam + + + + + + Study Identifier + + + + + + Related Domain Abbreviation + + + + + + + Unique Subject Identifier + + + + + + Identifying Variable + + + + + + Identifying Variable Value + + + + + + Qualifier Variable Name + + + + + + Qualifier Variable Label + + + + + + Data Value + + + + + + Origin + + + + + + Evaluator + + + + + + Reported Term for the Adverse Event + + + + + + + + + + Reported Term for the Adverse Event + + + + + + + + + + Standardized Disposition Term + + + + + + + + + + + Standardized Disposition Term + + + + + + + + + + + Reported Term for the Disposition Event + + + + + + + + + + Reported Term for the Disposition Event + + + + + + + + + + Result or Finding in Original Units + + + + + + Result or Finding in Original Units + + + + + + Character Result/Finding in Std Format + + + + + + Character Result/Finding in Std Format + + + + + + AVLT-REY List A Item 1-15 + + + + + + + + + + + AVLT-REY List A Item 16-17 + + + + + + + + + + AVLT-REY List B Item 18-32 + + + + + + + + + + + AVLT-REY List B Item 33-34 + + + + + + + + + + Lab Result or Finding in Original Units - Set 1 + + + + + Lab Result or Finding in Original Units - Set 2 + + + + + Lab Result or Finding in Original Units - Set 3 + + + + + Lab Result or Finding in Original Units - Specific Gravity + + + + + Lab Result or Finding in Original Units - Set 4 + + + + + Lab Result or Finding in Original Units - Set 5 + + + + + Lab Result or Finding in Original Units - Set 6 + + + + + Lab Result or Finding in Original Units - Color + + + + + Lab Result or Finding in Original Units - Glucose + + + + + Lab Result Units - ALT + + + + + + Lab Result Units - ALB + + + + + + Lab Result Units - ALP + + + + + + Lab Result Units - AST + + + + + + Lab Result Units - BASO + + + + + + Lab Result Units - BILI + + + + + + Lab Result Units - CA + + + + + + Lab Result Units - CL + + + + + + Lab Result Units - CHOL + + + + + + Lab Result Units - CK + + + + + + Lab Result Units - CREAT + + + + + + Lab Result Units - EOS + + + + + + Lab Result Units - MCH + + + + + + Lab Result Units - MCHC + + + + + + Lab Result Units - MCV + + + + + + Lab Result Units - RBC + + + + + + Lab Result Units - GGT + + + + + + Lab Result Units - GLUC + + + + + + Lab Result Units - HCT + + + + + + Lab Result Units - HGB + + + + + + Lab Result Units - WBC + + + + + + Lab Result Units - LYM + + + + + + Lab Result Units - MONO + + + + + + Lab Result Units - PHOS + + + + + + Lab Result Units - PLAT + + + + + + Lab Result Units - K + + + + + + Lab Result Units - PROT + + + + + + Lab Result Units - SODIUM + + + + + + Lab Result Units - TSH + + + + + + Lab Result Units - URATE + + + + + + Lab Result Units - UREAN + + + + + + Lab Result Units - VITB12 + + + + + + Character Result/Finding in Std Format - K + + + + + Character Result/Finding in Std Format - RBC + + + + + Character Result/Finding in Std Format - Set 1 + + + + + Character Result/Finding in Std Format - BILI + + + + + Character Result/Finding in Std Format - Set 2 + + + + + Character Result/Finding in Std Format - CREAT + + + + + Character Result/Finding in Std Format - URATE + + + + + Character Result/Finding in Std Format - MCHC + + + + + Character Result/Finding in Std Format - Set 3 + + + + + Character Result/Finding in Std Format - VITB12 + + + + + Character Result/Finding in Std Format - HGB + + + + + Character Result/Finding in Std Format - Set 4 + + + + + Character Result/Finding in Std Format - Set 5 + + + + + Character Result/Finding in Std Format - Set 6 + + + + + Character Result/Finding in Std Format - CK + + + + + Character Result/Finding in Std Format - COLOR + + + + + + Character Result/Finding in Std Format - GLUC + + + + + Lab Result Standard Units - ALT + + + + + + Lab Result Standard Units - ALB + + + + + + Lab Result Standard Units - ALP + + + + + + Lab Result Standard Units - AST + + + + + + Lab Result Standard Units - BASO + + + + + + Lab Result Standard Units - BILI + + + + + + Lab Result Standard Units - CA + + + + + + Lab Result Standard Units - CL + + + + + + Lab Result Standard Units - CHOL + + + + + + Lab Result Standard Units - CK + + + + + + Lab Result Standard Units - CREAT + + + + + + Lab Result Standard Units - EOS + + + + + + Lab Result Standard Units - MCH + + + + + + Lab Result Standard Units - MCHC + + + + + + Lab Result Standard Units - MCV + + + + + + Lab Result Standard Units - RBC + + + + + + Lab Result Standard Units - GGT + + + + + + Lab Result Standard Units - GLUC + + + + + + Lab Result Standard Units - HGB + + + + + + Lab Result Standard Units - WBC + + + + + + Lab Result Standard Units - LYM + + + + + + Lab Result Standard Units - MONO + + + + + + Lab Result Standard Units - PHOS + + + + + + Lab Result Standard Units - PLAT + + + + + + Lab Result Standard Units - K + + + + + + Lab Result Standard Units - PROT + + + + + + Lab Result Standard Units - SODIUM + + + + + + Lab Result Standard Units - TSH + + + + + + Lab Result Standard Units - URATE + + + + + + Lab Result Standard Units - UREAN + + + + + + Lab Result Standard Units - VITB12 + + + + + + Result or Finding in Original Units + + + + + + Result or Finding in Original Units + + + + + PHQ-9 Questions 1-9 + + + + + + PHQ-9 Question 10 + + + + + + PHQ-9 Question Total + + + + + PHQ-9 Questions 1-9, Standardized + + + + + + + + + + + PHQ-9 Question 10, Standardized + + + + + + + + + + + PHQ-9 Question Total, Standardized + + + + QSORRES where QSTESTCD EQ PHQ0111 + + + + + + + + + Race + + + + + + + + + + + Race + + + + + + + + + + + HAMD-17 Question 1 + + + + + + + + + + + HAMD-17 Question 2 + + + + + + + + + + + HAMD-17 Question 3 + + + + + + + + + + + HAMD-17 Question 4 + + + + + + + + + + + HAMD-17 Question 5 + + + + + + + + + + + HAMD-17 Question 6 + + + + + + + + + + + HAMD-17 Question 7 + + + + + + + + + + + HAMD-17 Question 8 + + + + + + + + + + + HAMD-17 Question 9 + + + + + + + + + + + HAMD-17 Question 10 + + + + + + + + + + + HAMD-17 Question 11 + + + + + + + + + + + HAMD-17 Question 12 + + + + + + + + + + + HAMD-17 Question 13 + + + + + + + + + + + HAMD-17 Question 14 + + + + + + + + + + + HAMD-17 Question 15 + + + + + + + + + + + HAMD-17 Question 16A + + + + + + + + + + + HAMD-17 Question 16B + + + + + + + + + + + HAMD-17 Question 17 + + + + + + + + + + + HAMD-17 Question 18 + + + + + + + + + + HAMD-17 Question 1 Standardized + + + + + + + + + + + HAMD-17 Question 2 Standardized + + + + + + + + + + + HAMD-17 Question 3 Standardized + + + + + + + + + + + HAMD-17 Question 4 Standardized + + + + + + + + + + + HAMD-17 Question 5 Standardized + + + + + + + + + + + HAMD-17 Question 6 Standardized + + + + + + + + + + + HAMD-17 Question 7 Standardized + + + + + + + + + + + HAMD-17 Question 8 Standardized + + + + + + + + + + + HAMD-17 Question 9 Standardized + + + + + + + + + + + HAMD-17 Question 10 Standardized + + + + + + + + + + + HAMD-17 Question 11 Standardized + + + + + + + + + + + HAMD-17 Question 12 Standardized + + + + + + + + + + + HAMD-17 Question 13 Standardized + + + + + + + + + + + HAMD-17 Question 14 Standardized + + + + + + + + + + + HAMD-17 Question 15 Standardized + + + + + + + + + + + HAMD-17 Question 16A Standardized + + + + + + + + + + + HAMD-17 Question 16B Standardized + + + + + + + + + + + HAMD-17 Question 17 Standardized + + + + + + + + + + + HAMD-17 Question 18 Standardized + + + + + + + + + + Race 1 + + + + + + + + + + + Race 2 + + + + + + + + + + + Race 3 + + + + + + + + + + + Race 4 + + + + + + + + + + + Race 5 + + + + + + + + + + + Reason for Occur Value + + + + + + + + + + Clinically Significant + + + + + + + + + + + Clinically Significant + + + + + + + + + + + Trial Summary Yes No Responses + + + + + + + Planned Maximum Age of Subjects + + + + + + Trial Summary Date Responses + + + + + + Dose Form + + + + + + + Dosing Frequency + + + + + + + Dose Units + + + + + + + Planned Country of Investigational Sites + + + + + + + Trial Disease/Condition Indication + + + + + + + Intervention Model + + + + + + + Intervention Type + + + + + + + Trial Length + + + + + + Trial Primary Objective + + + + + + Trial Secondary Objective + + + + + + Primary Outcome Measure + + + + + + Pharmacologic Class + + + + + + Randomization Quotient + + + + + + Registry Identifier + + + + + + Route of Administration + + + + + + + SDTM IG Version + + + + + + Sex of Participants + + + + + + + Clinical Study Sponsor + + + + + + Study Stop Rules + + + + + + Study Type + + + + + + + Trial Blinding Schema + + + + + + + Control Type + + + + + + + Diagnosis Group + + + + + + + Trial Intent Type + + + + + + + Trial Title + + + + + + Trial Phase Classification + + + + + + + Investigational Therapy or Treatment + + + + + + Trial Type + + + + + + + Blood Pressure + + + + + + + + + + Height + + + + + + + + + + Pulse Rate + + + + + + + + + + Temperature + + + + + + + + + + Weight + + + + + + + + + + Blood Pressure Units + + + + + + + + + + + Height Units + + + + + + + + + + + Pulse Rate Units + + + + + + + + + + + Temperature Units + + + + + + + + + + + Weight Units + + + + + + + + + + + Blood Pressure Units Std + + + + + + Height Units Std + + + + + + Pulse Rate Units Std + + + + + + Temperature Units Std + + + + + + Weight Units Std + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dose Increased + + + + + + Dose Not Changed + + + + + + Dose Reduced + + + + + + Drug Interrupted + + + + + + Drug Withdrawn + + + + + + Not Applicable + + + + + + Unknown + + + + + + + + + Related + + + + + Unlikely Related + + + + + Possibly Related + + + + + Not Related + + + + + + + Mild + + + + + + Moderate + + + + + + Severe + + + + + + + + + Years + + + + + + + + + + + + + + Placebo + + + + + Zanomaline Low Dose (54 mg) + + + + + Zanomaline High Dose (81 mg) + + + + + + + Trial Screen Failure + + + + + + + + + AVLT-REY - List A Word 1 + + + + + + AVLT-REY - List A Word 2 + + + + + + AVLT-REY - List A Word 3 + + + + + + AVLT-REY - List A Word 4 + + + + + + AVLT-REY - List A Word 5 + + + + + + AVLT-REY - List A Word 6 + + + + + + AVLT-REY - List A Word 7 + + + + + + AVLT-REY - List A Word 8 + + + + + + AVLT-REY - List A Word 9 + + + + + + AVLT-REY - List A Word 10 + + + + + + AVLT-REY - List A Word 11 + + + + + + AVLT-REY - List A Word 12 + + + + + + AVLT-REY - List A Word 13 + + + + + + AVLT-REY - List A Word 14 + + + + + + AVLT-REY - List A Word 15 + + + + + + AVLT-REY - List A Total + + + + + + AVLT-REY - List A Intrusions + + + + + + AVLT-REY - List B Word 1 + + + + + + AVLT-REY - List B Word 2 + + + + + + AVLT-REY - List B Word 3 + + + + + + AVLT-REY - List B Word 4 + + + + + + AVLT-REY - List B Word 5 + + + + + + AVLT-REY - List B Word 6 + + + + + + AVLT-REY - List B Word 7 + + + + + + AVLT-REY - List B Word 8 + + + + + + AVLT-REY - List B Word 9 + + + + + + AVLT-REY - List B Word 10 + + + + + + AVLT-REY - List B Word 11 + + + + + + AVLT-REY - List B Word 12 + + + + + + AVLT-REY - List B Word 13 + + + + + + AVLT-REY - List B Word 14 + + + + + + AVLT-REY - List B Word 15 + + + + + + AVLT-REY - List B Total + + + + + + AVLT-REY - List B Intrusions + + + + + + + + + Recalled + + + + + Not Recalled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Primary Cause of Death + + + + + + + + + + + + + + + + + + Device Type + + + + + + Serial Number + + + + + + + + + Adverse Events + + + + + + + + + Concomitant/Prior Medications + + + + + + + + + Death Details + + + + + + + + + Device Identifiers + + + + + + + + + Demographics + + + + + + + + + Disposition + + + + + + + + + Exposure as Collected + + + + + + + + + Exposure + + + + + + + + + Findings About Events or Interventions + + + + + + + + + Functional Tests + + + + + + + + + Inclusion/Exclusion Criteria Not Met + + + + + + + + + Laboratory Test Results + + + + + + + + + Medical History + + + + + + + + + Nervous Sysytem Findings + + + + + + + + + Ophthalmic Examinations + + + + + + + + + Questionnaires + + + + + + + + + Disease Response and Clin Classification + + + + + + + + + Subject Elements + + + + + + + + + Subject Visits + + + + + + + + + Trial Arms + + + + + + + + + Trial Elements + + + + + + + + + Trial Inclusion + + + + + + + + + Trial Summary + + + + + + + + + Trial Visits + + + + + + + + + Vital Signs + + + + + + + + + Disposition Event + + + + + + Protocol Milestone + + + + + + + + + Study Treatment + + + + + Study Participation + + + + + + + + + + + + + + Ongoing + + + + + + + + + Screening + + + + + + Treatment + + + + + + + + + Zanomaline 81 mg + + + + + Zanomaline 54 mg + + + + + Placebo + + + + + Screening + + + + + Zanomaline 54 mg Titration + + + + + + + Hispanic or Latino + + + + + + Not Hispanic or Latino + + + + + + + + + Placebo + + + + + Zanomaline + + + + + + + Injection Site Reaction + + + + + + + Erythema + + + + + Pain + + + + + Induration + + + + + Pruritus + + + + + Edema + + + + + + + No + + + + + + Yes + + + + + + + + + Mild + + + + + + Moderate + + + + + + Severe + + + + + + + + + + + + + Occurrence Indicator + + + + + Severity/Intensity + + + + + + + Daily + + + + + + As Needed + + + + + + Twice Daily + + + + + + Every Four Hours + + + + + + Four Times Daily + + + + + + Every Six Hours + + + + + + + + + Daily + + + + + + + + + Injectable Dosage Form + + + + + + + + + Rey Auditory Verbal Learning Functional Test + + + + + + + + + + + + + + + + Absent. + + + + + These feeling states indicated only on questioning. + + + + + These feeling states spontaneously reported verbally. + + + + + Communicates feeling states non-verbally, i.e. through facial expression, posture, voice and tendency to weep. + + + + + Patient reports virtually only these feeling states in his/her spontaneous verbal and non-verbal communication. + + + + + + + + + + + + + + Absent. + + + + + Self reproach, feels he/she has let people down. + + + + + Ideas of guilt or rumination over past errors or sinful deeds. + + + + + Present illness is a punishment. Delusions of guilt. + + + + + Hears accusatory or denunciatory voices and/or experiences threatening visual hallucinations. + + + + + + + + + + + + + + Absent. + + + + + Feels life is not worth living. + + + + + Wishes he/she were dead or any thoughts of possible death to self. + + + + + Ideas or gestures of suicide. + + + + + Attempts at suicide (any serious attempt rate 4). + + + + + + + + + + + + No difficulty falling asleep. + + + + + Complains of occasional difficulty falling asleep, i.e. more than 1/2 hour + + + + + Complains of nightly difficulty falling asleep. + + + + + + + + + + + + No difficulty. + + + + + Patient complains of being restless and disturbed during the night. + + + + + Waking during the night - any getting out of bed rates 2 (except for purposes of voiding). + + + + + + + + + + + + No difficulty. + + + + + Waking in early hours of the morning but goes back to sleep. + + + + + Unable to fall asleep again if he/she gets out of bed. + + + + + + + + + + + + + + No difficulty. + + + + + Thoughts and feelings of incapacity, fatigue or weakness related to activities, work or hobbies. + + + + + Loss of interest in activity, hobbies or work - either directly reported by the patient or indirect in listlessness, indecision and vacillation (feels he/she has to push self to work or activities). + + + + + Decrease in actual time spent in activities or decrease in productivity. Rate 3 if the patient does not spend at least three hours a day in activities (job or hobbies) excluding routine chores. + + + + + Stopped working because of present illness. Rate 4 if patient engages in no activities except routine chores, or if patient fails to perform routine chores unassisted. + + + + + + + + + + + + + + Normal speech and thought. + + + + + Slight retardation during the interview. + + + + + Obvious retardation during the interview. + + + + + Interview difficult. + + + + + Complete stupor. + + + + + + + + + + + + + + None. + + + + + Fidgetiness. + + + + + Playing with hands, hair, etc. + + + + + Moving about, cannot sit still. + + + + + Hand wringing, nail biting, hair-pulling, biting of lips. + + + + + + + + + + + + + + No difficulty. + + + + + Subjective tension and irritability. + + + + + Worrying about minor matters. + + + + + Apprehensive attitude apparent in face or speech. + + + + + Fears expressed without questioning. + + + + + + + + + + + + + + Absent. + + + + + Mild. + + + + + Moderate. + + + + + Severe. + + + + + Incapacitating. + + + + + + + + + + + + None. + + + + + Loss of appetite but eating without staff encouragement. Heavy feelings in abdomen. + + + + + Difficulty eating without staff urging. Requests or requires laxatives or medication for bowels or medication for gastro-intestinal symptoms. + + + + + + + + + + + + None. + + + + + Heaviness in limbs, back or head. Backaches, headaches, muscle aches. Loss of energy and fatigability. + + + + + Any clear-cut symptom rates 2. + + + + + + + + + + + + Absent. + + + + + Mild. + + + + + Severe. + + + + + + + + + + + + + + Not present. + + + + + Self-absorption (bodily). + + + + + Preoccupation with health. + + + + + Frequent complaints, requests for help, etc. + + + + + Hypochondriacal delusions. + + + + + + + + + + + + + No weight loss. + + + + + Probable weight loss associated with present illness. + + + + + Definite (according to patient) weight loss. + + + + + Not assessed. + + + + + + + + + + + + + Less than 1 lb weight loss in week. + + + + + Greater than 1 lb weight loss within week. + + + + + Greater than 2 lb weight loss in week. + + + + + Not assessed. + + + + + + + + + + + + Acknowledges being depressed and ill. + + + + + Acknowledges illness but attributes cause to bad food, climate, overwork, virus, need for rest, etc. + + + + + Denies being ill at all. + + + + + + + HAMD1-Depressed Mood + + + + + + HAMD1-Feelings of Guilt + + + + + + HAMD1-Suicide + + + + + + HAMD1-Insomnia Early - Early Night + + + + + + HAMD1-Insomnia Middle - Middle Night + + + + + + HAMD1-Insomnia Early Hours - Morning + + + + + + HAMD1-Work and Activities + + + + + + HAMD1-Retardation + + + + + + HAMD1-Agitation + + + + + + HAMD1-Anxiety Psychic + + + + + + HAMD1-Anxiety Somatic + + + + + + HAMD1-Somatic Symptoms GI + + + + + + HAMD1-General Somatic Symptoms + + + + + + HAMD1-Genital Symptoms + + + + + + HAMD1-Hypochondriasis + + + + + + HAMD1-Loss of WT According to Patient + + + + + + HAMD1-Loss of WT According to WK Meas + + + + + + HAMD1-Insight + + + + + + HAMD1-Total Score + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Exclusion + + + + + + Inclusion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Males and postmenopausal females at least 50 years of age. + + + + + Diagnosis of probable AD as defined by NINCDS and the ADRDA guidelines. + + + + + MMSE score of 10 to 23. + + + + + Modified Hachinski Ischemic Scale score of <= 4. + + + + + CNS imaging (CT scan or MRI of brain) compatible with AD within past 1 year. (See Protocol for incompatible findings.) + + + + + Investigator has obtained informed consent signed by the patient (and/or legal representative) and by the caregiver. + + + + + Geographic proximity to investigator's site that allows adequate follow-up. + + + + + Caregiver will monitor administration of prescribed medications, and will be responsible for the overall care of the patient at home. + + + + + Persons who have previously completed or withdrawn from this study or any other investigating xanomeline TTS or the oral formulation of Zanomaline. + + + + + Use of any investigational agent or approved Alzheimer's therapeutic medication within 30 days prior to enrollment into the study. + + + + + Serious illness which required hospitalization within 3 months of screening. + + + + + Diagnosis of serious neurological conditions + + + + + Episode of depression meeting DSM-IV criteria within 3 months of screening. + + + + + A history within the last 5 years of the following: a) Schizophrenia b) Bipolar Disease c) Ethanol or psychoactive drug abuse or dependence. + + + + + A history of syncope within the last 5 years. + + + + + Evidence from ECG recording at screening of any of the following conditions: a) Left bundle branch block b) Bradycardia <50 beats per minute c) Sinus pauses >2 seconds (See Protocol for Remainder) + + + + + A history within the last 5 years of a serious cardiovascular disorder, including a) Clinically significant arrhythmia (See Protocol for Remainder) + + + + + A history within the last 5 years of a serious gastrointestinal disorder, including +a) Chronic peptic/duodenal/gastric/esophageal ulcer that are untreated or refractory to treatment(See Protocol) + + + + + A history within the last 5 years of a serious endocrine disorder, including +a) Uncontrolled Insulin Dependent Diabetes Mellitus (IDDM) (See Protocol for other excluded disorders) + + + + + A history within the last 5 years of a serious respiratory disorder, including a) Asthma with bronchospasm refractory to treatment b) Decompensated chronic obstructive pulmonary disease. + + + + + A history within the last 5 years of a serious genitourinary disorder, including a) Renal failure b) Uncontrolled urinary retention + + + + + A history within the last 5 years of a serious rheumatologic disorder, including a) Lupus b) Temporal arteritis c) Severe rheumatoid arthritis + + + + + A known history of human immunodeficiency virus (HIV) within the last 5 years. + + + + + A history within the last 5 years of a serious infectious disease including a) Neurosyphilis b) Meningitis c) Encephalitis + + + + + A history within the last 5 years of a primary or recurrent malignant disease (See Exceptions in Protocol). + + + + + Visual, hearing, or communication disabilities impairing the ability to participate in the study; (for example, inability to speak or understand English, illiteracy). + + + + + Laboratory test values exceeding the Reference Range III for the patient's age in any of the following analytes: creatinine, total bilirubin, SGOT, SGPT, (See Protocol for Additional Analytes) + + + + + Central laboratory test values below reference range for folate, and vitamin B12, and outside reference range for thyroid function tests. + + + + + Positive syphilis screening with confirmatory testing. + + + + + Central laboratory test value above reference range for glycosylated hemoglobin (A1C) (insulin dependent diabetes mellitus patients only). + + + + + Treatment with medications within 1 month prior to enrollment a) Anticonvulsants b) Alpha receptor blockers c) Calcium channel blockers that are CNS active + + + + + Diagnosis of serious neurological conditions (Amend 1) + + + + + Treatment with medications within 1 month prior to enrollment a) Anticonvulsants b) Alpha receptor blockers c) Calcium channel blockers that are CNS active (Amend 1) + + + + + + + Parallel + + + + + + + + + Drug + + + + + + + + + Left + + + + + + Right + + + + + + + + + Chemistry + + + + + Hematology + + + + + Urinalysis + + + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Albumin Measurement + + + + + + Alkaline Phosphatase Measurement + + + + + + Alanine Aminotransferase Measurement + + + + + + Anisocyte Measurement + + + + + + Aspartate Aminotransferase Measurement + + + + + + Total Basophil Count + + + + + + Total Bilirubin Measurement + + + + + + Calcium Measurement + + + + + + Cholesterol Measurement + + + + + + Creatine Kinase Measurement + + + + + + Chloride Measurement + + + + + + Color Assessment + + + + + + Creatinine Measurement + + + + + + Eosinophil Count + + + + + + Gamma Glutamyl Transpeptidase Measurement + + + + + + Glucose Measurement + + + + + + Hematocrit Measurement + + + + + + Hemoglobin Measurement + + + + + + Potassium Measurement + + + + + + Ketone Measurement + + + + + + Lymphocyte Count + + + + + + Macrocyte Count + + + + + + Erythrocyte Mean Corpuscular Hemoglobin + + + + + + Erythrocyte Mean Corpuscular Hemoglobin Concentration + + + + + + Erythrocyte Mean Corpuscular Volume + + + + + + Monocyte Count + + + + + + pH + + + + + + Phosphate Measurement + + + + + + Platelet Count + + + + + + Poikilocyte Measurement + + + + + + Total Protein Measurement + + + + + + Erythrocyte Count + + + + + + Sodium Measurement + + + + + + Specific Gravity + + + + + + Thyrotropin Measurement + + + + + + Urate Measurement + + + + + + Urea Nitrogen Measurement + + + + + + Urobilinogen Measurement + + + + + + Vitamin B12 Measurement + + + + + + Leukocyte Count + + + + + + + + + + + + + + + Conjunctiva + + + + + + Eye + + + + + + Anterior Chamber of the Eye + + + + + + Iris + + + + + + Cornea + + + + + + + + + Ear + + + + + + Oral Cavity + + + + + + + + + Symptom Onset + + + + + + + + + Alzheimer's Disease + + + + + + + Adverse Event + + + + + + Completed + + + + + + Death + + + + + + Lack of Efficacy + + + + + + Lost to Follow-Up + + + + + + Other + + + + + + Physician Decision + + + + + + Pregnancy + + + + + + Protocol Deviation + + + + + + Screen Failure + + + + + + Study Terminated By Sponsor + + + + + + Withdrawal By Parent/Guardian + + + + + + Withdrawal By Subject + + + + + + + + + Not Done + + + + + + + + + Abnormal + + + + + + Normal + + + + + + + + + Abnormal + + + + + + High + + + + + + Low + + + + + + Normal + + + + + + + + + + + + + Interpretation + + + + + + + + No + + + + + + Yes + + + + + + + + + Yes + + + + + + + + + Right Eye + + + + + + Left Eye + + + + + + + + + Slit-lamp Examination + + + + + + + + + + + + + + + + Abnormality Detail + + + + + Interpretation + + + + + + + + + Fatal + + + + + + Not Recovered/Not Resolved + + + + + + Recovered/Resolved + + + + + + Recovered/Resolved With Sequelae + + + + + + Recovering/Resolving + + + + + + Unknown + + + + + + + + + PHQ01-Little Interest/Pleasure in Things + + + + + + PHQ01-Feeling Down Depressed or Hopeless + + + + + + PHQ01-Trouble Falling or Staying Asleep + + + + + + PHQ01-Feeling Tired or Little Energy + + + + + + PHQ01-Poor Appetite or Overeating + + + + + + PHQ01-Feeling Bad About Yourself + + + + + + PHQ01-Trouble Concentrating on Things + + + + + + PHQ01-Moving Slowly or Fidgety/Restless + + + + + + PHQ01-Thoughts You Be Better Off Dead + + + + + + PHQ01-Difficult to Work/Take Care Things + + + + + + PHQ01-Total Score + + + + + + + + + + + + + + + + + + + + + Not at all + + + + + Several days + + + + + More than half the days + + + + + Nearly every day + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Standing + + + + + + Supine + + + + + + + + + Informed Consent + + + + + + + + + Patient Health Questionnaire - 9 Item + + + + + + + + + Satisfaction With Life Scale Questionnaire + + + + + + + + + American Indian Or Alaska Native + + + + + + Asian + + + + + + Black Or African American + + + + + + Native Hawaiian Or Other Pacific Islander + + + + + + White + + + + + + + + + Multiple + + + + + + + Adverse Events + + + + + + Disposition + + + + + + Death Details + + + + + + Findings About Events or Interventions + + + + + + + + + Many + + + + + + One + + + + + + + + + Oral + + + + + + Topical + + + + + + Intravenous + + + + + + Nasal + + + + + + Inhalation Route of Administration + + + + + + Transdermal + + + + + + + + + Subcutaneous Route of Administration + + + + + + + + + Hamilton Depression Rating Scale 17 Item Clinical Classification + + + + + + + + + Female + + + + + + Male + + + + + + + + + + + + + + + + + Interventional + + + + + + + + + SWLS01-Have Gotten Important Things + + + + + + SWLS01-I Am Satisfied with My Life + + + + + + SWLS01-Live Life Over Change Nothing + + + + + + SWLS01-My Life Conditions are Excellent + + + + + + SWLS01-My Life is Close to Ideal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Strongly disagree + + + + + Disagree + + + + + Slightly disagree + + + + + Neither agree nor disagree + + + + + Slightly agree + + + + + Agree + + + + + Strongly agree + + + + + + + Double Blind + + + + + + + + + Placebo + + + + + + + + + Treatment + + + + + + + + + Phase II Trial + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Actual Subject Number + + + + + + Adaptive Study Design Indicator + + + + + + Test Product Added to Existing Treatment + + + + + + Planned Maximum Age of Subjects + + + + + + Planned Minimum Age of Subjects + + + + + + Data Cutoff Date Description + + + + + + Data Cutoff Date + + + + + + Dose + + + + + + Pharmaceutical Dosage Form + + + + + + Dose Frequency + + + + + + Dosage Form Unit + + + + + + Planned Country of Investigational Site + + + + + + Healthy Subject Indicator + + + + + + Trial Indication + + + + + + Intervention Model + + + + + + Intervention Type + + + + + + Trial Length + + + + + + Planned Number of Arms + + + + + + Trial Primary Objective + + + + + + Trial Secondary Objective + + + + + + Primary Outcome Measure + + + + + + Secondary Outcome Measure + + + + + + Pharmacological Class of Investigational Therapy + + + + + + Planned Subject Number + + + + + + Randomization + + + + + + Randomization Quotient + + + + + + Clinical Trial Registry Identifier + + + + + + Route of Administration + + + + + + Study Data Tabulation Model Implementation Guide Version + + + + + + Study Data Tabulation Model Version + + + + + + Clinical Study End Date + + + + + + Sex of Study Group + + + + + + Clinical Study Sponsor + + + + + + Study Start Date + + + + + + Study Stop Rule + + + + + + Study Type + + + + + + Trial Blinding Schema + + + + + + Control Type + + + + + + Diagnosis Group + + + + + + Clinical Study by Intent + + + + + + Trial Title + + + + + + Trial Phase + + + + + + Protocol Agent + + + + + + Trial Type + + + + + + + + + Efficacy + + + + + + Pharmacokinetic + + + + + + Safety + + + + + + + + + Milligram + + + + + + Nanogram + + + + + + Tablet + + + + + + + + + Milliliter + + + + + + + + + Gram per Liter + + + + + + + + + Milligram + + + + + + + + + Million per Microliter + + + + + + + + + Billion per Liter + + + + + + + + + Percentage + + + + + + + + + Unit per Liter + + + + + + + + + Femtoliter + + + + + + + + + Femtomole + + + + + + + + + Femtomole + + + + + + + + + Gram per Deciliter + + + + + + + + + Milliequivalent Per Liter + + + + + + + + + Microinternational Unit per Milliliter + + + + + + + + + Microunit per Milliliter + + + + + + + + + Milligram per Deciliter + + + + + + + + + Millimole per Liter + + + + + + + + + Nanogram per Liter + + + + + + + + + Picogram + + + + + + + + + Picomole per Liter + + + + + + + + + Micromole per Liter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Diastolic Blood Pressure + + + + + + Pulse Rate + + + + + + Height + + + + + + Systolic Blood Pressure + + + + + + Temperature + + + + + + Weight + + + + + + + + + Millimeter of Mercury + + + + + + + + + Millimeter of Mercury + + + + + + + + + Inch + + + + + + + + + Centimeter + + + + + + + + + Beats per Minute + + + + + + + + + Beats per Minute + + + + + + + + + Degree Fahrenheit + + + + + + + + + Degree Celsius + + + + + + + + + Pound + + + + + + + + + Kilogram + + + + + + + + + + + + + + + + + + + + + + + + + + If AEENRTPT is populated, AEENTPT is DM.RFPENDTC for the subject. + + + + + If CMENRTPT is populated, CMENTPT is DM.RFPENDTC for the subject. + + + + + Study day relative to RFSTDTC. Date - RFSTDTC + 1 if on or after RFSTDTC. Date - RFSTDTC if date precedes RFSTDTC. + + + + + Starts at "1" for first device identifier and increments by one for each DIPARM + + + + + If DTHDTC is populated then DTHFL='Y' + + + + + EPOCH from SE where date >= SESTDTC and date < SEENDTC + + + + + EXDOSE = ECDOSE * ECPSTRG expressed in mg. + + + + + If FTSTRESC is numeric then FTSTRESN=FTSTRESC in numeric format, else null. + + + + + If IECAT=INCLUSION then IEORRES=N, else if IECAT=EXCLUSION then IEORRES=Y + + + + + LBSTRESC is equal to LBORRES or the value in standard units if a conversion is necessary. + + + + + Set to "Y" for last record with non-null original result on or before the first dose date (RFXSTDTC). Null otherwise. + + + + + If QSORRES="Not at all" then 0 +If QSORRES="Several days" then 1 +If QSORRES="More than half the days" then 2 +If QSORRES="Nearly every day" then 3 + + + + + QSSTRESC=QSORRES + + + + + If QSORRES="Strongly disagree" then 1 +If QSORRES="Disagree" then 2 +If QSORRES="Slightly disagree" then 3 +If QSORRES="Neither agree nor disagree" then 4 +If QSORRES="Slightly agree" then 5 +If QSORRES="Agree" then 6 +If QSORRES="Strongly agree" then 7 + + + + + If QSSTRESC is numeric then QSSTRESN=QSSTRESC in numeric format, else null. + + + + + The Date of Study Completion or Early Termination. Null for screen failures. + + + + + The latest date of assessment for the subject as determined by the End of Study Form, any scheduled assessments, Adverse Events, or Concomitant Medications. + + + + + The first date/time of study drug. Null for screen failures. + + + + + The last date/time of study drug administration. Null for subjects with no treatment data. + + + + + The first date/time of study drug administration. Null for subjects with no treatment data. + + + + + RSSTRESC is the corresponding numeric value of RSORRES according the values shown on the HAMD-17 CRF page. + + + + + SEENDTC is set to the start of the next Element, or RFPENDTC for the last Element. + + + + + Unique sequence number within a subject, restarting at 1 for every subject, applied to sorted data. + + + + + SESTDTC if set to the --DTC for that subject which exists in the data for the defined start of the Element, such as DSSTDTC when DSDECOD=INFORMED CONSENT OBTAINED for Screening Elements or min(EXSTDTC) for Dosing Elements. + + + + + If --STRESC represents a numeric value then --STRESN is the numeric version of --STRESC, else null. "--" represents the domain code. + + + + + For each scheduled visit, SVENDTC = the last (max) date associated with a subject for that visit. For unplanned visits, SVENDTC is the date of the visit. + + + + + For each scheduled visit, SVSTDTC = the first (min) date associated with a subject for that visit. For unplanned visits, SVSTDTC is the date of the visit. + + + + + Unique sequence number within each TSPARM, restarting at 1 for per TSPARM, applied to sorted data. + + + + + Data collected in conventional units (i.e. F, lbs, inches) is converted using standard conversion factors to standard units (C, kg, cm). + + + + + + + + + + + Even though the variable is 'Assigned' an annotation has been added to page 23 to clarify the assignment. + + + + + Coding variables are not populated due to the proprietary coding dictionary, but the variables are included as they are Expected or Required. + + + + + Coding variables are not populated due to the proprietary coding dictionary, but the variables are included as they are Expected or Required. Note CDISC Conformance Rule CG0014 would fire for this variable due to the decision not to populate coding variables. + + + + + Subject CDISC003 had an AE of Epistaxis on 2013-09-30 with AESER set to 'Y' without any of the individual serious qualifiers set to 'Y' also. The site was queried several times but the data were not updated. Note Conformance Rule CG0041 would fire for this subject. + + + + + If the CM is not taken for a 'Primary Study Condition' then CMINDC would be 'Prophylaxis or Non-therapeutic use' + + + + + Since no collected data was subjective then QEVAL was not populated. It is an 'Expected' variable and so is included. + + + + + Since no subjects had more than 3 Races, RACE4 was not used. + + + + + Since no subjects had more than 3 Races, RACE5 was not used. + + + + + Variable is Assigned but there are annotations to help understand the data and so references to the proper pages are included + + + + + DataType is 'partialDatetime' instead of 'datetime' since datetime values are planned to be collected without seconds for this study. + + + + + All values are null as the findings are not visit based. The variable is Expected and so is included. + + + + + The FA domain contains Findings About Injection Site Reaction Adverse Events + + + + + IEDY is needed if IEDTC is included. Note RFSTDTC is not populated for not randomized subjects then IEDY could not be populated in those cases. + + + + + Please see Appendix 1 of the cSDRG for complete versions of IETESTCD and IETEST. + + + + + Standard's Conformance Notes: +1) The SDTM v1.7/SDTMIG v3.3 datasets were evaluated manually and programmatically by the CDISC SDS MSG Team. At the completion of the SDTM-MSG v2.0, the CDISC SDTM v1.7/SDTMIG v3.3 conformance rules were recently published, but not available by any validation tools to validate. +2) The Define-XML document was evaluated manually and programmatically by the CDISC SDS MSG Team. At the completion of the SDTM-MSG v2.0, the CDISC +Define-XML v2.1 conformance rules were not published, nor available by any validation tools to validate. Please ensure that any official regulatory submission of an Define-XML v2.1 document and accompanying data is done in accordance to the respective regulatory health authorities requirements/guidance. + + + + + Per protocol, electroencephalograms are only performed after such an event were to occur. No subjects within the trial had an occurrence of an electroencephalogram event. Therefore, no data exists for the NV dataset and as such was not submitted. + + + + + Per protocol, electroencephalograms are only performed after such an event were to occur. No subjects within the trial had an occurrence of an electroencephalogram event. Therefore, no data exists for the NV dataset and as such SUPPNV was not submitted. + + + + + No subjects within the trial had an ophthalmic examination of clinical significance to report. Therefore, no data exists for the SUPPOE dataset and as such was not submitted. + + + + + QSPH contains the PATIENT HEALTH QUESTIONNAIRE-9 (PHQ-9) questionnaire data. + + + + + QSSL contains the SATISFACTION WITH LIFE SURVEY (SWLS) questionnaire data. + + + + + Study Data Tabulation Model Implementation Guide: Human Clinical Trials Version 3.3 + + + + + Study Data Tabulation Model Implementation Guide for Medical Devices Version 1.0 + + + + + This was the latest release of CDISC CT available when this sample submission was completed. + + + + + This was the CDISC CT Package associated to the CDISC Define-XML Specification Version 2.1 when this sample submission was completed. + + + + + All vital signs were performed as expected, so VSSTAT was never populated. The variable is included as it was possible to populate it in this study. + + + + + + + + + + Annotated CRF + + + + Reviewers Guide + + + + + + + + + + diff --git a/tests/resources/CoreIssue1443/Rule.yml b/tests/resources/CoreIssue1443/Rule.yml index eaf3d07e4..9cc6c8254 100644 --- a/tests/resources/CoreIssue1443/Rule.yml +++ b/tests/resources/CoreIssue1443/Rule.yml @@ -1,43 +1,125 @@ Authorities: - Organization: CDISC Standards: - - Name: SDTMIG + - Name: SENDIG References: - Citations: - - Cited Guidance: xxx. - Document: IG v3.4 - Item: Item 3.b. - Section: '2.6' - Origin: SDTM and SDTMIG Conformance Rules + - Cited Guidance: If a controlled terminology codelist exists for a variable in a + SEND domain, the name of the codelist will be populated in the + Controlled Terms, Codelist, or Format column of the domain + model to indicate that a distinct set of controlled values + exist and is expected to be used. + Document: IG v3.0 + Item: Specification + Section: 4.3.1 + Origin: SEND Conformance Rules Rule Identifier: - Id: CG0011 + Id: SEND49 Version: '1' - Version: '2.0' - Version: '3.4' + Version: '5.0' + Version: '3.0' + - Name: SENDIG + References: + - Citations: + - Cited Guidance: If a controlled terminology codelist exists for a variable in a + SEND domain, the name of the codelist will be populated in the + Controlled Terms, Codelist, or Format column of the domain + model to indicate that a distinct set of controlled values + exist and is expected to be used. + Document: IG v3.1 + Item: Specification + Section: 4.3.1 + Origin: SEND Conformance Rules + Rule Identifier: + Id: SEND49 + Version: '1' + Version: '5.0' + Version: '3.1' + - Name: SENDIG + References: + - Citations: + - Cited Guidance: If a controlled terminology codelist exists for a variable in a + SEND domain, the name of the codelist will be populated in the + Controlled Terms, Codelist, or Format column of the domain + model to indicate that a distinct set of controlled values + exist and is expected to be used. + Document: IG v3.1.1 + Item: Specification + Section: 4.3.1 + Origin: SEND Conformance Rules + Rule Identifier: + Id: SEND49 + Version: '1' + Version: '5.0' + Version: '3.1' + - Name: SENDIG-GENETOX + References: + - Citations: + - Cited Guidance: If a controlled terminology codelist exists for a variable in a + SEND domain, the name of the codelist will be populated in the + Controlled Terms, Codelist, or Format column of the domain + model to indicate that a distinct set of controlled values + exist and is expected to be used. + Document: IG v3.1.1 + Item: Specification + Section: 4.3.1 + Origin: SEND Conformance Rules + Rule Identifier: + Id: SEND49 + Version: '1' + Version: '5.0' + Version: '1.0' + - Name: SENDIG-DART + References: + - Citations: + - Cited Guidance: If a controlled terminology codelist exists for a variable in a + SEND domain, the name of the codelist will be populated in the + Controlled Terms, Codelist, or Format column of the domain + model to indicate that a distinct set of controlled values + exist and is expected to be used. + Document: IG v3.1.0 + Item: Specification + Section: 4.3.1 + Origin: SEND Conformance Rules + Rule Identifier: + Id: SEND49 + Version: '1' + Version: '5.0' + Version: '1.1' + - Name: SENDIG-DART + References: + - Citations: + - Cited Guidance: If a controlled terminology codelist exists for a variable in a + SEND domain, the name of the codelist will be populated in the + Controlled Terms, Codelist, or Format column of the domain + model to indicate that a distinct set of controlled values + exist and is expected to be used. + Document: IG v3.1.1 + Item: Specification + Section: 4.3.1 + Origin: SEND Conformance Rules + Rule Identifier: + Id: SEND49 + Version: '1' + Version: '5.0' + Version: '1.2' Check: - any: - - all: - # Case 1: Variable lacks variable-level codelist - - name: define_variable_ccode - operator: empty - # BUT has VLM items with codelists that match library - - name: define_vlm_has_codelist_any - operator: equal_to - value: true - - name: define_vlm_ccode_matches_library_any - operator: equal_to - value: true + all: + - name: define_variable_ccode + operator: empty + - name: define_vlm_has_codelist_any + operator: equal_to + value: true Core: - Id: CDISC.SDTMIG.CG0011 + Id: CDISC.SENDIG.49 Status: Draft Version: '1' -Description: Variable has no variable-level codelist but has Value Level Metadata (VLM) with codelists that match the library standard. This indicates potential metadata inconsistency where codelist is defined at VLM level rather than variable level. +Description: 'For a variable identified in the SENDIG as being subject to CDISC + published Controlled Terminology, the Codelist listed in the Define-XML + document must properly reference the Controlled Terminology Codelist used.' Executability: Fully Executable Outcome: - Message: - Variable {{variable_name}} lacks variable-level CodeList but has VLM items - with CodeList matching library standard {{library_variable_ccode}}. - Consider defining codelist at variable level. + Message: 'As a controlled terminology codelist exists for the variable in the SEND domain, the codelist must be referenced for the variable in the define.xml' Output Variables: - variable_name - define_variable_ccode @@ -49,9 +131,8 @@ Rule Type: Variable Metadata Check against Define XML and Library Metadata Scope: Domains: Include: - - VS + - ALL Classes: Include: - - STUDY REFERENCE + - ALL Sensitivity: Record - \ No newline at end of file diff --git a/tests/resources/CoreIssue1443/unit-test-coreid-SENDIG_49.xlsx b/tests/resources/CoreIssue1443/unit-test-coreid-SENDIG_49.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..53fe96d5696240296967a2b6d07a8e28c12d97ec GIT binary patch literal 13788 zcma)D1yo#1lg5I(1ed`*I0T2mU4sOd;O+_T?(Xgog1fr~cL@Y{*8n@od%O8x{(tu@ z=ge(-&eV5Hy6SdU)m4y&gu(;^1A_&9NWj2N1#K3=!N6kRz`!s--@FIfSUVb9JL;;q z*%~`&GrC$?jwQ-kFEgPA-0}rCpIMv=%2mQ7cP!@Vne|= zB;E!h)#9V2ZgAS%QKM_FT{n-^fAgy@G~(>@HP)l0OE8nVdE91x>96+gmYCFlq*w;( zEv_C+Ul^Z~7>T4QRKK3|*yUAWFhzqu>{KYM*FnfvTeqbujWG3IXMC;eW{l+9MG%B% zS=Sn*+3J+ccZHeBeLfL05oNZSt;({YRYdC(zx$pnO68&h{#DHP^a)yQ{%NTGJa`}_ zL-bC4jaEMM`}tA`vocOu385ct*gPy;fU3C@3BmoYW&jbD4k4SOkxVbH$!4(h&1^BZ z6yiCT4;)0C$U=Wh?%n7+-^jzO`{)qX7V;Wtmdfr%6HIwD58plIOm@-}+&+x;Fcxf& z=z71RYdRSV*W8v)I=ID}vpZ$e(tfj@ng+&+rfY@Kth5xrw-Zfy!rv6T9w*aP^QU$Z zh$>K^%g6^&%x?+BoBQ=Xu4&N=B)$dUXl@8S3(GeMH>xvpp$G@Q26Iv)nBkv=IpJyi z2x&NpG0bzwX<@;srpp@<@Os!?&?}wbj!UckG$^8VUZ5sw*=q(Sl-+8HO=~&q%U%k< z`#p+#YgFVFFy!U>kUwxkY=P=;7F=rCVDuhS(sho8nNt+2&b(h*iBz0B3tTGUf2(XeE^&eYO8glR^nQ{Oq({HGq6TI zM0`IR<#lh`>qAjF{iil2FzdE0L4HvO(gqqx8%8#U3idX(4sQ%??2UhVg-5Ked^Zzj z-})1#^tyNpE@~2U9u84BIi&$x`|J(GY=zYlf}!WfTNr4O@9%BKn>sSrmajgjZFRj) zR}+($VACT9V+dFI$PRcDrolz&BVI}IH6jqMq%-atWs5|BtiRpaR`{zRcz1=kT6zDB zX!cxL>T3g}SGRskITm(iT3uflS3@-!+wb5_M;C%$du!Qm)q)4sQ^oQrg%X)@GTMME zDGcU-MP!Qk1rxQwR-Sor)DDN#D5z`PO@BoFbUR+Qrk=Q+-D+9k^c>tiMx3==6ez`6 zgDzOD5(AMphHr)k8T z`)v|ICfNghQ2*65`nI+|Et4_c1`o1K;Kphh?BcQtOw3em7#EMqZFKsxpo5%5WI@{} zGGFX(cjw(b^Nwk{z3|Lq{+dK1Qt*P(*8Pej;$C!&O5_}Sqr$M7C(-$POF)MxOp*&k zNh653L=1=G1Sw|-8>JN19TtVFz{~KwT>WGQt)X^ak}_r03@l5;y-utRnBmXrpMShL z81#HDFzE<7D!D=Wrwnr)j##%K-e(}e!0Rxz5L>Xr5sm|*tlHj_U=4)guLibhwPH**M0b6{@K99FSk|KmL%fe>2kmt%j4B zkh@(8@OIn)aVAIjoo%eZhs0i{=y}|Wx46Y~;K%qujRxE`;YT#d+vQBWwXTwOQ_9!3 z4s*or3(66LCcXlPpOnv&-IIgxd$yFB%J6&Wz4W*C-n`cRr@Fde^cQWRz`%~s|9VP+ z)a7VuY-Rk{mHDT#w$-I=zH^|q->RWDpAJ`(e48UHJJgMsU>f@!CLo~2Ee|p|Qy_A*Uk(#rm%o$A zg&9pmKI`4I6VI&m!+D2CM4u6I&vnw*v<%D4N4gyIK24rN4X)QknT%@MgUr>zp{Ds9 z?@76=BkFRlYjeaY?<<%srcaR$3V!+Snrg(c_fgg7Pwa41U4Zty_0tV(H8r)3O|a93 zyX>GW`43&&S75}ocU3kov)ktEJe@%do^w5)JLo@j0oJ@(#O}3Gw0CNTWFRG>9z9U` zVeVSjz!-*)j~MB`UN7j3oXZ2|!I*~nQtk7z5MsZ<+R~+;QuI-P^OH4R_A-hdm=5tN zB`ZJ2I*SQCdEYRMHQc&;8;U#RPHzWc!l z67Ntz)H3PmB*bPWS);UB#Ixj^3d_sL;~*~rZ_F4%&|)|C;))!beiE71oP!NV-He22 za!g}*i>gA=c8_vC3qc&M_*ynurkBCO&S&w8p8B)(0cWY$X2&jA?K^Od)T`>Pn<%pH zL9AD>?*gVLgwPlhMF9!z{j@bo zJBl8Fi@9eroOruC92n@*Nwar%4yU@c-F$KklIZCBF$vC^d>FT>gI2Eva`{@4@DZJ1 zoL%}<%wX;Ke8i{_OCwxdFUpi{-Ot|@LDrD=sLH0g*xPJ;SXt2fKzO-=w(K>D^#Z94 z_tH@r&y!@kIZ&A8%^_%@axz&!mOl=ql0%v|sVV$jud$QSG||Zn-C)~7#Ej0(^e}N& zKTIoiA4xVQUt!;o60T`BA?q{sW#Q^$-8+@plzuJMg>^nR5=*trHI4lazv|{x6(6R? z@A*x@B8#lbm!1rHrm6eZ6{1>^uJ<2fvX!rR)Vel3C|l1!`+NHb`Txe zlFV(4s?z0QX#arhX{uOMxvXl zPmJsNy+$vaHvbGzoam8_fuLA!h6o1sb8`&}P!6X0_Qpoaj`n8OCJsL%RD_y#T&@_V z$Jft$o7!kj11a&%0ShP5BvtNQDMbwaJWFsBf!2i|o;~nZB{f!@V`+7HZ&#*o%ib`( zJiJTT!ourvZDT6m7$i~HZPmNh*UumNU~7X4sA(RQ(&_1Th0%}xJfgcJERpMO@r5Z; zDbtf(HikH7xHmd0`&}aTno5d_SDGJ<9FkE07sOyG+d$rAhK6xDhs5}@CS&;iQ5T8T z*t2z46G8PWDiG{s)vcd1O*eUE4w$# zz(p9{zO!S0pdJgIiZB2Crep>o$Qz!-&taOl<#OrPmW=>oX&CYU5WGczwsJu zJLSR|K854aEpKKtzM6?`V=`3;a^qa;T|32hHBOlcH~pCDh~Drh07%L*?aOv`LhiLG z~ph^7F-|i&uP?iU~Pz+;4)DKS(Xqk zrIh>rylM9B2iZhv(?QXt)~N_%A&%XIsavHwpTKR+ENeUVfalt;7093EDAMV&gR4cM zqIMU>eJT+e0%U5DR7#6nYl^#JK7o%N_Bp*Wmxjo(p<26-mQBeS!|IX@uq#|og_te* zYL%)pjqx?g)R`6TLpSYSY_pVza?1&NdCjfPO>?CALx8CTr?c=pLM)o*G*4~O_z~KN zO6^Zr&z(%l#=8Zn(W*mkLfz0JNjPf@^&QSnHXf~|M2gA=RJk*1M!u1c^D~^`;&ZNg z8h+;@_;<%-{hSFWkFRSh-Z{(g%@;M0Q|7gAhfJ-X$C&3V4<$aBrs(+3pcp&7PF>rK zI%QM6%b@|{nRg3Vki9D4!woO@DUgR(J@kv>K`+z^M@Cv!0t=ZT+<$+Qz2-O?nj`Bq z_oa%zj_fqW(ShJDSuoIGqH{F;vp_Da{F}W9W zXjH{{gu%)3Gfy|cm7^F{J!pIc<%>{MTNMw3M?^`&`o*nYIT^-dg^fPL*WlYzKGaE! z{27lb*yC5UM9Lnt^e^E5^xM%uRpo8a#^N&(7#Pyue(UIFY5dD!k2MahNjWi}*NdtM zN(4${aVY^l^gxbi(bC$`QdwHngLg6di0ao`+&ARWSst1Es#*Cru8c%yor0mx4e(^l z?dc=C4(^d}3%%N|Xk5FQ$@IT<-;^MMBNyg~`!*qXx#2W4qcTN8piDA#GHU5VcU^yL z;r~t-dWwzXKq3M)8h|jKM>k?H{ptpd2Z@XzI7I{JF*wYcw?Q4#aEp0pOL^qWF~W#A zxwoHZ^qpZAD-%+jcT1HTBKY;gkb^!91cfE$M~I=JC@QKOle4ER$-(uf%lY-v^Am>= zUT_A#!7wpWuSfs3_1oA_X3?L_=kwUda9_Ek!Ot;sCVHNz^a<2^g6*gZ)I(h{#KkH* zX&x9;etcPAfi#_th7jV#xmTQELF~kn!&!J;K8uT%f=)vi|3_%z$ z-CraXMo*=r!iFX_7CM88G&Wc6F8+qli70CaM^uFkzKB*5MVfNM%L|0tM$c6F z%5nj-X$XCC#(IbOK)uivsMzl;|Krh!uC9PV>B^sG#>E^*I>mkUjFVaDilk;)cj*Ye zxjM)rdGc^!RE$%J*x*X-^hU%fnM<37znPeY{Ur)aLYIXCO)4yY#>ZTcS|mNpI8qeG z=r~9<-bSnhIC-3%Ibb^L%sqyCgYi{ZiZ{fKf2v_5Xrs}CC)R*+7Vg@tQE>snt?`_3 zgNDRyd|ZIPz^yCs7%f8EbQzbFX_Au4B5tm*tTv!yio8Ml-d&b*2sK4ksoTmR_KM=> zf;^n>e41x{Y?p}`?}{eVE_-)+3DHn;N=Sh6QdBuI-g#nIe_#AIj98h3n0TJeUK$>!5VNzE#9r0nvs9@By~%)q2&5i%IM9%?}NS?w0aS#3rZ zIOhAu6jyfuiaacDccXcMU!-|aqx4K#>?}(pxfb_{M6NQ*3srSRH}KJFsli)-_uIPV z{HU`AFkM(#X1}fX{;*u>kikSVhgx3v9FpE9^pehkmRSQv6is`T;u&h-du^!w1Pvm(=0W9{Q+gQm!e5lC6FN%)w=F>@`Ue6$~y(SgZi& zxim@{^1B?o5tU?7up)E>b`cYb6lEk+pN02{U+6QwONNz^rV{K93$>_|;MzLbWM4DU zev}=4`oNihWFZZNdyD7cgU+ICNej5{u9t+ne|OkA%e}5uVOUTi;Tgu(H|f7={$cgd zT+@yNNrr*=0Ag;c!5I;YW}%c?<;b4(wBivxaWrL(Ig|>AYnM_UcaOVDMxWLvWuK9y zIW5xtV4sn-83lMhGwtNy-p7!XQkgV)9oVB^@fCDqqQALb(79@dO;1TyN@5*hyt` z$&c$E4|nrds3qcD&8+6{Exn$nrZ3yk6odNhDIA<#qpM(zbEFs>-abCLUSB7R&iT*_ zQHQ+6pQzsZaWt|omy#5r^ac%FBCTfWZCkM6`OVu^gp$P7HRH1^0?@fzOb*d!1 zoz|sKszw*nwd#6Yz^4yJ5)n@GCHptg4sxJ@mLl!t2tke=mCQ zOAx5v-C2wN9zhk!^Z5GK8Y?oviT!^L#GN(WTYE`68C(VOjLE*a|Z zopA!gf$CJ!=afvkAPBX%5$ekg*v7Du|5iyCAG#m*XQuHm`msn~bu|g`D#U1u=;bfi z$EyfauH&I|IL%rpp6s9FqN3e3Uw(PW6dp<1+ZKis@Fd_ zag_^&N2Zm(+2`uQJ0%Wlf%p2_eQ+VdloykR#$)< zk$xwBdS;4Z3oQ=`c0iqrF*0UkPIwr*=;0NnK_{oq>IQ~7$5o&`G8>`9-Pg_qJ4eN_ z$sd)CMf}MrVh9F%5nBQaQy&c7eI{coCAyAv5_>Ba1g;nJRy+$WGc>r4>cvVlG@oRE9PE=>XHER-GTE-XE$|CRKfXd?D zz>@G;?(}305ufY_k2jegtI6jN1N#hZ)q${NjZ+^bn9+xGi-(tSoAb!-=(13eefqGr z;vzH=i5EjV=I^1Ke(uPA^kPX17|z9VI*j^?6R`@kt8)ycA2q)Ev5!I_|*Hr#a9tnMNhvWRFEY?@C0w09q3M7@I zHD=;!ie%c=HWem(jh`smB(ba9NZx5OJ|b^BSsi~?jVOp`f1V|=Oi?0#&W=Gfohad4 zBz$WH`(}?nxT9N|zmw-=OrSE4co%o2o%rik>=80yY``{?CMy!XnJGhDSGd&JT7H$k z!0Yq_&1bE`D}|4J$GngxJ@S6HP|o~!A1>Y`sbB+4U3$D z$9aL_5RxC>j?R0bPX;VI$wP%;HrOZnEKR`Yym z-+nunF1q!Bf1#P%+4kMtgg}`{_T#(TN9TZ;FCz4? zNxqS1fq3EkQ36QwN*$@ON?~9^$!Lrfs($3mZjy8c+)9ezQ~@(sU#ezDdZ}fHx^+uk zW1U)_@=0aBc{5EE=?&)Uy={wg(^k}n3@%JpuUe0nNrA2ymiH+O_Nd>FE z>Z-s?#E7HN*hnH9hSn|#6NgCkJ;&u+z+~N`MjjR-89f2Vz@VrJ<8~R(Lo?0><2T%4 zvy&qcs6wo^g7m1fd=&8KZCpLLGs&=~7VE~swL6egX-20mi#I(BFILw^x9aTX9-`V0 zMG!0YX(=(64yI+zTk1=z7i6p%e~i&KjGylxJ}`-I(X!#nzvtbA@~0;?V(513_zqV2 z;3X#EOS5*tV=&}eyp6Y?T@*~0<_K2Y^#i)h3D!4}=NP}}gal0jNkZ*=n0~eWouZ+A z`J@FqI*C<=$E2f{WA_KKt5}drF_74Pa_^o?P2$W;#CG0`SXD%mh8|GeAbaYF9~#DRj9VTeHd&x7 zeV2Ac%95r%+0x|d?Zk($Q=;t&h`WTf5ky&%2pS4BBcj^3ghzp07$Yfi+WdSrg>r^$;UEx|IQljN%?fGQm|@dmS}KN! zi!oUE;7k1hRf4w{+=sJbua$9x>cv~pxkRAaI2%rKP$?TlZNtowHoWwm;aG|F_8VsW z$0>a4EU7crADgbydb{82@ox>>I(&Hx+rttYR@fCSOYg@gc?o2nupMe&$-IE;Rb!Wb z&#!x7>F@aCl!=UEb;1KGCdq+zR)1%Q9Q6%Ar_49MhF{Mx;}}^vP@X^FHof~IlkylM zhgR|xR!lVQ>so?NS;`QKPXun1@oPjpPty7(UYWN$V_ff_)XCbr;+&I5?&%XCs_g6f zIg)f+F3vUJ4Fc*|kO4{JBsA~(fc@q+f>7*Aj66G@DdZ|ndRSvxC^$NJyA_+Z*H*%9 zFsjNhopa=2Y#vhOQ`7;K!1pu?i{IMA3OC+a97J$?t_Y#XGV1P(%m-i|spCF423hSQ z16*mtWRQ-etZ;tR)(#H3tyLRveMflDQ_ddL^m%)OhNgOp7Irty%nr}(cvLS&WE*-* zORNU2gO~~ykV)yrX^ujfWYZqNXCC_WJdBNfug)`>2>Fip83V~#hFjK=W9eeDlZV5) zc?!+iarvD0*Ju$Ig;=NUNcUXQUlo zy5vPR(0rfOPTwxuD!yc0bZlLZdU3wvd(&=36qkQR8#KF9e5syz=x6Ox<0_MQzT?p@ z_iona$Ca_Ol>{xjNPs|T(2vdsHT|^erEh?mFZRH#ookoa7EiA8%q(^oTsDZ;U*^+ zN6&K*{-m$E>BVWKvQ8ZSR2XwocDa12tI2EA&qUYSvc>N?JnZ)Tq#Vo7n>fos&`Nw` z9weG+mHN_VtZB0x*%0nU;N*LdcDk>9ukNw@N#N?S%k=YihD;9Q_8)4G&AK+1SsHas zkFsi-MTHwRjp0!!VLw{bYMY(3Y}{Y6t1Ixzbe|MDv|dWou0JTZJ-G97AMwxgzwd*i zyK%uPDnI+w63YrWccCx@z&TUw3ZtJ$@xx1csa;4)K)1w(L?0bX@goe`s-eTdVY<+g zE3Ceuhs$op7KWI8`Z-I97Ib2h(z{HRshssq(2DBSdzH(QB>mpag#^9 zXN4Z(*e)=0FN37?B?=Q^-%p+`BTd>DlZ^L9Nis*VU!5h5h_7Z&F8Uaos-)YOC|Eza zyg80-YRjQ(*;-<3x*usj>Rg{cyIsdA-x80&Nc7%}$2z0rtD)_$FwlFK9_IN?XMJgu zs?4ApenG?QHQ_$sX3n{A&beKkkFj^IN1jI*V(@)hQ!VWdGDTB0@}1@tmd{IB<5tlgPim z$Ry<4@NHbwCM9Cs_+Ya)rP%1WR%0K9Cy+hzO_Hb1z8xQZ$RpSSv~y-muqm`X+N z)ZBaL$nX>C#r3GXFj*3agzU;e^&h%ns9aQ(JBvz@#|~=(VO9C7D6BhQlK<<0-hk`+M4j}GYQ3{lyhqJ* z{>@O(reY#$-U>P^Z9Nn-E$9{}kui!unXRxU=U<%U0K|X?C;TkK9HYgip*Y4!#D~DO z7k!n|B~r0t{umr?^TMCppb#Ev_+BoRas!Q2Ea41P?)0K*nlC>HyCzMx`%Jb&{>{-+ z(aGj4j^T!1QSq)YYqy~Cb&zwuhcALdQ;7M9xWrFDo`O_lD{We0a)o$Q`5^y5I81(5 z;e3vg{qVu)&v(e+VN<9+$Y^0-r!QTteZfHMY5ye3;62yl`xaYuf4 z=FlTjCmOxvLCWkrBSW~9T7pNKPl_lkA({ZE6f=dI-yK8((l&tI=xsYNIgbsh1epH) zl2<_IjO#T&B8>%(QjpBRE>|D`%L*+Yr0ehuKwSen2EU_HFS@UaN(u>97m^UIJFL=4 zB$^Vi{W}j7uM{wvTZET?0MZqFLj8^@zg+((vnOwJb1e2$-b0nFQlT4)kIm#%q@3mS z@Ja8LOQ-~mhZ2wiwt*(123v(Sq(Is&o?hXfI8eZLSS%(y^uJkg9Ng6l5{L_}hgE8k zC+{E6l03E=Q$a#gN<_`i9R~3poeyG#*&Z_A2OtGckV{@5B#{6OK;lyEG=?$U07kt|7wGWgGQ{br`Cr!AT!zjPS3WCAsRIEXPGn~YP)d@vRwh+fhRRw;;{ z22}_)P_jD+fOXgmtF+-4^eE^r$ffvsiS#dPYcFj~%*ot++t5j93c}VZtv^HO%F&kz zK+%CJdf;Vqr$>@GOd+@+F9669UgUe{1%N?PZ1kj82flTJjfX(?y*c+qoqcU*ejC!e zpvdZEYEft&oDL7?K)XaLM@UMs4NSKW8coMzDd+?!E8%U<0F>dmbUH;n4gUhcdIHG3 zMO-TKYc~z!s(TbMI4VxzuKj7N32fsJa-#2hOMvD1?!n4v{+d*%OlmU>2F!6jR^x@?DHMn)1RzzIx~RkCvo#(GN33?10QleurpSJ(cPdYC z3zjW|96cUjPs`Tmsb;oEpU(c+Xs>N{MvGF=buUxkgQr6+OAK&Q$0k3JiRLaxRKoL} z(YK1;i-c1Ge#GR;7yr2c^TmDCcZH`VNrgZz7f6DI=Nr$C_;Y~>|5{A6Y>vw)kD35| zU|2wW;J770B0|VX@*KjeKvQbl;K2AmSjXT%2xPdk50oG)LBS)T4W@du*2IAvU)WF0 zk`~EB9TSgK!8BO#@d5;bJqm|}u~+3Q;W*&frDZzkAsn<1 z%qEdNF~OEUHNo(~AG&BHpnqUlUM2yJw3sb8o0?Ro7ht(Zikt(0N{v$8XtV)A|>JiZG&kFev<=GfFp#!DgYo8LL@{Nttqm;=Jy3skRk^Jzg3az&9Ns%P6*~wAzfMw z>0=m7hUK;m6gAt6rkz`wIHnLqHA>cpL-LW_Lrtbe652sc_UE;VY?#4EAO=rCM>7)k zcUj1kpz@V@i-gKT(Vg%`NhCUi1z=CwdA22PWoSZE6aHPN{9 zLEaSoHXkcT{o30s;J+1t_=^rhs89szCp$NFwB12e!UPa-+dvEevW051O{VylK{Xe% zC!+{1i>z?P!m^;GAai$ELz)xC6Hm2tytZ{#mkaf`~vBwv4Sx8hz~je5M1 zBwTBjxFlupnv-wj;xEs_zKHJ|m_F~bnZF!LTIYv)xf@s~9`<@C>VB_1`?0{ML^5{D!f->{u#S?^U`RQ8Ea5$Z$;}CTbZ7=%3XKbw!|`?8LR7e_xXprA2DfT3*pEehx7+K zMeA14=UUq3+q=Uu9Xo{vRn;8*>__Pnf5960RMi&3%a$9)=O&)SA0?xuoa^Pq+>O-B zMF+g^PB+c5uT0v)h7Sm(&mSI$mn*(J9t4%Qek|`_Bl2pHD;V! z6oFU!?FyOhPSh#8)3Y7`&IJ6-hWDFZ{Vs+602rp*4<~4X5>z_0ZA6%F{uH)E*t$FL z$JEYOR+NwmG_$;ol`CqEVi$p&$@_7T*z8IV$^_bru;Ee~`sL;aa=fQ&6=?dM0An!9 zPW|G!*~`jefmd>pM!-okzIU(qq4f3zFqMy`>;j5cE;!ZCIgeK%!`_->MZu}6hpW5T z)wgWcR-`!Iv>Hn_TzBnd-)`!*cDBOm#!Z;U=Molz2lt|#;>4&K55)N|j<9GfNAJI) z(L28aa#k@lVDDi2Ps-!laiY3GT_)6xKH*dY)}f8!gz%a1gDqPk%13YM3afyjx{WB zv?_67r4%l`?6a2s#31@2u}VoNgh&5Kag@(`Uh>f|st@L$sf|>hS&C{<9fSg8aI$}^ zhy2w*`l~AP%k00}M{~wWm<#hfQ zx#O3}XMc%ID3Wi6jn*vX;mz9i+{FebiTQW~?O65go9pfQQzYHtZuz30dvbY9^d%w= zu5rr{B0A%-Sqsc-(p2O+c5?k3u<}Zd?G(0t75ML45YnM==>0gWLc!T$sm!*AgZcRl zp8d&U0i+c^D7GciSp+&@;6E+!@u$IA0_!S@cu@qc=IP8|1k{z$ Date: Mon, 20 Jul 2026 17:55:49 +0000 Subject: [PATCH 04/13] Update merged schema files with markdown descriptions --- resources/schema/rule-merged/CORE-base.json | 142 ++--- resources/schema/rule-merged/Operations.json | 301 ++--------- resources/schema/rule-merged/Operator.json | 487 ++++-------------- .../rule-merged/Organization_CDISC.json | 112 +--- .../rule-merged/Organization_Custom.json | 53 +- .../schema/rule-merged/Organization_FDA.json | 38 +- 6 files changed, 227 insertions(+), 906 deletions(-) diff --git a/resources/schema/rule-merged/CORE-base.json b/resources/schema/rule-merged/CORE-base.json index e49252530..d8bc945f5 100644 --- a/resources/schema/rule-merged/CORE-base.json +++ b/resources/schema/rule-merged/CORE-base.json @@ -9,9 +9,7 @@ "$ref": "#/$defs/CheckItems" } }, - "required": [ - "all" - ], + "required": ["all"], "type": "object" }, { @@ -21,9 +19,7 @@ "$ref": "#/$defs/CheckItems" } }, - "required": [ - "any" - ], + "required": ["any"], "type": "object" }, { @@ -33,9 +29,7 @@ "$ref": "#/$defs/CheckItem" } }, - "required": [ - "not" - ], + "required": ["not"], "type": "object" } ] @@ -134,18 +128,13 @@ "$ref": "#/$defs/Domains" }, "include_split_datasets": { - "enum": [ - true - ] + "enum": [true] } }, "type": "object" }, "JoinType": { - "enum": [ - "inner", - "left" - ], + "enum": ["inner", "left"], "type": "string" }, "LeftRightKeys": { @@ -158,10 +147,7 @@ "$ref": "#/$defs/VariableName" } }, - "required": [ - "Left", - "Right" - ], + "required": ["Left", "Right"], "type": "object" }, "PascalCases": { @@ -246,10 +232,7 @@ "type": "string" } }, - "required": [ - "Document", - "Cited Guidance" - ], + "required": ["Document", "Cited Guidance"], "type": "object" }, "type": "array" @@ -258,14 +241,10 @@ "additionalProperties": false, "anyOf": [ { - "required": [ - "Logical Expression" - ] + "required": ["Logical Expression"] }, { - "required": [ - "Plain Language Expression" - ] + "required": ["Plain Language Expression"] } ], "properties": { @@ -279,25 +258,18 @@ "type": "string" } }, - "required": [ - "Rule" - ], + "required": ["Rule"], "type": "object" }, "Plain Language Expression": { "type": "string" }, "Type": { - "enum": [ - "Failure", - "Success" - ], + "enum": ["Failure", "Success"], "type": "string" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -311,18 +283,11 @@ "type": "string" }, "Relationship": { - "enum": [ - "Predecessor", - "Related", - "Successor" - ], + "enum": ["Predecessor", "Related", "Successor"], "type": "string" } }, - "required": [ - "Id", - "Relationship" - ], + "required": ["Id", "Relationship"], "type": "object" }, "type": "array" @@ -340,9 +305,7 @@ "type": "string" } }, - "required": [ - "Id" - ], + "required": ["Id"], "type": "object" }, "Validator Rule Message": { @@ -352,11 +315,7 @@ "type": "string" } }, - "required": [ - "Origin", - "Rule Identifier", - "Version" - ], + "required": ["Origin", "Rule Identifier", "Version"], "type": "object" }, "minItems": 1, @@ -369,11 +328,7 @@ "type": "string" } }, - "required": [ - "Name", - "References", - "Version" - ], + "required": ["Name", "References", "Version"], "type": "object" }, "minItems": 1, @@ -396,10 +351,7 @@ "$ref": "Organization_Custom.json" } ], - "required": [ - "Organization", - "Standards" - ], + "required": ["Organization", "Standards"], "type": "object" }, "minItems": 1, @@ -439,15 +391,10 @@ "const": "Published" } }, - "required": [ - "Id" - ] + "required": ["Id"] } ], - "required": [ - "Status", - "Version" - ], + "required": ["Status", "Version"], "type": "object" }, "Description": { @@ -493,9 +440,7 @@ "type": "string" } }, - "required": [ - "Name" - ], + "required": ["Name"], "type": "object" }, "minItems": 1, @@ -521,9 +466,7 @@ "type": "array" } }, - "required": [ - "Message" - ], + "required": ["Message"], "type": "object" }, "Rule Type": { @@ -541,9 +484,7 @@ "$ref": "#/$defs/Classes" } }, - "required": [ - "Include" - ], + "required": ["Include"], "type": "object" }, { @@ -553,9 +494,7 @@ "$ref": "#/$defs/Classes" } }, - "required": [ - "Exclude" - ], + "required": ["Exclude"], "type": "object" } ] @@ -569,9 +508,7 @@ "$ref": "#/$defs/DataStructures" } }, - "required": [ - "Include" - ], + "required": ["Include"], "type": "object" }, { @@ -581,9 +518,7 @@ "$ref": "#/$defs/DataStructures" } }, - "required": [ - "Exclude" - ], + "required": ["Exclude"], "type": "object" } ] @@ -623,14 +558,10 @@ }, "anyOf": [ { - "required": [ - "Exclude" - ] + "required": ["Exclude"] }, { - "required": [ - "Include" - ] + "required": ["Include"] } ], "type": "object" @@ -652,20 +583,13 @@ }, "oneOf": [ { - "required": [ - "Classes", - "Domains" - ] + "required": ["Classes", "Domains"] }, { - "required": [ - "Data Structures" - ] + "required": ["Data Structures"] }, { - "required": [ - "Entities" - ] + "required": ["Entities"] } ], "type": "object" @@ -700,9 +624,7 @@ } }, "then": { - "required": [ - "Grouping_Variables" - ] + "required": ["Grouping_Variables"] }, "type": "object" } diff --git a/resources/schema/rule-merged/Operations.json b/resources/schema/rule-merged/Operations.json index d8f634b4b..6bceb8ebc 100644 --- a/resources/schema/rule-merged/Operations.json +++ b/resources/schema/rule-merged/Operations.json @@ -10,10 +10,7 @@ "markdownDescription": "\nReturns a Series indicating whether a specified codelist is extensible. Used in conjunction with codelist_terms to determine if values outside the codelist are acceptable. From the above example, $extensible will contain a bool if the codelist PKUDUG is extensible in all rows of the column.\n\nIf ct_package_type, version, and codelist_code parameters are provided, it will instead attach a new column containing the extensible value for each combination provided in the source dataset.\n\nFor example, given the current dataset:\n\n```\nid \tcodeSystemVersion \t$codelist_code\n1 \t2024-09-27 \tC201264\n2 \t2024-09-27 \tC201265\n3 \t2023-03-29 \tC127262\n```\n\nand the following operation:\n\n```yaml\n- id: $codelist_extensible\n operator: codelist_extensible\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n```\n\nThis will result in the following dataset:\n\n```\nid \tcodeSystemVersion \t$codelist_code \t$codelist_extensible\n1 \t2024-09-27 \tC201264 \tfalse\n2 \t2024-09-27 \tC201265 \tfalse\n3 \t2023-03-29 \tC127262 \ttrue\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -23,10 +20,7 @@ "markdownDescription": "\nReturns a list of valid codelist/term values. Used for evaluating whether NCI codes, submission values or NCI preferred terms are valid based on controlled terminology. Expects three parameters: `codelists` which is a list of the codelist submission value(s) to retrieve, `level` which is the level of data (either \"codelist\" or \"term\") at which to return data from, and `returntype` which is the type of values to return: \"code\" for NCI Code(s), \"value\" for submission value(s), or \"pref_term\" for NCI preferred term(s).\n\n```yaml\n- Check:\n - all:\n - name: PPSTRESU\n operator: is_not_contained_by\n value: $terms\n - name: $extensible\n operator: equal_to\n value: true\n- Operations:\n - id: $terms\n operator: codelist_terms\n codelists:\n - PKUDUG\n level: term\n returntype: value\n - id: $extensible\n codelist: PKUDUG\n operator: codelist_extensible\n```\n\nIf `ct_package_type`, `version`, and `codelist_code` parameters are provided, it will instead attach a new column containing the term for each combination provided in the source dataset. If a column name is provided as:\n\n- `term_code`, it will find term information using the term codes in the specified column.\n- `term_value`, it will find term information using the term submission values in the specified column.\n- `term_pref_term`, it will find term information using the term preferred terms in the specified column.\n\nOnly one of `term_code`, `term_value` or `term_pref_term` can be provided. The term information returned will depend on the value of the `returntype` parameter, as described above. If `returntype` is not specified, specifying `term_code` will return the term submission value and specifying either `term_value` or `term_pref_term` will return the term code.\n\nFor example, given the current dataset:\n\n```\nid \tcodeSystemVersion $codelist_code code decode\n1 \t2024-09-27 C201264 C201356 After\n2 \t2024-09-27 C201265 C201352 End to End\n3 \t2023-03-29 C127262 C51282 CLINIC\n```\n\nand the following operations:\n\n```yaml\n- id: $found_term_value\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_code: code\n- id: $found_term_pref_term\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_code: code\n returntype: pref_term\n```\n\nThis will result in the following dataset:\n\n```\n id codeSystemVersion $codelist_code code decode $found_term_value $found_term_pref_term\n 1 2024-09-27 C201264 C201356 After After After Timing Type\n 2 2024-09-27 C201265 C201352 End to End End to End End to End\n 3 2023-03-31 C127262 C51282 CLINIC CLINIC Clinic\n```\n\nConversely, if given the same dataset, and the following operations:\n\n```yaml\n- id: $found_term_code1\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_value: decode\n- id: $found_term_code2\n operator: codelist_terms\n ct_package_type: DDF\n version: codeSystemVersion\n codelist_code: $codelist_code\n term_pref_term: decode\n```\n\nThis will result in the following dataset:\n\n```\n id codeSystemVersion $codelist_code code decode $found_term_code1 $found_term_code2\n 1 2024-09-27 C201264 C201356 After C201356\n 2 2024-09-27 C201265 C201352 End to End C201352 C201352\n 3 2023-03-31 C127262 C51282 CLINIC C51282 C51282\n```\n\nNote that `$found_term_code2` is:\n\n- `null` for the first record because \"After\" does not match any NCI preferred term in the C201264 codelist.\n- populated for the third record because matching is case-insensitive (i.e., \"CLINIC\" matches \"Clinic\").\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -36,11 +30,7 @@ "markdownDescription": "\nReturns a list of valid extensible codelist term's submission values. Used for evaluating whether submission values are valid based on controlled terminology. Expects the parameter codelists which is a list of the codelist submission value(s) to retrieve. If the codelist argument is [\"All\"] will return all extensible terms for the CT in a list.\n\n```yaml\n{\n \"id\": \"$ext_value\",\n \"codelist\": [\"ALL\"],\n \"operator\": \"define_extensible_codelists\",\n}\n```\n" } }, - "required": [ - "id", - "operator", - "codelists" - ], + "required": ["id", "operator", "codelists"], "type": "object" }, { @@ -50,11 +40,7 @@ "markdownDescription": "\nIf a target variable name is specified, returns the specified metadata in the define for the specified target variable.\n\nInput\n\n```yaml\n- operator: define_variable_metadata\n attribute_name: define_variable_label\n name: LBTESTCD\n id: $LBTESTCD_VARIABLE_LABEL\n```\n\nOutput\n\n```\nLaboratory Test Code\n```\n\nIf no target variable name specified, returns a dictionary containing the specified metadata in the define for all variables.\n\nInput\n\n```yaml\n- operator: define_variable_metadata\n attribute_name: define_variable_label\n id: $VARIABLE_LABEL\n```\n\nOutput\n\n```\n{\n \"STUDYID\": \"Study Identifier\",\n \"USUBJID\": \"Unique Subject Identifier\",\n \"LBTESTCD\": \"Laboratory Test Code\",\n \"...\": \"...\"\n}\n```\n" } }, - "required": [ - "id", - "operator", - "attribute_name" - ], + "required": ["id", "operator", "attribute_name"], "type": "object" }, { @@ -64,11 +50,7 @@ "markdownDescription": "\nGet a distinct list of values for the given name.\n\nIf a group list is specified, the distinct value list will be grouped by the variables within group.\nIf a filter object is provided, only values for records that match the filter criteria are included in the distinct values.\nIf `value_is_reference` is set to true, the target column contains the names of other columns, and the operation will check the referenced columns to ensure they exist in the associated dataset before adding them to the distinct list.\n\nIf group is provided, group_aliases may also be provided to assign new grouping variable names so that results grouped by the values in one set of grouping variables can be merged onto a dataset according to the same grouping value(s) stored in different set of grouping variables. When both group and group_aliases are provided, columns are renamed according to corresponding list position (i.e., the 1st column in group is renamed to the 1st column in group_aliases, etc.). If there are more columns listed in group than in group_aliases, only the group columns with corresponding group_aliases columns will be renamed. If there are more columns listed in group_aliases than in group, the extra column names in group_aliases will be ignored. See record_count for an example of the use of group_aliases.\n\n```yaml\nCheck:\n all:\n - name: SSSTRESC\n operator: equal_to\n value: DEAD\n value_is_literal: true\n - name: $ds_dsdecod\n operator: does_not_contain\n value: DEATH\n value_is_literal: true\nOperations:\n - operator: distinct\n domain: DS\n name: DSDECOD\n id: $ds_dsdecod\n group:\n - USUBJID\n filter:\n CAT: \"CATEGORY 1\"\n SCAT: \"SUBCATEGORY A\"\n```\n\n> below, `IDVAR` contains column names, the operation retrieves the value from each column for that row, checks the dataset associated with that column using the CO RDOMAIN. Columns that exist are added to the returns the distinct set.\n\n```yaml\nOperations:\n - domain: CO\n id: $rdomain_variables\n name: IDVAR\n operator: distinct\n value_is_reference: true\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -78,10 +60,7 @@ "markdownDescription": "\nChecks whether the domain is in the set of domains within the provided standard.\n\nInput\n\nTarget Domain: XY\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: domain_is_custom\n id: $domain_is_custom\n```\n\nOutput\n\n```\ntrue\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -91,10 +70,7 @@ "markdownDescription": "\nChecks whether the related domain (for example, the parent domain of a SUPP or RELREC dataset) is not present in the set of standard domains for the provided standard and version. This is useful for determining whether relationships point to non-standard or custom domains.\n\nInput\n\nTarget Domain: SUPPEX\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: related_domain_is_custom\n id: $related_domain_is_custom\n```\n\nOutput\n\n```\ntrue\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -104,10 +80,7 @@ "markdownDescription": "\nReturns the label for the domain the operation is executing on within the provided standard.\n\nInput.\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: domain_label\n id: $domain_label\n```\n\nOutput\n\n```\nLaboratory Test Results\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -117,11 +90,7 @@ "markdownDescription": "\nCalculates the number of days between the DTC and RFSTDTC. The Study Day value is incremented by 1 for each date following RFSTDTC. Dates prior to RFSTDTC are decreased by 1, with the date preceding RFSTDTC designated as Study Day -1 (there is no Study Day 0). All Study Day values are integers. Thus, to calculate Study Day:\n\n- --DY = (date portion of --DTC) - (date portion of RFSTDTC) + 1 if --DTC is on or after RFSTDTC\n- --DY = (date portion of --DTC) - (date portion of RFSTDTC) if --DTC precedes RFSTDTC\n\nThis algorithm should be used across all domains.\n\n```yaml\nCheck:\n all:\n - name: --DY\n operator: non_empty\n - name: --DTC\n operator: is_complete_date\n - name: RFSTDTC\n operator: is_complete_date\n - name: --DY\n operator: not_equal_to\n value: $dy\nOperations:\n - name: --DTC\n operator: dy\n id: $dy\nMatch Datasets:\n - Name: DM\n Keys:\n - USUBJID\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -131,11 +100,7 @@ "markdownDescription": "\nReturns the requested dataset level metadata value for the current dataset. Possible name values are:\n\n- dataset_size\n- dataset_location\n- dataset_name\n- dataset_label\n- domain\n- is_ap\n- ap_suffix\n\nExample\n\nInput:\n\nTarget domain: LB\n\n```yaml\n- name: dataset_label\n operator: extract_metadata\n id: $dataset_label\n```\n\nOutput:\n\n```\nLaboratory Test Results\n```\n\nExample: ap_suffix\n\nExtracts the domain suffix (characters 3-4) from AP-related domains. For example, \"FA\" from \"APFA\" DOMAIN value.\n\nInput:\n\nTarget domain: APFA\n\n```yaml\n- name: ap_suffix\n operator: extract_metadata\n id: $ap_suffix\n```\n\nOutput:\n\n```\nFA\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -145,10 +110,7 @@ "markdownDescription": "\nReturns the expected (\"Core\" = Exp ) variables for the domain in the current standard Variable Metadata for custom domains will pull from the model while non-custom domains will be from the IG and Model.\n\nInput:\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: expected_variables\n id: $expected_variables\n```\n\nOutput:\n\n```\n[\"LBCAT\", \"LBORRES\", \"LBORRESU\", \"...\"]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -158,13 +120,7 @@ "markdownDescription": "\nFetches controlled terminology attribute values from CT packages based on row-specific CT package and version references. The operation constructs CT package names based on the standard being validated and the values in the `name` and `version` columns (e.g., SDTMIG \u2192 \"sdtmct-{version}\"). When the `name` column contains \"CDISC\" or \"CDISC CT\", it uses the validation run's standard to determine the package prefix and the version found in the cell of the specified column. The operation extracts all codes matching the specified ct_attribute from the package.\n\n**Required Parameters:**\n\n- `ct_attribute`: Attribute to extract - `\"Term CCODE\"`, `\"Codelist CCODE\"`, `\"Term Value\"`, `\"Codelist Value\"`, or `\"Term Preferred Term\"`\n- `name`: Column containing CT reference (e.g., \"TSVCDREF\") - identifies which terminology system is referenced\n- `version`: Column containing CT version (e.g., \"TSVCDVER\")\n\n```yaml\n- id: $VALID_TERM_CODES\n name: TSVCDREF\n operator: get_codelist_attributes\n ct_attribute: Term CCODE\n version: TSVCDVER\n```\n\n**Note:** if using this operator with excel data, you must put the ctpackage versions contained within your data in the library tab for it work properly.\n" } }, - "required": [ - "id", - "operator", - "name", - "ct_attribute", - "version" - ], + "required": ["id", "operator", "name", "ct_attribute", "version"], "type": "object" }, { @@ -174,10 +130,7 @@ "markdownDescription": "\nReturns list of dataset columns in order\n\n```yaml\nCheck:\n all:\n - name: $column_order_from_dataset\n operator: is_not_ordered_by\n value: $column_order_from_library\nOperations:\n - id: $column_order_from_library\n operator: get_column_order_from_library\n - id: $column_order_from_dataset\n operator: get_column_order_from_dataset\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -187,10 +140,7 @@ "markdownDescription": "\nFetches column order for a given domain from the CDISC library. The lists with column names are sorted in accordance to \"ordinal\" key of library metadata.\nOptionally Filters variables based on specified metadata criteria.\n\nRule Type: Variable Metadata Check\n\n```yaml\nCheck:\n all:\n - name: variable_name\n operator: is_not_contained_by\n value: $ig_variables\nOperations:\n - id: $ig_variables\n operator: get_column_order_from_library\n key_name: \"role\" # role, core, etc\n key_value: \"Exp\" # Timing, Req, Exp, Perm, etc\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -200,10 +150,7 @@ "markdownDescription": "\nReturns the list of domains for a given class from the CDISC Library Implementation Guide. This operation retrieves all domains that belong to a specified class (e.g., \"TRIAL DESIGN\", \"FINDINGS\", \"EVENTS\") based on the current standard and version. The operation uses the standard and version from the validation context as well as the optional `domain_class` parameter which is the name of the class to filter by (e.g., \"TRIAL DESIGN\", \"FINDINGS\", \"EVENTS\", \"INTERVENTIONS). NOTE: Class names are case-sensitive and should match the Library metadata format. If no `domain_class` parameter is provided, the operation returns all domains across all classes in the Implementation Guide:\n\n```yaml\n- operator: get_library_class_domains\n id: $trial_design_domains\n domain_class: \"TRIAL DESIGN\"\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -213,10 +160,7 @@ "markdownDescription": "\nFetches column order for a given model class from the CDISC library. The lists with column names are sorted in accordance to \"ordinal\" key of library metadata.\n\nRule Type: Variable Metadata Check\n\n```yaml\nCheck:\n all:\n - name: variable_name\n operator: is_not_contained_by\n value: $model_variables\nOperations:\n - id: $model_variables\n operator: get_model_column_order\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -226,12 +170,7 @@ "markdownDescription": "\nFetches variable level library model properties filtered by the provided key_name and key_value\n\nExample\n\nInput\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: get_model_filtered_variables\n id: $model_filtered_variables\n key_name: \"role\"\n key_value: \"Timing\"\n```\n\nOutput\n\n```\n[\"VISITNUM\", \"VISIT\", \"VISITDY\", \"TAETORD\", \"...\"]\n```\n" } }, - "required": [ - "id", - "operator", - "key_name", - "key_value" - ], + "required": ["id", "operator", "key_name", "key_value"], "type": "object" }, { @@ -241,10 +180,7 @@ "markdownDescription": "\nFetches column order for a given SUPP's parent model class from the CDISC library. The lists with column names are sorted in accordance to \"ordinal\" key of library metadata.\n\n```yaml\nCheck:\n all:\n - operator: is_not_contained_by\n value: $parent_model_variables\nOperations:\n - id: $parent_model_variables\n operator: get_parent_model_column_order\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -254,12 +190,7 @@ "markdownDescription": "\nFilters variables from the dataset based on specified metadata criteria. Returns a list of variable names that exist in the dataset and match the filter criteria.\n\n```yaml\n- operator: get_dataset_filtered_variables\n id: $timing_variables\n key_name: \"role\"\n key_value: \"Timing\"\n```\n" } }, - "required": [ - "id", - "operator", - "key_name", - "key_value" - ], + "required": ["id", "operator", "key_name", "key_value"], "type": "object" }, { @@ -269,11 +200,7 @@ "markdownDescription": "\nGenerates a dataframe where each record in the dataframe is the library ig variable metadata corresponding with the variable label found in the column provided in name. The metadata column names are prefixed with the string provided in `id`.\n\nInput\n\nTarget Dataset: SUPPLB\n\nProduct: sdtmig\n\nVersion: 3-4\n\nDataset:\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QLABEL\": [\"Toxicity\", \"Viscosity\", \"Analysis Method\"]\n}\n```\n\nRule:\n\n```yaml\n- operator: label_referenced_variable_metadata\n id: $qlabel_referenced_variable_metadata\n name: \"QLABEL\"\n```\n\nOutput\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QLABEL\": [\"Toxicity\", \"Viscosity\", \"Analysis Method\"],\n \"$qlabel_referenced_variable_metadata_name\": [\"LBTOX\", null, \"LBANMETH\"],\n \"$qlabel_referenced_variable_metadata_role\": [\n \"Variable Qualifier\",\n null,\n \"Record Qualifier\"\n ],\n \"$qlabel_referenced_variable_metadata_ordinal\": [44, null, 38],\n \"$qlabel_referenced_variable_metadata_core\": [\"Req\", \"Req\", \"Req\"],\n \"$qlabel_referenced_variable_metadata_label\": [\"Toxicity\", null, \"Analysis Method\"]\n}\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -283,11 +210,7 @@ "markdownDescription": "\nAllows the creation of a lookup table to take the values from multiple input columns and map them to values in an output column. The map parameter contains a list of objects. Each dictionary contains column names as properties that match the column names in the source dataset and an output property that will be returned as a result.\n\nIf map has a single object and output is the only property specified on that object, this will function as a direct assignment.\n\nFor example, given the following current dataset:\n\n```\nid \tparent_entity \tparent_rel\n1 \tTiming \trelativeToFrom\n2 \tSomething \trelativeToFrom\n3 \tTiming \ttype\n```\n\nand the following operation:\n\n```yaml\nOperations:\n - id: $codelist_code\n operator: map\n map:\n - parent_entity: Timing\n parent_rel: type\n output: C201264\n - parent_entity: Timing\n parent_rel: relativeToFrom\n output: C201265\n```\n\nThis will result in the following dataset:\n\n```\nid \tparent_entity \tparent_rel \t$codelist_code\n1 \tTiming \trelativeToFrom \tC201265\n2 \tSomething \trelativeToFrom \tNone\n3 \tTiming \ttype \tC201264\n```\n\nThe following operation:\n\n```yaml\nOperations:\n - id: $codelist_code\n operator: map\n map:\n - output: C201264\n```\n\nWill result in the following dataset:\n\n```\nid \tparent_entity \tparent_rel \t$codelist_code\n1 \tTiming \trelativeToFrom \tC201264\n2 \tSomething \trelativeToFrom \tC201264\n3 \tTiming \ttype \tC201264\n```\n" } }, - "required": [ - "id", - "operator", - "map" - ], + "required": ["id", "operator", "map"], "type": "object" }, { @@ -297,11 +220,7 @@ "markdownDescription": "\nIf no group is provided, returns the max value in name. If group is provided, returns the max value in name, within each unique set of the grouping variables.\n\n```yaml\nCheck:\n all:\n - name: \"$max_age\"\n operator: \"greater_than\"\n value: \"MAXAGE\"\nOperations:\n - operator: \"max\"\n domain: \"DM\"\n name: \"AGE\"\n id: \"$max_age\"\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -311,11 +230,7 @@ "markdownDescription": "\nIf no group is provided, returns the max date value in name. If group is provided, returns the max date value in name, within each unique set of the grouping variables.\n\n```yaml\nCheck:\n all:\n - name: USUBJID\n operator: is_contained_by\n value: $ex_usubjid\n - name: RFXENDTC\n operator: not_equal_to\n value: $max_ex_exstdtc\n - name: RFXENDTC\n operator: not_equal_to\n value: $max_ex_exendtc\nOperations:\n - operator: distinct\n domain: EX\n name: USUBJID\n id: $ex_usubjid\n - operator: max_date\n domain: EX\n name: EXSTDTC\n id: $max_ex_exstdtc\n group:\n - USUBJID\n - operator: max_date\n domain: EX\n name: EXENDTC\n id: $max_ex_exendtc\n group:\n - USUBJID\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -325,11 +240,7 @@ "markdownDescription": "\nExample: AAGE > mean(DM.AGE), where AAGE is a fictitious NSV\n\n```yaml\nCheck:\n all:\n - name: \"AAGE\"\n operator: \"greater_than\"\n value: \"$average_age\"\nOperations:\n - operator: \"mean\"\n domain: \"DM\"\n name: \"AGE\"\n id: \"$average_age\"\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -339,11 +250,7 @@ "markdownDescription": "\nIf no group is provided, returns the min value in name. If group is provided, returns the min value in name, within each unique set of the grouping variables.\n\n```yaml\nCheck:\n all:\n - name: \"$min_age\"\n operator: \"less_than\"\n value: \"MINAGE\"\nOperations:\n - operator: \"min\"\n domain: \"DM\"\n name: \"AGE\"\n id: \"$min_age\"\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -353,11 +260,7 @@ "markdownDescription": "\nIf no group is provided, returns the min date value in name. If group is provided, returns the min date value in name, within each unique set of the grouping variables.\n\nExample: RFSTDTC is greater than min AE.AESTDTC for the current USUBJID\n\n```yaml\nCheck:\n all:\n - name: \"RFSTDTC\"\n operator: \"date_greater_than\"\n value: \"$ae_aestdtc\"\nOperations:\n - operator: \"min_date\"\n domain: \"AE\"\n name: \"AESTDTC\"\n id: \"$ae_aestdtc\"\n group:\n - USUBJID\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -367,12 +270,7 @@ "markdownDescription": "\nComputes set difference: elements in `name` that are not in `subtract`. By default a standard [set difference]() semantics (A \u2216 B) is applied. Optional `order_insensitive` property allows to have the element order to be taken into consideration and only those `name` elements are removed which follow the same order as in `subtract` . Preserves order from the first list. Both `name` and `subtract` must reference other operation results (e.g., `$expected_variables`, `$dataset_variables`). When `subtract` is empty or missing, returns all elements from `name`. Can be computed and added to output variables to display missing elements in error results.\n\n```yaml\nOperations:\n - id: $expected_variables\n operator: expected_variables\n - id: $dataset_variables\n operator: get_column_order_from_dataset\n - id: $expected_minus_dataset\n name: $expected_variables\n operator: minus\n subtract: $dataset_variables\n order_insensitive: false\n```\n" } }, - "required": [ - "id", - "operator", - "name", - "subtract" - ], + "required": ["id", "operator", "name", "subtract"], "type": "object" }, { @@ -382,11 +280,7 @@ "markdownDescription": "\nGenerates a dataframe where each record in the dataframe is the library ig variable metadata corresponding with the variable name found in the column provided in name. The metadata column names are prefixed with the string provided in `id`.\n\nInput\n\nTarget Dataset: SUPPLB\n\nProduct: sdtmig\n\nVersion: 3-4\n\nDataset:\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QNAM\": [\"Toxicity\", \"LBVISCOS\", \"Analysis Method\"]\n}\n```\n\nRule:\n\n```yaml\n- operator: name_referenced_variable_metadata\n id: $qnam_referenced_variable_metadata\n name: \"QNAM\"\n```\n\nOutput\n\n```\n{\n \"STUDYID\": [\"STUDY1\", \"STUDY1\", \"STUDY1\"],\n \"USUBJID\": [\"SUBJ1\", \"SUBJ1\", \"SUBJ1\"],\n \"QNAM\": [\"LBTOX\", \"LBVISCOS\", \"LBANMETH\"],\n \"$qnam_referenced_variable_metadata_name\": [\"LBTOX\", null, \"LBANMETH\"],\n \"$qnam_referenced_variable_metadata_role\": [\n \"Variable Qualifier\",\n null,\n \"Record Qualifier\"\n ],\n \"$qnam_referenced_variable_metadata_ordinal\": [44, null, 38],\n \"$qnam_referenced_variable_metadata_core\": [\"Req\", \"Req\", \"Req\"],\n \"$qnam_referenced_variable_metadata_label\": [\"Toxicity\", null, \"Analysis Method\"]\n}\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -396,10 +290,7 @@ "markdownDescription": "\nReturns the permissible variables (\"Core\" = Perm ) for a given domain and standard Variable Metadata for custom domains will pull from the model while non-custom domains will be from the IG and Model.\n\nInput:\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: permissible_variables\n id: $permissible_variables\n```\n\nOutput:\n\n```\n[\"LBGRPID\", \"LBREFID\", \"LBSPID\", \"...\"]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -409,10 +300,7 @@ "markdownDescription": "\nIf no filter or group is provided, returns the number of records in the dataset. If filter is provided, returns the number of records in the dataset that contain the value(s) in the corresponding column(s) provided in the filter. Filter can have a wildcard `&` that when added to the end of the filter value will look for all instances of that prefix (see 4th example below). If group is provided, returns the number of rows matching each unique set of the grouping variables. These can be static column name(s) or can be derived from other operations like get_dataset_filtered_variables.\n\nIf both filter and group are provided, returns the number of records in the dataset that contain the value(s) in the corresponding column(s) provided in the filter that also match each unique set of the grouping variables.\n\n**Wildcard Filtering:** Filter values ending with % will match any records where the column value starts with the specified prefix. For example, RACE% will match RACE1, RACE2, RACE3, etc. This is useful for matching related variables with numeric or alphabetic suffixes.\n\n**Regex Transformation:** If regex is provided along with group, the regex pattern will be applied to transform grouping column values before grouping. The regex is only applied to columns where the pattern matches the data type. For example, using regex `^\\d{4}-\\d{2}-\\d{2}` on a column containing `2022-01-14T08:00` will extract `2022-01-14` for grouping purposes.\n\nIf group is provided, group_aliases may also be provided to assign new grouping variable names so that results grouped by the values in one set of grouping variables can be merged onto a dataset according to the same grouping value(s) stored in different set of grouping variables. When both group and group_aliases are provided, columns are renamed according to corresponding list position (i.e., the 1st column in group is renamed to the 1st column in group_aliases, etc.). If there are more columns listed in group than in group_aliases, only the group columns with corresponding group_aliases columns will be renamed. If there are more columns listed in group_aliases than in group, the extra column names in group_aliases will be ignored.\n\nExample: return the number of records in a dataset.\n\n```yaml\n- operator: record_count\n id: $records_in_dataset\n```\n\nExample: return the number of records where STUDYID = \"CDISC01\" and FLAGVAR = \"Y\".\n\n```yaml\n- operator: record_count\n id: $flagged_cdisc01_records_in_dataset\n filter:\n STUDYID: \"CDISC01\"\n FLAGVAR: \"Y\"\n```\n\nExample: return the number of records grouped by USUBJID and timing variables, extracting only the date portion from datetime values.\n\n```yaml\n- operator: record_count\n id: $records_per_usubjid_date\n group:\n - USUBJID\n - --TESTCD\n - $TIMING_VARIABLES\n regex: \"^\\d{4}-\\d{2}-\\d{2}\"\n```\n\nExample: return the number of records where QNAM starts with \"RACE\" (matches RACE1, RACE2, RACE3, etc.) per USUBJID.\n\n```yaml\n- operator: record_count\n id: $race_records_in_dataset\n filter:\n QNAM: \"RACE&\"\n group:\n - \"USUBJID\"\n```\n\nExample: return the number of records grouped by USUBJID.\n\n```yaml\n- operator: record_count\n id: $records_per_usubjid\n group:\n - USUBJID\n```\n\nExample: return the number of records grouped by USUBJID where FLAGVAR = \"Y\".\n\n```yaml\n- operator: record_count\n id: $flagged_records_per_usubjid\n group:\n - USUBJID\n filter:\n FLAGVAR: \"Y\"\n```\n\nExample: return the number of records grouped by USUBJID and IDVARVAL where QNAM = \"TEST1\" and IDVAR = \"GROUPID\", renaming the IDVARVAL column to GROUPID for subsequent merging.\n\n```yaml\n- operator: record_count\n id: $test1_records_per_usubjid_groupid\n group:\n - USUBJID\n - IDVARVAL\n filter:\n QNAM: \"TEST1\"\n IDVAR: \"GROUPID\"\n group_aliases:\n - USUBJID\n - GROUPID\n```\n\nExample: Group the StudyIdentifier dataset by parent_id and merge the result back to the context dataset StudyVersion using StudyVersion.id == StudyIdentifier.parent_id\n\n```yaml\nScope:\n Entities:\n Include:\n - StudyVersion\nOperations:\n - domain: StudyIdentifier\n filter:\n parent_entity: \"StudyVersion\"\n parent_rel: \"studyIdentifiers\"\n rel_type: \"definition\"\n studyIdentifierScope.organizationType.code: \"C70793\"\n studyIdentifierScope.organizationType.codeSystem: \"http://www.cdisc.org\"\n group:\n - parent_id\n group_aliases:\n - id\n id: $num_sponsor_ids\n operator: record_count\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -422,10 +310,7 @@ "markdownDescription": "\nReturns the required variables ( \"Core\" = Req ) for a given domain and standard Variable Metadata for custom domains will pull from the model while non-custom domains will be from the IG and Model.\n\nInput:\n\nTarget Domain: LB\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\n- operator: required_variables\n id: $required_variables\n```\n\nOutput:\n\n```\n[\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"LBSEQ\", \"LBTESTCD\", \"LBTEST\"]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -435,12 +320,7 @@ "markdownDescription": "\nSplits a dataset column by a given delimiter\n\n```yaml\nOperations:\n - name: PPSPEC\n delimiter: ;\n id: $ppspec_value\n operator: split_by\n```\n" } }, - "required": [ - "id", - "operator", - "delimiter", - "name" - ], + "required": ["id", "operator", "delimiter", "name"], "type": "object" }, { @@ -450,10 +330,7 @@ "markdownDescription": "\nReturns a list of the domains in the study\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -463,10 +340,7 @@ "markdownDescription": "\nReturns a list of the submitted dataset filenames in all uppercase\n\nex. if TS.xpt, AE.xpt, EC.xpt, and SUPPEC.xpt are submitted -> [TS, AE, EC, SUPPEC] will be returned\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -476,10 +350,7 @@ "markdownDescription": "\nReturns a list of valid SDTM domain names from the standard metadata. This can be used to compare extracted suffixes from DOMAIN values or dataset names.\n\nInput\n\nProduct: sdtmig\n\nVersion: 3-4\n\n```yaml\nOperations:\n - operator: standard_domains\n id: $valid_domain_names\n```\n\nOutput\n\n```\n[\"AE\", \"CM\", \"DM\", \"FA\", \"LB\", \"QS\", ...]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -489,10 +360,7 @@ "markdownDescription": "\nReturns the valid terminology package dates for a given standard.\n\nGiven a list of terminology packages:\n\n```\n[\n \"sdtmct-2023-10-26\",\n \"sdtmct-2023-12-13\",\n \"adamct-2023-12-13\",\n \"cdashct-2023-05-19\"\n]\n```\n\nand standard: sdtmig\n\nthe operation will return:\n\n```\n[\"2023-10-26\", \"2023-12-13\"]\n```\n\nBy default, the standard is as specified when running validation - as the validation runtime parameter and/or as specified in the rule header - and the list of terminology packages is obtained from the current cache. If required, the default standard may be overridden using the optional ct_package_types parameter. For example, given the same list of terminology packages, the following operation:\n\n```yaml\nOperations:\n - operator: valid_codelist_dates\n id: $valid_dates\n ct_package_types:\n - SDTM\n - CDASH\n```\n\nwill return:\n\n```\n[\"2023-05-19\", \"2023-10-26\", \"2023-12-13\"]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -502,11 +370,7 @@ "markdownDescription": "\nReturns true if the version of an external dictionary provided in the define.xml file matches the version parsed from the dictionary files.\n\nInput:\n\n```yaml\nOperations:\n - operator: valid_define_external_dictionary_version\n id: $is_valid_loinc_version\n external_dictionary_type: loinc\n```\n\nOutput:\n\n```\n[true, true, true, true]\n```\n" } }, - "required": [ - "id", - "operator", - "external_dictionary_type" - ], + "required": ["id", "operator", "external_dictionary_type"], "type": "object" }, { @@ -564,10 +428,7 @@ "markdownDescription": "\nDetermines whether the values are valid in the following variables:\n\n- --SOCCD (System Organ Class Code)\n- --HLGTCD (High Level Group Term Code)\n- --HLTCD (High Level Term Code)\n- --PTCD (Preferred Term Code)\n- --LLTCD (Lowest Level Term Code)\n\nInput:\n\n```yaml\nOperations:\n - id: $is_valid_meddra_codes\n operator: valid_meddra_code_references\n```\n\nOutput:\n\n```\n[true, false, true, true]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -577,10 +438,7 @@ "markdownDescription": "\nDetermines whether the values are valid in the following variable pairs:\n\n- --SOCCD, --SOC (System Organ Class Code and Term)\n- --HLGTCD, --HLGT (High Level Group Term Code and Term)\n- --HLTCD, --HLT (High Level Term Code and Term)\n- --PTCD, --DECOD (Preferred Term Code and Dictionary-Derived Term)\n- --LLTCD, --LLT (Lowest Level Term Code and Term)\n\nInput:\n\n```yaml\nOperations:\n - id: $is_valid_meddra_pairs\n operator: valid_meddra_code_term_pairs\n```\n\nOutput:\n\n```\n[true, true, false, true, true]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -590,10 +448,7 @@ "markdownDescription": "\nDetermines whether the values are valid in the following variables:\n\n- --SOC (System Organ Class)\n- --HLGT (High Level Group Term)\n- --HLT (High Level Term)\n- --DECOD (Dictionary-Derived Term)\n- --LLT (Lowest Level Term)\n\nInput:\n\n```yaml\nOperations:\n - id: $is_valid_meddra_terms\n operator: valid_meddra_term_references\n```\n\nOutput:\n\n```\n[true, true, false, true, true]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -603,11 +458,7 @@ "markdownDescription": "\nChecks if a reference to whodrug term in name points to the existing code in Atc Text (INA) file.\n\nInput:\n\n```yaml\nOperations:\n - id: $whodrug_refs_valid\n operator: valid_whodrug_references\n```\n\nOutput:\n\n```\n[true, false, true, true]\n```\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -617,10 +468,7 @@ "markdownDescription": "\nReturns a mapping of variable names to the number of times that variable appears in a domain within the study.\n\nInput\n\n```\n{\n \"AE\": [\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"AETERM\", \"AEENDTC\"],\n \"LB\": [\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"LBTESTCD\", \"LBENDTC\"]\n}\n```\n\nOutput\n\n```\n{\n \"STUDYID\": 2,\n \"DOMAIN\": 2,\n \"USUBJID\": 2,\n \"--TERM\": 1,\n \"--TESTCD\": 1,\n \"--ENDTC\": 2\n}\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -630,10 +478,7 @@ "markdownDescription": "\nOperation operates only on original submission datasets regardless of rule type. Flags an error if a column exists is in the submission dataset currently being evaluated.\n\nRule Type: Domain Presence Check\n\n```yaml\nCheck:\n all:\n - name: $MIDS_EXISTS\n operator: equal_to\n value: true\n - name: TM\n operator: not_exists\nOperations:\n - id: $MIDS_EXISTS\n name: MIDS\n operator: variable_exists\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -643,10 +488,7 @@ "markdownDescription": "\nReturns true if a variable is missing from the dataset or if all values within the variable are null or empty string. This operation first checks if the target variable exists in the dataset, and if it does exist, evaluates whether all its values are null or empty.\nThe operation supports two sources via the `source` parameter:\n\n- **`submission`** : checks against the raw submission dataset\n- **`evaluation`** (default): checks against the evaluation dataset built based on the rule type\n\n```yaml" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -656,10 +498,7 @@ "markdownDescription": "\nReturns the set of variable names from the library for the given standard. This operation extracts all variable names across all domains in the specified standard's library metadata.\n\nInput:\n\nValidation Standard: sdtmig\nValidation Version: 3-4\n\n```yaml\n- operator: variable_names\n id: $all_variables\n```\n\nOutput:\n\n```\n[\"STUDYID\", \"DOMAIN\", \"USUBJID\", \"SUBJID\", \"RFSTDTC\", \"RFENDTC\", \"SITEID\", \"AGE\", \"AGEU\", \"SEX\", \"RACE\", \"ETHNIC\", \"ARMCD\", \"ARM\", \"ACTARMCD\", \"ACTARM\", \"COUNTRY\", \"DMDTC\", \"DMDY\", \"AETERM\", \"AEDECOD\", \"AECAT\", \"AESCAT\", \"AEPRESP\", \"AEBODSYS\", \"AEBDSYCD\", \"AESOC\", \"AESOCCD\", \"AELLT\", \"AELLTCD\", \"AEHLT\", \"AEHLTCD\", \"AEHLGT\", \"AEHLGTCD\", \"AEPTCD\", \"AESTDTC\", \"AEENDTC\", \"AESTDY\", \"AEENDY\", \"AEDUR\", \"AESER\", \"AESEV\", \"AEACN\", \"AEREL\", \"AEOUT\", \"AESCAN\", \"AESCONG\", \"AESDISAB\", \"AESDTH\", \"AESHOSP\", \"AESLIFE\", \"AESOD\", \"AECONTRT\", \"AETOXGR\", \"LBTESTCD\", \"LBTEST\", \"LBCAT\", \"LBSCAT\", \"LBSPEC\", \"LBMETHOD\", \"LBORRES\", \"LBORRESU\", \"LBORNRLO\", \"LBORNRHI\", \"LBSTRESC\", \"LBSTRESN\", \"LBSTRESU\", \"LBSTNRLO\", \"LBSTNRHI\", \"LBNRIND\", \"LBNAM\", \"LBSPEC\", \"LBANTREG\", \"LBFAST\", \"LBDRVFL\", \"LBTOX\", \"LBTOXGR\", \"LBSTDTC\", \"LBENDTC\", \"LBSTDY\", \"LBENDY\", \"LBTPT\", \"LBTPTNUM\", \"LBELTM\", \"LBTPTREF\", \"LBRFTDTC\", \"...\"]\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -669,11 +508,7 @@ "markdownDescription": "\nGiven a variable name, returns a mapping of variable values to the number of times that value appears in the variable within all datasets in the study.\n" } }, - "required": [ - "id", - "operator", - "name" - ], + "required": ["id", "operator", "name"], "type": "object" }, { @@ -683,10 +518,7 @@ "markdownDescription": "\nDetermines whether the values are valid and in the correct hierarchical structure in the following variables:\n\n- --DECOD\n- --CLAS\n- --CLASCD\n\nInput:\n\n```yaml\nOperations:\n - id: $valid_whodrug_codes\n operator: whodrug_code_hierarchy\n```\n" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" }, { @@ -696,12 +528,7 @@ "markdownDescription": "\nValidates XHTML fragments in the target column against the specified namespace.\n\n```yaml\nOperations:\n - id: $xhtml_errors\n name: text\n operator: get_xhtml_errors\n namespace: http://www.cdisc.org/ns/usdm/xhtml/v1.0\n```\n\nNote that a local XSD file is required for validation. The file must be stored in the folder indicated by the value of the `LOCAL_XSD_FILE_DIR` default file path and the mapping between the namespace and the local XSD file's `sub-folder/name` must be included in the value of the `LOCAL_XSD_FILE_MAP` default file path.\n" } }, - "required": [ - "id", - "operator", - "name", - "namespace" - ], + "required": ["id", "operator", "name", "namespace"], "type": "object" } ], @@ -764,13 +591,7 @@ "type": "string" }, "dictionary_term_type": { - "enum": [ - "LLT", - "PT", - "HLT", - "HLGT", - "SOC" - ] + "enum": ["LLT", "PT", "HLT", "HLGT", "SOC"] }, "domain": { "anyOf": [ @@ -783,9 +604,7 @@ ] }, "external_dictionary_type": { - "enum": [ - "meddra" - ] + "enum": ["meddra"] }, "filter": { "type": "object" @@ -830,10 +649,7 @@ }, "level": { "type": "string", - "enum": [ - "codelist", - "term" - ] + "enum": ["codelist", "term"] }, "map": { "type": "array", @@ -844,9 +660,7 @@ "type": "string" } }, - "required": [ - "output" - ] + "required": ["output"] } }, "name": { @@ -863,11 +677,7 @@ }, "returntype": { "type": "string", - "enum": [ - "code", - "value", - "pref_term" - ] + "enum": ["code", "value", "pref_term"] }, "source": { "type": "string" @@ -894,9 +704,6 @@ "type": "string" } }, - "required": [ - "id", - "operator" - ], + "required": ["id", "operator"], "type": "object" } diff --git a/resources/schema/rule-merged/Operator.json b/resources/schema/rule-merged/Operator.json index f3a269a4d..e1b988e6a 100644 --- a/resources/schema/rule-merged/Operator.json +++ b/resources/schema/rule-merged/Operator.json @@ -9,9 +9,7 @@ "const": "additional_columns_empty" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -20,9 +18,7 @@ "const": "additional_columns_not_empty" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -32,10 +28,7 @@ "markdownDescription": "\nWill return True if the value in `value` is contained within the collection/iterable in the target column, or if there's an exact match for non-iterable data.\n\nThe operator checks if every value in a column is a list or set. If yes, it compares row-by-row. If any value is blank or a different type (like a string or number), it compares each value against the entire column instead.\n\nExample:\n\n```yaml\n- name: \"--TOXGR\" # Column containing lists like ['GRADE', 'SEVERITY', 'ONSET']\n operator: \"contains\"\n value: \"GRADE\" # True if 'GRADE' is an element in the list\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -45,9 +38,7 @@ "markdownDescription": "\nTrue if all values in `value` are contained within the variable `name`.\n\n> All of ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment') in ACTARM\n\n```yaml\n- name: \"ACTARM\"\n operator: \"contains_all\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n\nThe operator also supports lists:\n\n```yaml\n- name: \"$spec_codelist\"\n operator: \"contains_all\"\n value: \"$ppspec_value\"\n```\n\nWhere:\n\n| $spec_codelist | $ppspec_value |\n| :-------------------------- | :----------------: |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\", \"CODE2\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE2\", \"CODE3\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\"] |\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -57,10 +48,7 @@ "markdownDescription": "\nTrue if the value in `value` is contained within the collection/iterable in the target column, performing case-insensitive comparison.\n\nExample:\n\n```yaml\n- name: \"--TOXGR\" # Column containing lists like ['Grade', 'Severity', 'Onset']\n operator: \"contains_case_insensitive\"\n value: \"grade\" # True if 'Grade'/'GRADE'/'grade' exists in the list\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -70,10 +58,7 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified.\n\nThe `date_component` parameter accepts: `\"year\"`, `\"month\"`, `\"day\"`, `\"hour\"`, `\"minute\"`, `\"second\"`, `\"microsecond\"`, or `\"auto\"`.\n\nWhen `date_component: \"auto\"` is used, the operator automatically detects the precision of both dates and compares at the common (less precise) level.\n\n```yaml\n- name: \"AESTDTC\"\n operator: \"date_equal_to\"\n value: \"RFSTDTC\"\n date_component: \"auto\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -83,10 +68,7 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> Year part of BRTHDTC > 2021\n\n```yaml\n- name: \"BRTHDTC\"\n operator: \"date_greater_than\"\n date_component: \"year\"\n value: \"2021\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -96,10 +78,7 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> Year part of BRTHDTC >= 2021\n\n```yaml\n- name: \"BRTHDTC\"\n operator: \"date_greater_than_or_equal_to\"\n date_component: \"year\"\n value: \"2021\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -109,10 +88,7 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> AEENDTC < AESTDTC\n\n```yaml\n- name: \"AEENDTC\"\n operator: \"date_less_than\"\n value: \"AESTDTC\"\n```\n\n> SSDTC < all DS.DSSTDTC when SSSTRESC = \"DEAD\"\n\n```yaml\nCheck:\n all:\n - name: \"SSSTRESC\"\n operator: \"equal_to\"\n value: \"DEAD\"\n - name: \"SSDTC\"\n operator: \"date_less_than\"\n value: \"$max_ds_dsstdtc\"\nOperations:\n - operator: \"max_date\"\n domain: \"DS\"\n name: \"DSSTDTC\"\n id: \"$max_ds_dsstdtc\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -122,10 +98,7 @@ "markdownDescription": "\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n\n> AEENDTC <= AESTDTC\n\n```yaml\n- name: \"AEENDTC\"\n operator: \"date_less_than_or_equal_to\"\n value: \"AESTDTC\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -135,10 +108,7 @@ "markdownDescription": "\nComplement of `date_equal_to`\n\nDate comparison. Compare `name` to `value`. Compares partial dates if `date_component` is specified. Supports `date_component: \"auto\"`.\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -148,10 +118,7 @@ "markdownDescription": "\nComplement of `contains`. Returns True when the value is NOT contained within the target collection.\n\n```yaml\n- name: \"--TOXGR\"\n operator: \"does_not_contain\"\n value: \"GRADE\" # True if 'GRADE' is NOT an element in the list\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -161,10 +128,7 @@ "markdownDescription": "\nComplement of `contains_case_insensitive`. Returns True when the value is NOT contained within the target collection (case-insensitive).\n\nExample:\n\n```yaml\n- name: \"--TOXGR\"\n operator: \"does_not_contain_case_insensitive\"\n value: \"grade\" # True if no case variation of 'grade' exists in the list\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -177,11 +141,7 @@ "type": "boolean" } }, - "required": [ - "operator", - "value", - "regex" - ], + "required": ["operator", "value", "regex"], "type": "object" }, { @@ -191,12 +151,7 @@ "markdownDescription": "\nComplement of `has_next_corresponding_record`\n" } }, - "required": [ - "operator", - "ordering", - "value", - "within" - ], + "required": ["operator", "ordering", "value", "within"], "type": "object" }, { @@ -206,9 +161,7 @@ "markdownDescription": "\nValue presence\n\n> --OCCUR = null\n\n```yaml\n- name: --OCCUR\n operator: empty\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -218,10 +171,7 @@ "markdownDescription": "\n> SEENDTC is not empty when it is not the last record, grouped by USUBJID, sorted by SESTDTC\n\n```yaml\n- name: SEENDTC\n operator: empty_within_except_last_row\n ordering: SESTDTC\n value: USUBJID\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -231,10 +181,7 @@ "markdownDescription": "\nSubstring matching\n\n> DOMAIN ending with 'FOOBAR'\n\n```yaml\n- name: \"DOMAIN\"\n operator: \"ends_with\"\n value: \"FOOBAR\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -253,10 +200,7 @@ "type": "boolean" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -275,10 +219,7 @@ "type": "boolean" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -291,11 +232,7 @@ "type": "boolean" } }, - "required": [ - "operator", - "value", - "regex" - ], + "required": ["operator", "value", "regex"], "type": "object" }, { @@ -305,9 +242,7 @@ "markdownDescription": "\nTrue if the column exists in the current dataframe. (Works for datasets and variables)\n\n> --OCCUR is present in dataset\n\n```yaml\n- name: \"--OCCUR\"\n operator: \"exists\"\n```\n\n> Domain SJ exists\n\n```yaml\nRule Type: Domain Presence Check\nCheck:\n all:\n - name: \"SJ\"\n operator: \"exists\"\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -317,10 +252,7 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL > 0\n\n```yaml\n- name: TSVAL\n operator: greater_than\n value: 0\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -330,10 +262,7 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL >= 0\n\n```yaml\n- name: TSVAL\n operator: greater_than_or_equal_to\n value: 1\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -343,9 +272,7 @@ "markdownDescription": "\nComplement of `has_same_values`\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -355,9 +282,7 @@ "markdownDescription": "\nLength comparison\n\n> Check whether variable values has equal length of another variable.\n\n```yaml\n- name: SEENDTC\n operator: has_equal_length\n value: SESTDTC\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -367,12 +292,7 @@ "markdownDescription": "\nEnsures that a value of a variable `name` in one record is equal to the value of another variable `value` in the next corresponding record. The rows are grouped by `within` and ordered by `ordering`.\n\n> SEENDTC is equal to the SESTDTC of the next record within a USUBJID. Ordered by SESEQ\n\n```yaml\n- name: SEENDTC\n operator: has_next_corresponding_record\n value: SESTDTC\n within: USUBJID\n ordering: SESEQ\n```\n" } }, - "required": [ - "operator", - "ordering", - "value", - "within" - ], + "required": ["operator", "ordering", "value", "within"], "type": "object" }, { @@ -382,9 +302,7 @@ "markdownDescription": "\nComplement of `has_equal_length`\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -394,9 +312,7 @@ "markdownDescription": "\nTrue if all values in `name` are the same\n\n> Condition: MHCAT ^= null\n> Rule: MHCAT ^= the same value for all records\n\n```yaml\nCheck:\n all:\n - name: MHCAT\n operator: non_empty\n - name: MHCAT\n operator: has_same_values\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -406,10 +322,7 @@ "markdownDescription": "\nDuration ISO-8601 check, returns True if a duration is not in ISO-8601 format. The negative parameter must be specified to indicate if negative durations are either allowed (True) or disallowed (False)\n\n> DURVAR is invalid (negative durations disallowed)\n\n```yaml\n- name: \"DURVAR\"\n operator: \"invalid_duration\"\n negative: False\n```\n" } }, - "required": [ - "operator", - "negative" - ], + "required": ["operator", "negative"], "type": "object" }, { @@ -419,9 +332,7 @@ "markdownDescription": "\nThe operator performs date validation against complete and partial dates with uncertainty in the following order:\n\n1. Attempts to parse using [dateutil.parser.isoparse()](https://dateutil.readthedocs.io/en/stable/parser.html)\n2. If parsing fails and the string contains uncertainty indicators (`/`, `--`, `-:`), validates against an extended ISO 8601 dates regex pattern\n3. If parsing succeeds, dates are still validated against the regex pattern.\n\n```yaml\n- name: \"BRTHDTC\"\n operator: \"invalid_date\"\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -431,9 +342,7 @@ "markdownDescription": "\nDate check\n\n> DM.RFSTDTC = complete date\n\n```yaml\n- name: \"RFSTDTC\"\n operator: \"is_complete_date\"\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -443,10 +352,7 @@ "markdownDescription": "\nValue in `name` compared against a list in `value`. The list can have literal values or be a reference to a `$variable`.\n\nThis operator behaves similarly to `contains`. The key distinction: `contains` checks if comparator \u2208 target, while `is_contained_by` checks if target \u2208 comparator.\n\n> ACTARM in ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment')\n\n```yaml\n- name: \"ACTARM\"\n operator: \"is_contained_by\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -456,10 +362,7 @@ "markdownDescription": "\nValue in `name` case insensitive compared against a list in `value`. The list can have literal values or be a reference to a `$variable`.\n\n> ACTARM in ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment')\n\n```yaml\n- name: \"ACTARM\"\n operator: \"is_contained_by_case_insensitive\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -469,9 +372,7 @@ "markdownDescription": "\nComplement of `is_complete_date`\n\nDate check\n\n> DM.RFSTDTC ^= complete date\n\n```yaml\n- name: \"RFSTDTC\"\n operator: \"is_incomplete_date\"\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -481,10 +382,7 @@ "markdownDescription": "\nComplement of `is_contained_by`\n\n> ARM not in ('Screen Failure', 'Not Assigned')\n\n```yaml\n- name: \"ARM\"\n operator: \"is_not_contained_by\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -494,10 +392,7 @@ "markdownDescription": "\nComplement of `is_contained_by_case_insensitive`\n\n> ARM not in ('Screen Failure', 'Not Assigned')\n\n```yaml\n- name: \"ARM\"\n operator: \"is_not_contained_by_case_insensitive\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -507,10 +402,7 @@ "markdownDescription": "\nComplement of `is_ordered_by`\n" } }, - "required": [ - "operator", - "order" - ], + "required": ["operator", "order"], "type": "object" }, { @@ -519,10 +411,7 @@ "const": "is_not_ordered_set" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -532,10 +421,7 @@ "markdownDescription": "\nComplement of `is_unique_relationship`\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -545,9 +431,7 @@ "markdownDescription": "\nComplement of `is_unique_set`.\n\n> --SEQ is not unique within DOMAIN, USUBJID, and --TESTCD\n\n```yaml\n- name: \"--SEQ\"\n operator: is_not_unique_set\n value:\n - \"DOMAIN\"\n - \"USUBJID\"\n - \"--TESTCD\"\n```\n\n> `name` can be a variable containing a list of columns and `value` does not need to be present\n\n```yaml\nRule Type: Dataset Contents Check against Define XML\nCheck:\n all:\n - name: define_dataset_key_sequence # contains list of dataset key columns\n operator: is_not_unique_set\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -557,10 +441,7 @@ "markdownDescription": "\nTrue if the dataset rows are ordered by the values within `name`, given the ordering specified by `order`\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n operator: is_ordered_by\n order: asc\n```\n" } }, - "required": [ - "operator", - "order" - ], + "required": ["operator", "order"], "type": "object" }, { @@ -570,10 +451,7 @@ "markdownDescription": "\nTrue if the dataset rows are in ascending order of the values within `name`, grouped by the values within `value`. Value can either be a single column or multiple.\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n operator: is_ordered_set\n value: USUBJID\n```\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n operator: is_ordered_set\n value:\n - USUBJID\n - \"--TESTCD\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -583,10 +461,7 @@ "markdownDescription": "\nRelationship Integrity Check looking for a 1-1 relationship between name and value. Ensures uniqueness of both name and value.\n\n> AETERM and AEDECOD has a 1-to-1 relationship\n\n```yaml\n- name: AETERM\n operator: is_unique_relationship\n value: AEDECOD\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -596,10 +471,7 @@ "markdownDescription": "\nChecks if a variable maintains consistent values within groups defined by one or more grouping variables. Groups records by specified value(s) and validates that the target variable maintains the same value within each unique combination of grouping variables. When inconsistency is detected within a group, the operator attempts to identify a majority value. If one value appears more frequently than all others, only the minority records (those not matching the majority value) are flagged. If no single majority exists \u2014 i.e., two or more values are tied for the highest frequency \u2014 all records in that group are flagged.\n\nSingle grouping variable - true if the values of BGSTRESU differ within USUBJID:\n\nIf a regex parameter is provided, it is applied to the values of the target variable before the consistency check. The first capture group of the regex is used as the normalized value for comparison. This can be useful when only part of the value should be considered during comparison (for example, comparing only the date portion of a datetime value).\n\n- regex is optional.\n- The pattern must include at least one capture group(or whole regex will be wrapped to capture group).\n- Only the first capture group is used for comparison.\n- If the pattern does not match a value, the original value is used.\n\n```yaml\n- name: \"BGSTRESU\"\n operator: is_inconsistent_across_dataset\n value: \"USUBJID\"\n```\n\nMultiple grouping variables - true if the values of --STRESU differ within each combination of --TESTCD, --CAT, --SCAT, --SPEC, and --METHOD:\n\n```yaml\n- name: \"--STRESU\"\n operator: is_inconsistent_across_dataset\n value:\n - \"--TESTCD\"\n - \"--CAT\"\n - \"--SCAT\"\n - \"--SPEC\"\n - \"--METHOD\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -609,9 +481,7 @@ "markdownDescription": "\nRelationship Integrity Check\n\n> --SEQ is unique within DOMAIN, USUBJID, and --TESTCD\n\n```yaml\n- name: \"--SEQ\"\n operator: is_unique_set\n value:\n - \"DOMAIN\"\n - \"USUBJID\"\n - \"--TESTCD\"\n```\n\n> `name` can be a variable containing a list of columns and `value` does not need to be present\n\n> The `regex` parameter allows you to extract portions of values using a regex pattern before checking uniqueness.\n\n> Compare date only (YYYY-MM-DD) for uniqueness\n\n```yaml\n- name: \"--REPNUM\"\n operator: is_not_unique_set\n value:\n - \"USUBJID\"\n - \"--TESTCD\"\n - \"$TIMING_VARIABLES\"\n regex: '^\\d{4}-\\d{2}-\\d{2}'\n```\n\n> Compare by first N characters of a string\n\n```yaml\n- name: \"ITEM_ID\"\n operator: is_not_unique_set\n value:\n - \"USUBJID\"\n - \"CATEGORY\"\n regex: \"^.{2}\"\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -621,10 +491,7 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL < 1\n\n```yaml\n- name: TSVAL\n operator: less_than\n value: 1\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -634,10 +501,7 @@ "markdownDescription": "\nValue comparison\n\n> TSVAL <= 1\n\n```yaml\n- name: TSVAL\n operator: less_than_or_equal_to\n value: 1\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -647,10 +511,7 @@ "markdownDescription": "\nLength comparison\n\n> SETCD value length > 8\n\n```yaml\n- name: \"SETCD\"\n operator: \"longer_than\"\n value: 8\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -660,10 +521,7 @@ "markdownDescription": "\nLength comparison\n\n> TSVAL value length >= 201\n\n```yaml\n- name: \"TSVAL\"\n operator: \"longer_than_or_equal_to\"\n value: 201\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -673,10 +531,7 @@ "markdownDescription": "\nRegular Expression value matching\n\n- Determine if each string starts with a match of a regular expression. Refer to this pandas documentation: https://pandas.pydata.org/docs/reference/api/pandas.Series.str.match.html\n- To \"search\" for a regex within the entire text, prefix the regex with `.*` and do not use anchors `^` , `$`\n- To do a \"fullmatch\" of a regex with the entire text, suffix the regex with an anchor `$` and do not prefix the regex with `.*`\n- For syntax guide, refer to this Python documentation: [Regular Expression HOWTO](https://docs.python.org/3/howto/regex.html).\n- Suggestion for an on-line regular expression logic. tester: https://regex101.com, choose the Python dialect.\n- For regex token visualization, try https://www.debuggex.com.\n\n> --DOSTXT value is non-numeric\n\n```yaml\n- name: --DOSTXT\n operator: matches_regex\n value: ^\\d*\\.?\\d*$\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -686,9 +541,7 @@ "markdownDescription": "\nComplement of `empty`\n\n> --OCCUR ^= null\n\n```yaml\n- name: --OCCUR\n operator: non_empty\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -698,10 +551,7 @@ "markdownDescription": "\nComplement of `empty_within_except_last_row`\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -711,9 +561,7 @@ "markdownDescription": "\nComplement of `contains_all`\n\n> All of ('Screen Failure', 'Not Assigned', 'Not Treated', 'Unplanned Treatment') not in ACTARM\n\n```yaml\n- name: \"ACTARM\"\n operator: \"not_contains_all\"\n value:\n - \"Screen Failure\"\n - \"Not Assigned\"\n - \"Not Treated\"\n - \"Unplanned Treatment\"\n```\n\nThe operator also supports lists:\n\n```yaml\n- name: \"$spec_codelist\"\n operator: \"not_contains_all\"\n value: \"$ppspec_value\"\n```\n\nWhere:\n\n| $spec_codelist | $ppspec_value |\n| :-------------------------- | :----------------: |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\", \"CODE2\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE2\", \"CODE3\"] |\n| [\"CODE1\", \"CODE2\", \"CODE3\"] | [\"CODE1\"] |\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -732,10 +580,7 @@ "type": "boolean" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -754,10 +599,7 @@ "type": "boolean" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -767,9 +609,7 @@ "markdownDescription": "\nComplement of `exists`\n\n> AEOCCUR not present in dataset\n\n```yaml\n- name: \"AEOCCUR\"\n operator: \"not_exists\"\n```\n\n> Domain SJ does not exist\n\n```yaml\nRule Type: Domain Presence Check\nCheck:\n all:\n - name: \"SJ\"\n operator: \"not_exists\"\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -779,10 +619,7 @@ "markdownDescription": "\nComplement of `matches_regex`\n\n> --TESTCD <= 8 chars and contains only letters, numbers, and underscores and can not start with a number\n\n```yaml\n- name: --TESTCD\n operator: not_matches_regex\n value: ^[A-Z_][A-Z0-9_]{0,7}$\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -792,11 +629,7 @@ "markdownDescription": "\nComplement of `prefix_matches_regex`\n" } }, - "required": [ - "operator", - "prefix", - "value" - ], + "required": ["operator", "prefix", "value"], "type": "object" }, { @@ -806,10 +639,7 @@ "markdownDescription": "\nComplement of `present_on_multiple_rows_within`\n\n```yaml\n- operator: \"not_present_on_multiple_rows_within\"\n name: \"RELID\"\n value: 4 (optional)\n within: \"USUBJID\"\n```\n" } }, - "required": [ - "operator", - "within" - ], + "required": ["operator", "within"], "type": "object" }, { @@ -819,11 +649,7 @@ "markdownDescription": "\nComplement of `suffix_matches_regex`\n\n> QNAM does not end with numbers\n\n```yaml\n- name: \"QNAM\"\n operator: \"not_suffix_matches_regex\"\n suffix: 2\n value: \"\\d\\d\"\n```\n" } }, - "required": [ - "operator", - "suffix", - "value" - ], + "required": ["operator", "suffix", "value"], "type": "object" }, { @@ -833,11 +659,7 @@ "markdownDescription": "\nTrue if the `prefix` number of characters beginning a string in `name` match one of the strings in the list in `value`\n\n> Check if a variable's domain identifier exists in the study\n\n```yaml\n- name: variable_name\n operator: prefix_is_contained_by\n prefix: 2\n value: $study_domains\n```\n" } }, - "required": [ - "operator", - "prefix", - "value" - ], + "required": ["operator", "prefix", "value"], "type": "object" }, { @@ -847,11 +669,7 @@ "markdownDescription": "\nTrue if the `prefix` number of characters beginning a string in `name` match the string in `value`\n\n```yaml\n- name: dataset_name\n operator: prefix_equal_to\n prefix: 2\n value: DOMAIN\n```\n" } }, - "required": [ - "operator", - "prefix", - "value" - ], + "required": ["operator", "prefix", "value"], "type": "object" }, { @@ -861,11 +679,7 @@ "markdownDescription": "\nComplement of `prefix_is_contained_by`\n" } }, - "required": [ - "operator", - "prefix", - "value" - ], + "required": ["operator", "prefix", "value"], "type": "object" }, { @@ -875,11 +689,7 @@ "markdownDescription": "\nTrue if the `prefix` number of characters beginning a string in `name` match a regular expression in `value`\n\n```yaml\n- name: DOMAIN\n operator: prefix_matches_regex\n prefix: 2\n value: (AP|ap)\n```\n" } }, - "required": [ - "operator", - "prefix", - "value" - ], + "required": ["operator", "prefix", "value"], "type": "object" }, { @@ -889,11 +699,7 @@ "markdownDescription": "\nComplement of `prefix_equal_to`\n" } }, - "required": [ - "operator", - "prefix", - "value" - ], + "required": ["operator", "prefix", "value"], "type": "object" }, { @@ -903,10 +709,7 @@ "markdownDescription": "\nTrue if the same value of `name` is present on multiple rows, grouped by `within`. A maximum allowed number of occurrences can be specified in the value attribute. In this instance the value: 4 means that an error will be flagged if the same value appears more than 4 times within a USUBJID. By default the operator will flag any time a value appears more than once.\n\n```yaml\n- operator: \"present_on_multiple_rows_within\"\n name: \"RELID\"\n value: 4 (optional)\n within: \"USUBJID\"\n```\n" } }, - "required": [ - "operator", - "within" - ], + "required": ["operator", "within"], "type": "object" }, { @@ -916,10 +719,7 @@ "markdownDescription": "\nWill raise an issue if at least one of the values in `name` is the same as one of the values in `value`. See [shares_no_elements_with](#shares_no_elements_with).\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -929,10 +729,7 @@ "markdownDescription": "\nWill raise an issue if exactly one of the values in `name` is the same as one of the values in `value`. See [shares_no_elements_with](#shares_no_elements_with).\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -942,10 +739,7 @@ "markdownDescription": "\nWill raise an issue if the values in `name` do not share any of the values in `value`\n\n> Check if $dataset_variables shares no elements with $timing_variables\n\n```yaml\nRule Type: Dataset Metadata Check # One record per dataset\nCheck:\n - all:\n name: $dataset_variables\n operator: shares_no_elements_with\n value: $timing_variables\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -955,10 +749,7 @@ "markdownDescription": "\nLength comparison\n\n> SETCD value length < 9\n\n```yaml\n- name: \"SETCD\"\n operator: \"shorter_than\"\n value: 9\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -968,10 +759,7 @@ "markdownDescription": "\nLength comparison\n\n> TSVAL value length <= 200\n\n```yaml\n- name: \"TSVAL\"\n operator: \"shorter_than_or_equal_to\"\n value: 201\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -981,9 +769,7 @@ "markdownDescription": "\nSplits a string by a separator and checks if both parts have equal length. Generic operator for validating paired data formats where both parts must have the same level of detail or precision.\n\nParameters:\n\n- `separator`: The delimiter to split on (default: \"/\")\n\n> Check that string parts separated by a delimiter have equal length\n\n```yaml\n- name: --DTC\n operator: split_parts_have_equal_length\n separator: \"/\"\n```\n\nUse cases:\n\n- **Date/time intervals**: `2003-12-15T10:00/2003-12-15T10:30` \u2192 True (both 16 characters)\n- **Date ranges**: `2003-12-01/2003-12-10` \u2192 True (both 10 characters)\n- **Version ranges**: `1.2.3/2.0.0` \u2192 True (both 5 characters)\n- **Product codes**: `ABC-123/XYZ-789` \u2192 True (both 7 characters)\n\nInvalid example:\n\n- `2003-12-15T10:00/2003-12-15T10:30:15` \u2192 False (16 vs 19 characters - different precision)\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -993,9 +779,7 @@ "markdownDescription": "\nComplement of `split_parts_have_equal_length`. Returns True when parts have unequal lengths (indicates a violation).\n\n```yaml\n- name: --DTC\n operator: split_parts_have_unequal_length\n separator: \"/\"\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -1005,10 +789,7 @@ "markdownDescription": "\nSubstring matching\n\n> DOMAIN beginning with 'AP'\n\n```yaml\n- name: \"DOMAIN\"\n operator: \"starts_with\"\n value: \"AP\"\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -1018,11 +799,7 @@ "markdownDescription": "\nTrue if the `suffix` number of characters ending a string in `name` match the string in `value`\n\n```yaml\n- name: dataset_name\n operator: suffix_equal_to\n prefix: 2\n value: DOMAIN\n```\n" } }, - "required": [ - "operator", - "suffix", - "value" - ], + "required": ["operator", "suffix", "value"], "type": "object" }, { @@ -1032,11 +809,7 @@ "markdownDescription": "\nTrue if the `suffix` number of characters ending a string in `name` match one of the strings in the list in `value`\n\n> Check if a supp's parent domain exists in the study\n\n```yaml\n- name: dataset_name\n operator: suffix_is_contained_by\n prefix: 2\n value: $study_domains\n```\n" } }, - "required": [ - "operator", - "suffix", - "value" - ], + "required": ["operator", "suffix", "value"], "type": "object" }, { @@ -1046,11 +819,7 @@ "markdownDescription": "\nComplement of `suffix_is_contained_by`\n" } }, - "required": [ - "operator", - "suffix", - "value" - ], + "required": ["operator", "suffix", "value"], "type": "object" }, { @@ -1060,11 +829,7 @@ "markdownDescription": "\nTrue if the `suffix` number of characters ending a string in `name` match a regular expression in `value`\n\n> QNAM ends with numbers\n\n```yaml\n- name: \"QNAM\"\n operator: \"suffix_matches_regex\"\n suffix: 2\n value: \"\\d\\d\"\n```\n" } }, - "required": [ - "operator", - "suffix", - "value" - ], + "required": ["operator", "suffix", "value"], "type": "object" }, { @@ -1074,11 +839,7 @@ "markdownDescription": "\nComplement of `suffix_equal_to`\n" } }, - "required": [ - "operator", - "suffix", - "value" - ], + "required": ["operator", "suffix", "value"], "type": "object" }, { @@ -1088,11 +849,7 @@ "markdownDescription": "\nComplement of `target_is_sorted_by`\n" } }, - "required": [ - "operator", - "value", - "within" - ], + "required": ["operator", "value", "within"], "type": "object" }, { @@ -1102,11 +859,7 @@ "markdownDescription": "\nTrue if the values in name are ordered according to the values specified by value\nin ascending/descending order, grouped by the values in within. Each value entry\nrequires a variable name, a sort_order of asc or desc, and an optional\nnull_position of first or last (defaults to last) which controls where null/empty\ncomparator values are placed in the expected ordering. Within accepts either a\nsingle column or an ordered list of columns. Columns can be either number or Char\nDates in ISO8601 YYYY-MM-DD format. Date value(s) with different precisions that\noverlap (e.g. 2005-10, 2005-10-3 and 2005-10-08) are all flagged as not sorted as\ntheir order cannot be inferred.\n\nOptionally supports a `regex` parameter that extracts a portion of the target\nvalue for sorting. The regex must contain at least one capturing group. The first\ncaptured group is extracted and converted to numeric if possible, allowing proper\nsorting of sequence numbers (e.g., \"MIDS1\", \"MIDS2\", ..., \"MIDS10\" with regex\n`.*?(\\\\d+)$`). This is particularly useful for variables that end with sequence\nnumbers that may or may not be zero-padded.\n\n```yaml\nCheck:\n all:\n - name: --SEQ\n within:\n - USUBJID\n - MIDSTYPE\n operator: target_is_sorted_by\n value:\n - name: --STDTC\n sort_order: asc\n null_position: last\n```\n\nExample with regex for extracting sequence numbers:\n\n```yaml\nCheck:\n all:\n - name: MIDS\n operator: target_is_sorted_by\n regex: \".*?(\\\\d+)$\" # Extract trailing digits, convert to numeric\n value:\n - name: SMSTDTC\n sort_order: asc\n within:\n - USUBJID\n - MIDSTYPE\n```\n" } }, - "required": [ - "operator", - "value", - "within" - ], + "required": ["operator", "value", "within"], "type": "object" }, { @@ -1116,10 +869,7 @@ "markdownDescription": "\nComplement of `value_has_multiple_references`\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -1129,10 +879,7 @@ "markdownDescription": "\nTrue if the value in `name` has more than one count in the dictionary defined in `value`\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -1142,10 +889,7 @@ "markdownDescription": "\nChecks for inconsistencies in enumerated columns of a DataFrame. Starting with the smallest/largest enumeration of the given variable, returns True if VARIABLE(N+1) is populated but VARIABLE(N) is not populated. Repeats for all variables belonging to the enumeration. Note that the initial variable will not have an index (VARIABLE) and the next enumerated variable has index 1 (VARIABLE1).\n\nex: Check if there are inconsistencies in the TSVAL columns (TSVAL, TSVAL1, TSVAL2, etc.)\n\n```yaml\nCheck:\n all:\n - name: \"TSVAL\"\n operator: \"inconsistent_enumerated_columns\"\n```\n" } }, - "required": [ - "operator", - "name" - ], + "required": ["operator", "name"], "type": "object" }, { @@ -1155,10 +899,7 @@ "markdownDescription": "\nChecks if elements in the target list appear in the same relative order in the comparator list.\n\n> Check if dataset column order is a correctly ordered subset of library column order\n\n```yaml\n- name: $column_order_from_dataset\n operator: is_ordered_subset_of\n value: $column_order_from_library\n```\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -1168,10 +909,7 @@ "markdownDescription": "\nComplement of `is_ordered_subset_of`\n" } }, - "required": [ - "operator", - "value" - ], + "required": ["operator", "value"], "type": "object" }, { @@ -1181,9 +919,7 @@ "markdownDescription": "\nValidates that variable labels follow proper title case formatting rules using the titlecase PyPi library. Title case capitalizes the first word and all major words, while keeping articles (a, an, the), conjunctions (and, but, or), and prepositions (in, of, for) in lowercase unless they are the first word. \nNOTE: The titlecase library may produce false positives or false negatives in syntactic edge cases (e.g. hyphenated words, slash-separated terms, uncommon prepositions).\n\n> Check that AELABEL values are in proper title case\n\n```yaml\n- name: AELABEL\n operator: is_title_case\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" }, { @@ -1193,18 +929,13 @@ "markdownDescription": "\nComplement of `is_title_case`. Returns True when values are NOT in proper title case.\n\n> Flag AELABEL values that violate title case rules\n\n```yaml\n- name: AELABEL\n operator: is_not_title_case\n```\n" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" } ], "properties": { "comparator": { - "type": [ - "number", - "string" - ] + "type": ["number", "string"] }, "context": { "type": "string" @@ -1242,27 +973,18 @@ "type": "boolean" }, "codelistcheck": { - "enum": [ - "code", - "value" - ], + "enum": ["code", "value"], "type": "string" }, "codelistlevel": { - "enum": [ - "term", - "codelist" - ], + "enum": ["term", "codelist"], "type": "string" }, "operator": { "type": "string" }, "order": { - "enum": [ - "asc", - "dsc" - ], + "enum": ["asc", "dsc"], "type": "string" }, "ordering": { @@ -1280,25 +1002,17 @@ "value": { "oneOf": [ { - "type": [ - "boolean", - "number", - "string" - ] + "type": ["boolean", "number", "string"] }, { "items": { - "type": [ - "number" - ] + "type": ["number"] }, "type": "array" }, { "items": { - "type": [ - "string" - ] + "type": ["string"] }, "type": "array" }, @@ -1309,10 +1023,7 @@ "$ref": "Operator.json#/properties/name" }, "null_position": { - "enum": [ - "first", - "last" - ], + "enum": ["first", "last"], "type": "string" }, "order": { @@ -1355,8 +1066,6 @@ "type": "string" } }, - "required": [ - "operator" - ], + "required": ["operator"], "type": "object" } diff --git a/resources/schema/rule-merged/Organization_CDISC.json b/resources/schema/rule-merged/Organization_CDISC.json index 9aaef8a76..db1041921 100644 --- a/resources/schema/rule-merged/Organization_CDISC.json +++ b/resources/schema/rule-merged/Organization_CDISC.json @@ -22,9 +22,7 @@ "const": "Failure" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -40,9 +38,7 @@ "type": "object" }, "Version": { - "enum": [ - "5.0" - ] + "enum": ["5.0"] } }, "type": "object" @@ -51,12 +47,7 @@ "type": "array" }, "Version": { - "enum": [ - "1.0", - "1.1", - "1.2", - "1.3" - ] + "enum": ["1.0", "1.1", "1.2", "1.3"] } }, "type": "object" @@ -75,9 +66,7 @@ "const": "Success" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -90,19 +79,13 @@ "type": "string" }, "Version": { - "enum": [ - "1", - "2", - "3" - ] + "enum": ["1", "2", "3"] } }, "type": "object" }, "Version": { - "enum": [ - "2.0" - ] + "enum": ["2.0"] } }, "type": "object" @@ -111,11 +94,7 @@ "type": "array" }, "Version": { - "enum": [ - "3.2", - "3.3", - "3.4" - ] + "enum": ["3.2", "3.3", "3.4"] } }, "type": "object" @@ -134,9 +113,7 @@ "const": "Success" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -152,9 +129,7 @@ "type": "object" }, "Version": { - "enum": [ - "5.0" - ] + "enum": ["5.0"] } }, "type": "object" @@ -163,11 +138,7 @@ "type": "array" }, "Version": { - "enum": [ - "3.0", - "3.1", - "3.1.1" - ] + "enum": ["3.0", "3.1", "3.1.1"] } }, "type": "object" @@ -186,9 +157,7 @@ "const": "Success" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -204,9 +173,7 @@ "type": "object" }, "Version": { - "enum": [ - "5.0" - ] + "enum": ["5.0"] } }, "type": "object" @@ -215,10 +182,7 @@ "type": "array" }, "Version": { - "enum": [ - "1.1", - "1.2" - ] + "enum": ["1.1", "1.2"] } }, "type": "object" @@ -237,9 +201,7 @@ "const": "Success" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -255,9 +217,7 @@ "type": "object" }, "Version": { - "enum": [ - "5.0" - ] + "enum": ["5.0"] } }, "type": "object" @@ -266,9 +226,7 @@ "type": "array" }, "Version": { - "enum": [ - "1.0" - ] + "enum": ["1.0"] } }, "type": "object" @@ -287,9 +245,7 @@ "const": "Success" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -305,9 +261,7 @@ "type": "object" }, "Version": { - "enum": [ - "1.0" - ] + "enum": ["1.0"] } }, "type": "object" @@ -316,24 +270,13 @@ "type": "array" }, "Version": { - "enum": [ - "1.0" - ] + "enum": ["1.0"] }, "Substandard": { - "enum": [ - "SDTM", - "SEND", - "ADaM", - "CDASH" - ] + "enum": ["SDTM", "SEND", "ADaM", "CDASH"] } }, - "required": [ - "Name", - "Version", - "Substandard" - ], + "required": ["Name", "Version", "Substandard"], "type": "object" }, { @@ -354,17 +297,13 @@ "type": "string" }, "Version": { - "enum": [ - "1" - ] + "enum": ["1"] } }, "type": "object" }, "Version": { - "enum": [ - "1.0" - ] + "enum": ["1.0"] } }, "type": "object" @@ -373,10 +312,7 @@ "type": "array" }, "Version": { - "enum": [ - "3.0", - "4.0" - ] + "enum": ["3.0", "4.0"] } }, "type": "object" diff --git a/resources/schema/rule-merged/Organization_Custom.json b/resources/schema/rule-merged/Organization_Custom.json index c5f591394..bf5bd7276 100644 --- a/resources/schema/rule-merged/Organization_Custom.json +++ b/resources/schema/rule-merged/Organization_Custom.json @@ -9,10 +9,7 @@ "type": "string", "description": "Name of your custom organization", "not": { - "enum": [ - "CDISC", - "FDA" - ] + "enum": ["CDISC", "FDA"] } }, "Standards": { @@ -48,9 +45,7 @@ "description": "Version of the rule" } }, - "required": [ - "Id" - ], + "required": ["Id"], "type": "object" }, "Version": { @@ -60,10 +55,7 @@ "Criteria": { "properties": { "Type": { - "enum": [ - "Failure", - "Success" - ], + "enum": ["Failure", "Success"], "type": "string" }, "Plain Language Expression": { @@ -78,46 +70,30 @@ "type": "string" } }, - "required": [ - "Rule" - ], + "required": ["Rule"], "type": "object" } }, - "required": [ - "Type" - ], + "required": ["Type"], "anyOf": [ { - "required": [ - "Logical Expression" - ] + "required": ["Logical Expression"] }, { - "required": [ - "Plain Language Expression" - ] + "required": ["Plain Language Expression"] } ], "type": "object" } }, - "required": [ - "Origin", - "Rule Identifier", - "Version" - ], + "required": ["Origin", "Rule Identifier", "Version"], "type": "object" }, "minItems": 1, "type": "array" } }, - "required": [ - "Name", - "References", - "Version" - ], + "required": ["Name", "References", "Version"], "type": "object" }, "minItems": 1, @@ -165,10 +141,7 @@ }, "OutputType": { "type": "string", - "enum": [ - "Check", - "Listing" - ], + "enum": ["Check", "Listing"], "description": "Output type of the rule validation result" }, "Keywords": { @@ -182,11 +155,7 @@ "additionalProperties": true } }, - "required": [ - "Organization", - "Standards", - "Category" - ], + "required": ["Organization", "Standards", "Category"], "type": "object", "$defs": { "metadata": { diff --git a/resources/schema/rule-merged/Organization_FDA.json b/resources/schema/rule-merged/Organization_FDA.json index 94af54bc4..b0f7de783 100644 --- a/resources/schema/rule-merged/Organization_FDA.json +++ b/resources/schema/rule-merged/Organization_FDA.json @@ -41,10 +41,7 @@ } } ], - "required": [ - "Document", - "Cited Guidance" - ], + "required": ["Document", "Cited Guidance"], "type": "object" }, "type": "array" @@ -55,9 +52,7 @@ "const": "Success" } }, - "required": [ - "Type" - ], + "required": ["Type"], "type": "object" }, "Origin": { @@ -73,9 +68,7 @@ "type": "object" }, "Version": { - "enum": [ - "1.5" - ] + "enum": ["1.5"] } }, "type": "object" @@ -91,11 +84,7 @@ "const": "SDTMIG" }, "Version": { - "enum": [ - "3.2", - "3.3", - "3.4" - ] + "enum": ["3.2", "3.3", "3.4"] } }, "type": "object" @@ -106,11 +95,7 @@ "const": "SENDIG" }, "Version": { - "enum": [ - "3.0", - "3.1", - "3.1.1" - ] + "enum": ["3.0", "3.1", "3.1.1"] } }, "type": "object" @@ -121,9 +106,7 @@ "const": "SENDIG-AR" }, "Version": { - "enum": [ - "1.0" - ] + "enum": ["1.0"] } }, "type": "object" @@ -134,10 +117,7 @@ "const": "SENDIG-DART" }, "Version": { - "enum": [ - "1.1", - "1.2" - ] + "enum": ["1.1", "1.2"] } }, "type": "object" @@ -148,9 +128,7 @@ "const": "SENDIG-GENETOX" }, "Version": { - "enum": [ - "1.0" - ] + "enum": ["1.0"] } }, "type": "object" From d113b4f00fca8b97c1283de3070b09c06dd564ef Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 22 Jul 2026 13:31:56 -0400 Subject: [PATCH 05/13] fixed lint --- .../test_Issues/test_CoreIssue1443.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py index 0046b95a5..6563f926d 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py @@ -4,7 +4,6 @@ import pytest from conftest import get_python_executable from QARegressionTests.globals import ( - dataset_details_sheet, issue_datails_sheet, rules_report_sheet, issue_sheet_variable_column, @@ -18,7 +17,7 @@ def test_vlm_fallback_codelist_check(): Test for GitHub Issue #1443: Rule blocked: CDISC.SENDIG.49 Validates that rules can use VLM (Value Level Metadata) columns as fallback when variable-level codelist is not available. - + Scenario: - VSORRESU variable has NO variable-level CodeListRef (empty ccode) - VSORRESU has VLM items with CodeListRef that match library standard @@ -55,7 +54,7 @@ def test_vlm_fallback_codelist_check(): if file.startswith("CORE-Report-") and file.endswith(".xlsx") ] excel_file_path = sorted(excel_files)[-1] - + # Open the Excel file workbook = openpyxl.load_workbook(excel_file_path) @@ -67,14 +66,14 @@ def test_vlm_fallback_codelist_check(): variables_names_values = [ cell.value for cell in variables_names_column[1:] if cell.value is not None ] - + # DEBUG: print all issue details rows print("\n=== Issue Details (first 10 rows) ===") for row in sheet.iter_rows(min_row=1, max_row=11, values_only=True): if any(row): print(row) print(f"\nColumn I values: {variables_names_values}") - + # Verify that VSORRESU issue is detected assert len(variables_names_values) >= 1, "Expected at least one variable issue" assert any("VSORRESU" in str(val) for val in variables_names_values), \ @@ -93,13 +92,13 @@ def test_vlm_fallback_codelist_check(): row for row in workbook[rules_report_sheet].iter_rows(values_only=True) ][1:] rules_values = [row for row in rules_values if any(row)] - + # Verify rule execution assert len(rules_values) > 0, "Expected rule results in Rules Report" rule_ids = [row[0] for row in rules_values if row] assert any("SEND49" in str(rid) or "CDISC.SENDIG.49" in str(rid) for rid in rule_ids), \ f"Expected SEND49 rule in Rules Report. Found: {rule_ids}" - + # Verify rule reported an issue for row in rules_values: if row and ("SEND49" in str(row[0]) or "CDISC.SENDIG.49" in str(row[0])): @@ -107,6 +106,7 @@ def test_vlm_fallback_codelist_check(): "Expected SEND49 to report an ISSUE" break + @pytest.mark.regression def test_vlm_with_variable_level_codelist(): """ @@ -144,7 +144,7 @@ def test_vlm_with_variable_level_codelist(): if file.startswith("CORE-Report-") and file.endswith(".xlsx") ] excel_file_path = sorted(excel_files)[-1] - + workbook = openpyxl.load_workbook(excel_file_path) sheet = workbook[issue_datails_sheet] @@ -153,7 +153,7 @@ def test_vlm_with_variable_level_codelist(): variables_names_values = [ cell.value for cell in variables_names_column[1:] if cell.value is not None ] - + # Verify that VSORRESU is NOT flagged when variable-level codelist is present assert not any("VSORRESU" in str(val) for val in variables_names_values), \ - "Expected VSORRESU NOT to be flagged when variable-level codelist is present" \ No newline at end of file + "Expected VSORRESU NOT to be flagged when variable-level codelist is present" From 8d0221f02a04b22cb88d7b9b1902170b3cc09f4b Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 22 Jul 2026 13:49:13 -0400 Subject: [PATCH 06/13] fixed indentations and line length --- tests/resources/CoreIssue1443/Rule.yml | 15 ++++++------ ...with_define_and_library_dataset_builder.py | 24 +++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/resources/CoreIssue1443/Rule.yml b/tests/resources/CoreIssue1443/Rule.yml index 9cc6c8254..f7c9767cb 100644 --- a/tests/resources/CoreIssue1443/Rule.yml +++ b/tests/resources/CoreIssue1443/Rule.yml @@ -104,12 +104,12 @@ Authorities: Version: '5.0' Version: '1.2' Check: - all: - - name: define_variable_ccode - operator: empty - - name: define_vlm_has_codelist_any - operator: equal_to - value: true + all: + - name: define_variable_ccode + operator: empty + - name: define_vlm_has_codelist_any + operator: equal_to + value: true Core: Id: CDISC.SENDIG.49 Status: Draft @@ -119,7 +119,8 @@ Description: 'For a variable identified in the SENDIG as being subject to CDISC document must properly reference the Controlled Terminology Codelist used.' Executability: Fully Executable Outcome: - Message: 'As a controlled terminology codelist exists for the variable in the SEND domain, the codelist must be referenced for the variable in the define.xml' + Message: 'As a controlled terminology codelist exists for the variable in the SEND + domain, the codelist must be referenced for the variable in the define.xml' Output Variables: - variable_name - define_variable_ccode diff --git a/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py b/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py index 575d5d3d9..c7351190f 100644 --- a/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py +++ b/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py @@ -226,14 +226,14 @@ def test_build_combined_metadata( assert not usubjid_row["variable_is_empty"] aeterm_row = result[result["variable_name"] == "AETERM"].iloc[0] - assert aeterm_row["define_vlm_present"] == True + assert aeterm_row["define_vlm_present"] assert aeterm_row["define_vlm_item_count"] == 2 assert aeterm_row["define_vlm_ccodes"] == [] # no codelists on either VLM item - assert aeterm_row["define_vlm_has_codelist_any"] == False - assert aeterm_row["define_vlm_has_codelist_all"] == False - assert aeterm_row["define_vlm_ccode_missing_any"] == True # both ccodes are empty - assert aeterm_row["define_vlm_ccode_matches_library_any"] == False - assert aeterm_row["define_vlm_ccode_matches_library_all"] == False + assert not aeterm_row["define_vlm_has_codelist_any"] + assert not aeterm_row["define_vlm_has_codelist_all"] + assert aeterm_row["define_vlm_ccode_missing_any"] # both ccodes are empty + assert not aeterm_row["define_vlm_ccode_matches_library_any"] + assert not aeterm_row["define_vlm_ccode_matches_library_all"] assert aeterm_row["variable_size"] == 200.0 assert aeterm_row["variable_order_number"] == 9.0 assert aeterm_row["variable_data_type"] == "Char" @@ -246,14 +246,14 @@ def test_build_combined_metadata( for var in ["STUDYID", "USUBJID"]: row = result[result["variable_name"] == var].iloc[0] - assert row["define_vlm_present"] == False + assert not row["define_vlm_present"] assert row["define_vlm_item_count"] == 0 assert row["define_vlm_ccodes"] == [] - assert row["define_vlm_has_codelist_any"] == False - assert row["define_vlm_has_codelist_all"] == False - assert row["define_vlm_ccode_missing_any"] == False - assert row["define_vlm_ccode_matches_library_any"] == False - assert row["define_vlm_ccode_matches_library_all"] == False + assert not row["define_vlm_has_codelist_any"] + assert not row["define_vlm_has_codelist_all"] + assert not row["define_vlm_ccode_missing_any"] + assert not row["define_vlm_ccode_matches_library_any"] + assert not row["define_vlm_ccode_matches_library_all"] for _, row in result.iterrows(): assert row["library_variable_name"] != "" From 298f520c868be1a4fc0c3a635c0d641af3bd4e1b Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 22 Jul 2026 13:57:07 -0400 Subject: [PATCH 07/13] Fix lint and formatting for Issue 1443 tests --- ...with_define_and_library_dataset_builder.py | 91 +++++++++++-------- .../test_Issues/test_CoreIssue1443.py | 24 +++-- ...with_define_and_library_dataset_builder.py | 2 +- 3 files changed, 68 insertions(+), 49 deletions(-) diff --git a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py index 1fa770ea7..200289e16 100644 --- a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py +++ b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py @@ -106,7 +106,9 @@ def build(self): # Third merge: add VLM summary columns define_vlm_records: List[dict] = self.get_define_xml_value_level_metadata() - define_vlm_dataset = self.dataset_implementation.from_records(define_vlm_records) + define_vlm_dataset = self.dataset_implementation.from_records( + define_vlm_records + ) define_vlm_df = define_vlm_dataset.data has_vlm = not define_vlm_df.empty @@ -124,64 +126,77 @@ def build(self): ) if has_vlm: - vlm_summary = ( - define_vlm_df.groupby("define_variable_name", as_index=False) - .agg( - define_vlm_item_count=("define_vlm_ccode", "count"), - define_vlm_ccodes=( - "define_vlm_ccode", - lambda x: sorted(set(v for v in x if v != "")) - ), - define_vlm_has_codelist_any=("define_vlm_has_codelist", "any"), - define_vlm_has_codelist_all=("define_vlm_has_codelist", "all"), - define_vlm_ccode_missing_any=( - "define_vlm_ccode", - lambda x: (x == "").any() - ), - ) + vlm_summary = define_vlm_df.groupby( + "define_variable_name", as_index=False + ).agg( + define_vlm_item_count=("define_vlm_ccode", "count"), + define_vlm_ccodes=( + "define_vlm_ccode", + lambda x: sorted(set(v for v in x if v != "")), + ), + define_vlm_has_codelist_any=("define_vlm_has_codelist", "any"), + define_vlm_has_codelist_all=("define_vlm_has_codelist", "all"), + define_vlm_ccode_missing_any=( + "define_vlm_ccode", + lambda x: (x == "").any(), + ), ) vlm_summary["define_vlm_present"] = True else: - vlm_summary = pd.DataFrame(columns=[ - "define_variable_name", - "define_vlm_item_count", - "define_vlm_ccodes", - "define_vlm_has_codelist_any", - "define_vlm_has_codelist_all", - "define_vlm_ccode_missing_any", - "define_vlm_present", - ]) + vlm_summary = pd.DataFrame( + columns=[ + "define_variable_name", + "define_vlm_item_count", + "define_vlm_ccodes", + "define_vlm_has_codelist_any", + "define_vlm_has_codelist_all", + "define_vlm_ccode_missing_any", + "define_vlm_present", + ] + ) - vlm_summary = vlm_summary.rename(columns={"define_variable_name": "variable_name"}) + vlm_summary = vlm_summary.rename( + columns={"define_variable_name": "variable_name"} + ) final_dataframe = final_dataframe.merge( vlm_summary, how="left", on="variable_name", ) - final_dataframe = final_dataframe.drop(columns=["define_variable_name_y"], errors="ignore") - - final_dataframe["define_vlm_present"] = ( - final_dataframe["define_vlm_present"].fillna(False) + final_dataframe = final_dataframe.drop( + columns=["define_variable_name_y"], errors="ignore" ) + + final_dataframe["define_vlm_present"] = final_dataframe[ + "define_vlm_present" + ].fillna(False) final_dataframe["define_vlm_item_count"] = ( final_dataframe["define_vlm_item_count"].fillna(0).astype(int) ) - final_dataframe["define_vlm_ccodes"] = final_dataframe["define_vlm_ccodes"].apply( - lambda x: x if isinstance(x, list) else [] - ) - for col in ["define_vlm_has_codelist_any", "define_vlm_has_codelist_all", - "define_vlm_ccode_missing_any"]: + final_dataframe["define_vlm_ccodes"] = final_dataframe[ + "define_vlm_ccodes" + ].apply(lambda x: x if isinstance(x, list) else []) + for col in [ + "define_vlm_has_codelist_any", + "define_vlm_has_codelist_all", + "define_vlm_ccode_missing_any", + ]: final_dataframe[col] = final_dataframe[col].fillna(False) final_dataframe["define_vlm_ccode_matches_library_any"] = final_dataframe.apply( - lambda row: row["library_variable_ccode"] in row["define_vlm_ccodes"] - if row["define_vlm_ccodes"] else False, + lambda row: ( + row["library_variable_ccode"] in row["define_vlm_ccodes"] + if row["define_vlm_ccodes"] + else False + ), axis=1, ) final_dataframe["define_vlm_ccode_matches_library_all"] = final_dataframe.apply( lambda row: ( bool(row["define_vlm_ccodes"]) - and all(c == row["library_variable_ccode"] for c in row["define_vlm_ccodes"]) + and all( + c == row["library_variable_ccode"] for c in row["define_vlm_ccodes"] + ) ), axis=1, ) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py index 6563f926d..7a6c2ef71 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py @@ -76,16 +76,19 @@ def test_vlm_fallback_codelist_check(): # Verify that VSORRESU issue is detected assert len(variables_names_values) >= 1, "Expected at least one variable issue" - assert any("VSORRESU" in str(val) for val in variables_names_values), \ - "Expected VSORRESU to be in issue variables" + assert any( + "VSORRESU" in str(val) for val in variables_names_values + ), "Expected VSORRESU to be in issue variables" # Check Core ID core_id_column = sheet[issue_sheet_coreid_column] core_id_column_values = [ cell.value for cell in core_id_column[1:] if cell.value is not None ] - assert any("SEND49" in str(val) or "CDISC.SENDIG.49" in str(val) for val in core_id_column_values), \ - f"Expected SEND49 rule to report issues. Found: {core_id_column_values}" + assert any( + "SEND49" in str(val) or "CDISC.SENDIG.49" in str(val) + for val in core_id_column_values + ), f"Expected SEND49 rule to report issues. Found: {core_id_column_values}" # Go to the "Rules Report" sheet rules_values = [ @@ -96,14 +99,14 @@ def test_vlm_fallback_codelist_check(): # Verify rule execution assert len(rules_values) > 0, "Expected rule results in Rules Report" rule_ids = [row[0] for row in rules_values if row] - assert any("SEND49" in str(rid) or "CDISC.SENDIG.49" in str(rid) for rid in rule_ids), \ - f"Expected SEND49 rule in Rules Report. Found: {rule_ids}" + assert any( + "SEND49" in str(rid) or "CDISC.SENDIG.49" in str(rid) for rid in rule_ids + ), f"Expected SEND49 rule in Rules Report. Found: {rule_ids}" # Verify rule reported an issue for row in rules_values: if row and ("SEND49" in str(row[0]) or "CDISC.SENDIG.49" in str(row[0])): - assert "ISSUE REPORTED" in str(row), \ - "Expected SEND49 to report an ISSUE" + assert "ISSUE REPORTED" in str(row), "Expected SEND49 to report an ISSUE" break @@ -155,5 +158,6 @@ def test_vlm_with_variable_level_codelist(): ] # Verify that VSORRESU is NOT flagged when variable-level codelist is present - assert not any("VSORRESU" in str(val) for val in variables_names_values), \ - "Expected VSORRESU NOT to be flagged when variable-level codelist is present" + assert not any( + "VSORRESU" in str(val) for val in variables_names_values + ), "Expected VSORRESU NOT to be flagged when variable-level codelist is present" diff --git a/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py b/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py index c7351190f..24d00fbb0 100644 --- a/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py +++ b/tests/unit/test_dataset_builders/test_variables_metadata_with_define_and_library_dataset_builder.py @@ -228,7 +228,7 @@ def test_build_combined_metadata( aeterm_row = result[result["variable_name"] == "AETERM"].iloc[0] assert aeterm_row["define_vlm_present"] assert aeterm_row["define_vlm_item_count"] == 2 - assert aeterm_row["define_vlm_ccodes"] == [] # no codelists on either VLM item + assert aeterm_row["define_vlm_ccodes"] == [] # no codelists on either VLM item assert not aeterm_row["define_vlm_has_codelist_any"] assert not aeterm_row["define_vlm_has_codelist_all"] assert aeterm_row["define_vlm_ccode_missing_any"] # both ccodes are empty From ed657f619ef8af7e0781bb7bbafc5c85d7a7880a Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 22 Jul 2026 16:09:59 -0400 Subject: [PATCH 08/13] Update CoreIssue1421 regression for collapsed metadata issue reporting --- .../test_Issues/test_CoreIssue1421.py | 83 ++++++++++++++----- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py index 009e7eca0..eefeced27 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py @@ -7,7 +7,6 @@ dataset_details_sheet, issue_datails_sheet, rules_report_sheet, - issue_sheet_variable_column, issue_sheet_coreid_column, ) @@ -51,23 +50,51 @@ def test_validate_define_xml_against_lib_metadata(): # Go to the "Issue Details" sheet sheet = workbook[issue_datails_sheet] + expected_output_variables = [ + "variable_name", + "library_variable_name", + "library_variable_ccode", + "library_variable_data_type", + "define_variable_name", + "define_variable_ccode", + ] + # Check Variable(s) column (H) variables_names_column = sheet["H"] variables_names_values = [ cell.value for cell in variables_names_column[1:] if cell.value is not None ] - assert len(variables_names_values) == 3 - for value in variables_names_values: - assert len(value.split(",")) == 6 - - # Check Value(s) column (I) - variables_values_column = sheet[issue_sheet_variable_column] - variables_values = [ - cell.value for cell in variables_values_column[1:] if cell.value is not None + + # Collapsed behavior: one issue row that lists the reported output fields + assert len(variables_names_values) == 1 + assert variables_names_values[0] == ", ".join(expected_output_variables) + + issue_rows = [ + row for row in sheet.iter_rows(min_row=2, values_only=True) if any(row) ] - assert len(variables_values) == 3 - for value in variables_values: - assert len(value.split(",")) == 6 + + reported_issue_rows = [row for row in issue_rows if row[7]] + execution_error_rows = [row for row in issue_rows if not row[7] and row[8]] + + assert len(reported_issue_rows) == 1 + assert len(execution_error_rows) == 1 + + issue_row = reported_issue_rows[0] + assert issue_row[7] == ", ".join(expected_output_variables) + + reported_values = [value.strip() for value in issue_row[8].split(",")] + assert len(reported_values) == len(expected_output_variables) + + # Still verify the row is diagnostically useful + assert reported_values[0] == reported_values[1] + assert reported_values[0] == reported_values[4] + assert reported_values[2] not in {"", "null"} + assert reported_values[3] not in {"", "null"} + assert reported_values[5] != reported_values[2] + + execution_error_row = execution_error_rows[0] + assert execution_error_row[3] == "SUPPEC" + assert "Failed to build dataset for rule validation" in execution_error_row[8] dataset_column = sheet["D"] dataset_column_values = [ @@ -86,12 +113,16 @@ def test_validate_define_xml_against_lib_metadata(): row for row in workbook[rules_report_sheet].iter_rows(values_only=True) ][1:] rules_values = [row for row in rules_values if any(row)] - assert rules_values[0][0] == "CDISC.SDTMIG.CG0999" - assert "ISSUE REPORTED" in rules_values[0] + + assert len(rules_values) == 1 + rule_row = rules_values[0] + + assert rule_row[0] == "CDISC.SDTMIG.CG0999" assert ( - rules_values[0][4] + rule_row[4] == "Issue with codelist definition in the Define-XML document." ) + assert rule_row[5] == "EXECUTION ERROR" # Go to the "Dataset Details" sheet dataset_sheet = workbook[dataset_details_sheet] @@ -114,18 +145,24 @@ def test_validate_define_xml_against_lib_metadata(): # Go to the "Issue Summary" sheet issue_summary_sheet = workbook["Issue Summary"] - summary_values = [row for row in issue_summary_sheet.iter_rows(values_only=True)][ - 1: - ] + summary_values = [row for row in issue_summary_sheet.iter_rows(values_only=True)][1:] summary_values = [row for row in summary_values if any(row)] + assert len(summary_values) == 2 core_ids = set(row[1] for row in summary_values if row[1] is not None) assert core_ids == {"CDISC.SDTMIG.CG0999"} - # Check Message and dataset columns - for row in summary_values: - assert row[2] == "Issue with codelist definition in the Define-XML document." - datasets_in_summary = set(row[0] for row in summary_values if row[0] is not None) - assert datasets_in_summary == {"DM", "SUPPEC"} + + summary_by_dataset = {row[0]: row for row in summary_values if row[0] is not None} + assert set(summary_by_dataset.keys()) == {"DM", "SUPPEC"} + + assert ( + summary_by_dataset["DM"][2] + == "Issue with codelist definition in the Define-XML document." + ) + assert ( + summary_by_dataset["SUPPEC"][2] + == "rule evaluation error - evaluation dataset failed to build" + ) # Delete the excel file if os.path.exists(excel_file_path): From fd77c6a20755206ea2bc0d3e08424a60637a2bf5 Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 22 Jul 2026 16:14:09 -0400 Subject: [PATCH 09/13] Update CoreIssue1421 regression expectations --- .../QARegressionTests/test_Issues/test_CoreIssue1421.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py index eefeced27..dcf7ea249 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py @@ -118,10 +118,7 @@ def test_validate_define_xml_against_lib_metadata(): rule_row = rules_values[0] assert rule_row[0] == "CDISC.SDTMIG.CG0999" - assert ( - rule_row[4] - == "Issue with codelist definition in the Define-XML document." - ) + assert rule_row[4] == "Issue with codelist definition in the Define-XML document." assert rule_row[5] == "EXECUTION ERROR" # Go to the "Dataset Details" sheet @@ -145,7 +142,9 @@ def test_validate_define_xml_against_lib_metadata(): # Go to the "Issue Summary" sheet issue_summary_sheet = workbook["Issue Summary"] - summary_values = [row for row in issue_summary_sheet.iter_rows(values_only=True)][1:] + summary_values = [row for row in issue_summary_sheet.iter_rows(values_only=True)][ + 1: + ] summary_values = [row for row in summary_values if any(row)] assert len(summary_values) == 2 From ef9c78e797e94ce3371a5ac792ecbfefae0069aa Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Mon, 27 Jul 2026 12:12:22 -0400 Subject: [PATCH 10/13] Removed unneeded code --- ...riables_metadata_with_define_and_library_dataset_builder.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py index 200289e16..f2ec8f76d 100644 --- a/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py +++ b/cdisc_rules_engine/dataset_builders/variables_metadata_with_define_and_library_dataset_builder.py @@ -163,9 +163,6 @@ def build(self): how="left", on="variable_name", ) - final_dataframe = final_dataframe.drop( - columns=["define_variable_name_y"], errors="ignore" - ) final_dataframe["define_vlm_present"] = final_dataframe[ "define_vlm_present" From 9f2f8494abf3f0f45a8c08e7e618a3093b0bedce Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 29 Jul 2026 08:54:00 -0400 Subject: [PATCH 11/13] Fixed merge conflicts --- tests/QARegressionTests/test_Issues/test_CoreIssue1421.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py index 6b088464f..3b7e64c8c 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1421.py @@ -1,6 +1,7 @@ import os import subprocess import openpyxl +import pytest from conftest import get_python_executable from QARegressionTests.globals import ( dataset_details_sheet, @@ -10,6 +11,7 @@ ) +@pytest.mark.regression def test_validate_define_xml_against_lib_metadata(): """Validates that codelist definitions in a Define-XML are checked against CDISC library CT metadata via rule CDISC.SDTMIG.CG0999: verifies From 747f2e64b72d2d3cdcd7c35f5058943e8ac5c4f6 Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 29 Jul 2026 09:26:29 -0400 Subject: [PATCH 12/13] Fixed issue post merge --- .../test_Issues/test_CoreIssue1443.py | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py index 7a6c2ef71..479c51718 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py @@ -6,6 +6,7 @@ from QARegressionTests.globals import ( issue_datails_sheet, rules_report_sheet, + issue_sheet_values_column, issue_sheet_variable_column, issue_sheet_coreid_column, ) @@ -67,18 +68,24 @@ def test_vlm_fallback_codelist_check(): cell.value for cell in variables_names_column[1:] if cell.value is not None ] + # Check Value(s) column + values_column = sheet[issue_sheet_values_column] + values_column_values = [ + cell.value for cell in values_column[1:] if cell.value is not None + ] + # DEBUG: print all issue details rows print("\n=== Issue Details (first 10 rows) ===") for row in sheet.iter_rows(min_row=1, max_row=11, values_only=True): if any(row): print(row) - print(f"\nColumn I values: {variables_names_values}") + print(f"\nColumn I values: {values_column_values}") # Verify that VSORRESU issue is detected assert len(variables_names_values) >= 1, "Expected at least one variable issue" assert any( - "VSORRESU" in str(val) for val in variables_names_values - ), "Expected VSORRESU to be in issue variables" + "VSORRESU" in str(val) for val in values_column_values + ), "Expected VSORRESU to be in issue values" # Check Core ID core_id_column = sheet[issue_sheet_coreid_column] @@ -151,13 +158,12 @@ def test_vlm_with_variable_level_codelist(): workbook = openpyxl.load_workbook(excel_file_path) sheet = workbook[issue_datails_sheet] - # Check Variable(s) column - variables_names_column = sheet[issue_sheet_variable_column] - variables_names_values = [ - cell.value for cell in variables_names_column[1:] if cell.value is not None - ] + values_column = sheet[issue_sheet_values_column] + values_column_values = [ + cell.value for cell in values_column[1:] if cell.value is not None + ] # Verify that VSORRESU is NOT flagged when variable-level codelist is present assert not any( - "VSORRESU" in str(val) for val in variables_names_values - ), "Expected VSORRESU NOT to be flagged when variable-level codelist is present" + "VSORRESU" in str(val) for val in values_column_values + ), "Expected VSORRESU NOT to be in issue values when variable-level codelist is present" From 3b3054947e798654258280305b154c35822bbec6 Mon Sep 17 00:00:00 2001 From: "Niemes, Adam" Date: Wed, 29 Jul 2026 09:28:06 -0400 Subject: [PATCH 13/13] Fixed lint errors --- tests/QARegressionTests/test_Issues/test_CoreIssue1443.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py index 479c51718..6bfe1865a 100644 --- a/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py +++ b/tests/QARegressionTests/test_Issues/test_CoreIssue1443.py @@ -72,7 +72,7 @@ def test_vlm_fallback_codelist_check(): values_column = sheet[issue_sheet_values_column] values_column_values = [ cell.value for cell in values_column[1:] if cell.value is not None - ] + ] # DEBUG: print all issue details rows print("\n=== Issue Details (first 10 rows) ===") @@ -161,7 +161,7 @@ def test_vlm_with_variable_level_codelist(): values_column = sheet[issue_sheet_values_column] values_column_values = [ cell.value for cell in values_column[1:] if cell.value is not None - ] + ] # Verify that VSORRESU is NOT flagged when variable-level codelist is present assert not any(