@@ -1800,6 +1800,37 @@ def update_datasets_dict(self):
18001800 # Add TS dataset
18011801 if "TS" not in self .datasets_dict :
18021802 self .datasets_dict ["TS" ] = {}
1803+
1804+ # Add TSPARMCD values extracted from vlm_lookup["TSPARMCD"] WhereClause Values
1805+ tsparmcd_values = set ()
1806+ for entry in self .vlm_lookup .get ("TSPARMCD" , []):
1807+ for where_clause in entry .get ("WhereClause" , []):
1808+ for clause in where_clause .get ("Clause" , []):
1809+ for value in clause .get ("Values" , []):
1810+ if value :
1811+ tsparmcd_values .add (value )
1812+
1813+ if tsparmcd_values :
1814+ self .datasets_dict ["TS" ]["TSPARMCD" ] = {"codelist" : {
1815+ "C66738" : sorted (tsparmcd_values )
1816+ }}
1817+
1818+ # Add TSPARM values by matching conceptIds from filtered TSPARMCD terms against C67152
1819+ kept_concept_ids = {term .get ('conceptId' ) for term in [
1820+ t for t in self .client .get_api_json (f"/mdr/ct/packages/sdtmct-{ self .sdtmct } /codelists/C66738" )['terms' ]
1821+ if not tsparmcd_values or t .get ('submissionValue' ) in tsparmcd_values
1822+ ]}
1823+
1824+ tsparm_values = {
1825+ term .get ('submissionValue' )
1826+ for term in self .client .get_api_json (f"/mdr/ct/packages/sdtmct-{ self .sdtmct } /codelists/C67152" )['terms' ]
1827+ if term .get ('conceptId' ) in kept_concept_ids and term .get ('submissionValue' )
1828+ }
1829+
1830+ if tsparm_values :
1831+ self .datasets_dict ["TS" ]["TSPARM" ] = {"codelist" : {
1832+ "C67152" : sorted (tsparm_values )
1833+ }}
18031834
18041835 # Add TA dataset from arms
18051836 if self .studyDesignData .get ('arms' , []):
@@ -2060,7 +2091,7 @@ def update_datasets_dict(self):
20602091 "OID" : f"CL.{ epoch_codelist_name } " ,
20612092 "name" : "Epoch" ,
20622093 "dataType" : "text" ,
2063- "standard" : "ST .SDTMCT" ,
2094+ "standard" : "STD .SDTMCT" ,
20642095 "codeListItems" : epoch_terms ,
20652096 }
20662097
@@ -2106,8 +2137,13 @@ def _process_standard_dataset(self, dataset, dataset_data):
21062137 "purpose" : "Tabulation" ,
21072138 "structure" : dataset_data ['datasetStructure' ],
21082139 "isReferenceData" : (dataset_data .get ('_links' , {}).get ('parentClass' , {}).get ('title' ) == "Trial Design" ) or not any (v .get ('name' ) in ("USUBJID" , "POOLID" ) for v in all_vars ),
2109- # Here are we always sure to use ST.SDTMIG?
2110- "standard" : "ST.SDTMIG" ,
2140+ "keySequence" : ["__PLACEHOLDER__" ],
2141+ # Here are we always sure to use STD.SDTMIG?
2142+ "standard" : "STD.SDTMIG" ,
2143+ "observationClass" : {
2144+ "name" : dataset_data .get ("_links" , {}).get ("parentClass" , {}).get ("title" , "" ).upper ()
2145+ },
2146+ # Here add future code for subClass in ADaM if needed
21112147 "items" : []
21122148 }
21132149
@@ -2131,6 +2167,8 @@ def _process_standard_dataset(self, dataset, dataset_data):
21312167
21322168 if 'length' in var_data :
21332169 item_dict ['length' ] = var_data ['length' ]
2170+ else :
2171+ item_dict ['length' ] = None
21342172
21352173 if 'format' in var_data :
21362174 item_dict ['displayFormat' ] = var_data ['format' ]
@@ -2143,6 +2181,11 @@ def _process_standard_dataset(self, dataset, dataset_data):
21432181 "type" : var_data ['originType' ],
21442182 "source" : var_data ['originSource' ]
21452183 }
2184+ else :
2185+ item_dict ['origin' ] = {
2186+ "type" : "__PLACEHOLDER__" ,
2187+ "source" : "__PLACEHOLDER__"
2188+ }
21462189
21472190 # Add codelist references for TA variables
21482191 if dataset == "TA" :
@@ -2281,6 +2324,7 @@ def _process_standard_dataset(self, dataset, dataset_data):
22812324 "OID" : f"VL.{ dataset } .{ var_name } " ,
22822325 "name" : f"VL_{ dataset } _{ var_name } " ,
22832326 "type" : "ValueList" ,
2327+ "wasDerivedFrom" : f"IT.{ dataset } .{ var_name } " ,
22842328 "items" : self .vlm_items_by_variable [vlm_key ]
22852329 }
22862330 slices .append (slice_dict )
@@ -2772,6 +2816,7 @@ def process(self):
27722816 self .process_biomedical_concepts ()
27732817 self .build_vlm_lookup ()
27742818 self .update_datasets_dict ()
2819+ self ._build_global_codelist_terms ()
27752820 self .populate_study_elements ()
27762821 self .process_datasets ()
27772822 self .add_standards ()
@@ -2780,6 +2825,27 @@ def process(self):
27802825 if self .debug :
27812826 self .save_debug_files ()
27822827
2828+ def _build_global_codelist_terms (self ):
2829+ """
2830+ Pre-scan datasets_dict to build a union of all explicitly restricted
2831+ terms per codelist C-Code. Used to decide placeholder vs. real terms.
2832+
2833+ For each codelist C-Code encountered across all datasets/variables:
2834+ - Non-empty list: contributes those values to the union
2835+ - Empty list: contributes nothing (means "unrestricted" for that variable)
2836+
2837+ Result stored in self.global_codelist_terms = {codelist_id: set_of_values}.
2838+ A codelist with an empty set means no dataset ever restricted it → placeholder.
2839+ """
2840+ self .global_codelist_terms = {}
2841+ for variables in self .datasets_dict .values ():
2842+ for var_data in variables .values ():
2843+ for codelist_id , terms in var_data .get ('codelist' , {}).items ():
2844+ if codelist_id not in self .global_codelist_terms :
2845+ self .global_codelist_terms [codelist_id ] = set ()
2846+ for term in terms :
2847+ self .global_codelist_terms [codelist_id ].add (term )
2848+
27832849 def _get_or_create_condition_from_vlm (self , where_clause_data , dataset , variable_name ):
27842850 """
27852851 Get existing or create new conditions from VLM where clause data.
@@ -2932,7 +2998,15 @@ def create_term_dict(term):
29322998 restriction_list = restriction_codes [codelist_id ]
29332999
29343000 if not restriction_list :
2935- final_terms = [create_term_dict (term ) for term in all_terms ]
3001+ global_terms = self .global_codelist_terms .get (codelist_id , set ())
3002+ if global_terms :
3003+ final_terms = [
3004+ create_term_dict (term )
3005+ for term in all_terms
3006+ if term .get ("submissionValue" ) in global_terms
3007+ ]
3008+ else :
3009+ final_terms = [{"NCI Term Code" : None , "Term" : "__PLACEHOLDER__" , "Decoded Value" : ["__PLACEHOLDER__" ]}]
29363010 else :
29373011 # Find matching terms from standard codelist
29383012 final_terms = [
@@ -2962,7 +3036,15 @@ def create_term_dict(term):
29623036 ]
29633037
29643038 else :
2965- final_terms = [create_term_dict (term ) for term in all_terms ]
3039+ global_terms = self .global_codelist_terms .get (codelist_id , set ())
3040+ if global_terms :
3041+ final_terms = [
3042+ create_term_dict (term )
3043+ for term in all_terms
3044+ if term .get ("submissionValue" ) in global_terms
3045+ ]
3046+ else :
3047+ final_terms = [{"NCI Term Code" : None , "Term" : "__PLACEHOLDER__" , "Decoded Value" : ["__PLACEHOLDER__" ]}]
29663048
29673049 codelist_entry = {
29683050 "NCI Codelist Code" : codelist_data .get ("conceptId" ),
@@ -2990,7 +3072,7 @@ def create_term_dict(term):
29903072 "OID" : oid ,
29913073 "name" : name ,
29923074 "dataType" : "text" ,
2993- "standard" : "ST .SDTMCT" ,
3075+ "standard" : "STD .SDTMCT" ,
29943076 }
29953077
29963078 # Add coding if NCI Codelist Code exists
@@ -3038,14 +3120,14 @@ def add_standards(self):
30383120 """
30393121 self .template ["standards" ] = [
30403122 {
3041- "OID" : "ST .SDTMIG" ,
3123+ "OID" : "STD .SDTMIG" ,
30423124 "name" : "SDTMIG" ,
30433125 "type" : "IG" ,
30443126 "version" : self .sdtmig ,
30453127 "status" : "FINAL"
30463128 },
30473129 {
3048- "OID" : "ST .SDTMCT" ,
3130+ "OID" : "STD .SDTMCT" ,
30493131 "name" : "CDISC/NCI" ,
30503132 "type" : "CT" ,
30513133 "version" : self .sdtmct ,
0 commit comments