.. index:: using_builders .. _using_builders: Using Builders ************** Creating ODM messages by hand can be difficult. The builders package provides a simple API for generating these ODM documents. Here is an example of an ODM message to create a subject and update two values in the Enrollment default form for this study. .. code-block:: xml This ODM file can be created using builders with this python code:: >>> from rwslib.builders import * >>> odm = ODM("test system")( ... ClinicalData("Mediflex","DEV")( ... SubjectData("MDSOL","New Subject", "Insert")( ... StudyEventData("Subject")( ... FormData("EN", transaction_type="Update")( ... ItemGroupData()( ... ItemData("SUBJINIT","AAA"), ... ItemData("SUBJID",001) ... ) ... ) ... ) ... ) ... ) ... ) >>> # Get an lxml document from the ODM object for further manipulation >>> root = odm.getroot() >>> >>> # Print a string representation of the ODM document >>> print(str(odm)) Builders also allow you to create the elements in stages and "pipeline" them together to create the document. The following example creates the same document as above:: >>> from rwslib.builders import * >>> >>> # Make a root ODM element with originator system >>> odm = ODM("test system") >>> >>> # Study and environment >>> clinical_data = ClinicalData("Mediflex", "DEV") >>> >>> # Subject Site, Subject Name and the transaction type >>> subject_data = SubjectData("MDSOL", "New Subject", "Insert") >>> >>> # The special "SUBJECT" event represents subject-level forms >>> event_data = StudyEventData("SUBJECT") >>> >>> # We want to update this form that will be created automatically when subject created >>> form_data = FormData("EN", transaction_type="Update") >>> >>> # We need an ItemGroupData element >>> itemgroup = ItemGroupData() >>> >>> # Push itemdata elements into the itemgroup >>> itemgroup << ItemData("SUBJINIT","AAA") >>> itemgroup << ItemData("SUBJID",001) >>> >>> # Now we put it all together >>> odm << clinical_data << subject_data << event_data << form_data << itemgroup >>> >>> # Get an lxml document from the ODM object for further manipulation >>> root = odm.getroot() >>> >>> # Print a string representation of the ODM document >>> print(str(odm)) The builder creates a number of ODM properties including CreationDateTime, FileOID (a random identifier), FileType and all namespace declarations. Metadata Builders ----------------- Builders also exist for creating Metadata ODM files:: from rwslib.builders import * odm = ODM("SYSTEM_NAME", filetype=ODM.FILETYPE_SNAPSHOT) study_name = 'MyStudy' draft_name = 'Draft 1' study = Study(study_name, project_type=Study.PROJECT) # Push study element into odm odm << study # Create global variables and set them into study. study << GlobalVariables(study_name) # Expected that protocol name will match the Study OID. # Create some basic definitions bd = BasicDefinitions() # Add some measurement units to the basic definitions. This time using the call () syntax: bd( MeasurementUnit("KG", "Kilograms")( Symbol()(TranslatedText("Kilograms")) ), MeasurementUnit("CM", "Centimeters")( Symbol()(TranslatedText("Centimeters")) ) ) # Add basic definitions to study study << bd # Now metadata which will contain all our form and field defs eventually meta = MetaDataVersion('META1', draft_name) study << meta # Protocol contains StudyEventRefs protocol = Protocol() # Add some StudyEventRefs protocol << StudyEventRef("FLDR1", 1, True) # Order 1, Mandatory # protocol << StudyEventRef("FLDR2", 2, False) # Order 2, Not Mandatory # protocol << StudyEventRef("AE", 3, True) meta << protocol # Add Study Event Defs with some child FormRefs fldr1 = StudyEventDef("FLDR1", "Folder 1", False, StudyEventDef.SCHEDULED) fldr1 << FormRef("DM", 1, True) fldr1 << FormRef("VS", 2, True) meta << fldr1 meta << StudyEventDef("FLDR2", "Folder 2", False, StudyEventDef.UNSCHEDULED)( FormRef("VS", 1, True) ) meta << StudyEventDef("AE", "Adverse Events", False, StudyEventDef.COMMON)( FormRef("AE", 1, False) ) dm_form = FormDef("DM","Demography") dm_form << MdsolHelpText("en","Some help text for Demography form") dm_form << MdsolViewRestriction('Data Manager') dm_form << MdsolEntryRestriction('Batch Upload') dm_form << ItemGroupRef("DM_IG1", 1) dm_form << ItemGroupRef("DM_IG2", 2) # Add to metadata meta << dm_form # Define item group meta << ItemGroupDef("DM_IG1", "DM Item Group 1")( MdsolLabelRef("LBL1", 1), ItemRef("SEX", 2), ItemRef("RACE", 3), ItemRef("RACE_OTH", 4), ItemRef("DOB", 5), ItemRef("AGE", 6) ) # Add the ItemDefs meta << ItemDef("SEX", "Gender", DATATYPE_TEXT, 1, control_type=ItemDef.CONTROLTYPE_RADIOBUTTON )( Question()(TranslatedText("Gender at Birth")), CodeListRef("CL_SEX") ) meta << ItemDef("RACE", "Race", DATATYPE_TEXT, 2, control_type=ItemDef.CONTROLTYPE_RADIOBUTTON_VERTICAL )( Question()(TranslatedText("Race")), CodeListRef("CL_RACE") ) meta << ItemDef("RACE_OTH", "RaceOther", DATATYPE_TEXT, 20) \ << Question() << TranslatedText("If Race Other, please specify") meta << ItemDef("DOB", "DateOfBirth", DATATYPE_DATE, 10, control_type=ItemDef.CONTROLTYPE_DATETIME, date_time_format="dd/mm/yyyy" )( Question()(TranslatedText("Date of Birth")), MdsolHelpText("en","If month unknown, enter January") ) meta << ItemDef("AGE", "Age in Years", DATATYPE_INTEGER, 4, significant_digits=3, control_type=ItemDef.CONTROLTYPE_TEXT )( Question()(TranslatedText("Age in Years")), RangeCheck(RangeCheck.GREATER_THAN_EQUAL_TO, RangeCheck.SOFT) ( CheckValue("18") ), RangeCheck(RangeCheck.LESS_THAN_EQUAL_TO, RangeCheck.SOFT) ( CheckValue("65") ) ) # Add a Label meta.add(MdsolLabelDef("LBL1", "Label1")(TranslatedText("Please answer all questions."))) # As well as () and << you can use add() meta.add( CodeList("CL_SEX", "SEX", datatype=DATATYPE_TEXT)( CodeListItem("M").add( Decode().add( TranslatedText("Male")) ), CodeListItem("F").add( Decode().add( TranslatedText("Female")) ), ), CodeList("CL_RACE", "RACE", datatype=DATATYPE_TEXT)( CodeListItem("Y")(Decode()(TranslatedText("Yes"))), CodeListItem("N")(Decode()(TranslatedText("No"))), ) ) # Get an lxml document from the ODM object for further manipulation root = odm.getroot() # Print a string representation of the ODM document print(str(odm))