Changeset 1838
- Timestamp:
- May 11, 2011, 6:16:26 PM (12 years ago)
- Location:
- trunk/grails-app
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/studycapturing/SimpleWizardController.groovy
r1834 r1838 37 37 */ 38 38 def index = { 39 if( params.id ) 40 redirect( action: "simpleWizard", id: params.id ); 41 else 42 redirect( action: "simpleWizard" ); 39 // if( params.id ) 40 // redirect( action: "simpleWizard", id: params.id ); 41 // else 42 // redirect( action: "simpleWizard" ); 43 redirect action: 'simpleWizard', params: params 43 44 } 44 45 … … 48 49 flow.study = getStudyFromRequest( params ) 49 50 if (!flow.study) retrievalError() 50 51 52 flow.inferDesign = params.inferDesign 51 53 // Search for studies 52 54 flow.studies = Study.giveWritableStudies( authenticationService.getLoggedInUser(), 100 ) … … 817 819 failedCells: failedcells 818 820 ]; 819 820 // loop through all entities to validate them and add them to failedcells if an error occurs 821 def numInvalidEntities = 0; 822 def errors = []; 823 824 // Add all samples 825 table.each { record -> 826 record.each { entity -> 827 if( entity ) { 828 // Determine entity class and add a parent. Add the entity to the study 829 def preferredIdentifier = importerService.givePreferredIdentifier( entity.class ); 830 def equalClosure = { it.getIdentifier() == entity.getIdentifier() } 831 def entityName = entity.class.name[ entity.class.name.lastIndexOf( "." ) + 1 .. -1 ] 832 833 entity.parent = study 834 835 switch( entity.class ) { 836 case Sample: 837 if( !study.samples?.find( equalClosure ) ) { 838 study.addToSamples( entity ); 839 } 840 841 // If an eventgroup is created, add it to the study 842 // The eventgroup must have a unique name, but the user shouldn't be bothered with it 843 // Add 'group ' + samplename and it that is not unique, add a number to it 844 if( entity.parentEventGroup ) { 845 study.addToEventGroups( entity.parentEventGroup ) 846 847 entity.parentEventGroup.name = "Group " + entity.name 848 while( !entity.parentEventGroup.validate() ) { 849 //entity.parentEventGroup.getErrors().each { println it } 850 entity.parentEventGroup.name += "" + Math.floor( Math.random() * 100 ) 851 } 852 } 853 854 break; 855 case Subject: 856 if( !study.samples?.find( equalClosure ) ) { 857 858 if( preferredIdentifier ) { 859 // Subjects without a name should just be called 'subject' 860 if( !entity.getFieldValue( preferredIdentifier.name ) ) 861 entity.setFieldValue( preferredIdentifier.name, "Subject" ); 862 863 // Subjects should have unique names; if the user has entered the same name multiple times, 864 // the subject will be renamed 865 def baseName = entity.getFieldValue( preferredIdentifier.name ) 866 def counter = 2; 867 868 while( study.subjects?.find { it.getFieldValue( preferredIdentifier.name ) == entity.getFieldValue( preferredIdentifier.name ) } ) { 869 entity.setFieldValue( preferredIdentifier.name, baseName + " (" + counter++ + ")" ) 870 } 871 } 872 873 study.addToSubjects( entity ); 874 875 } 876 877 break; 878 case Event: 879 if( !study.events?.find( equalClosure ) ) { 880 study.addToEvents( entity ); 881 } 882 break; 883 case SamplingEvent: 884 // Sampling events have a 'sampleTemplate' value, which should be filled by the 885 // template that is chosen for samples. 886 if( !entity.getFieldValue( 'sampleTemplate' ) ) { 887 entity.setFieldValue( 'sampleTemplate', flow.sampleForm.template.Sample.name ) 888 } 889 890 if( !study.samplingEvents?.find( equalClosure ) ) { 891 study.addToSamplingEvents( entity ); 892 } 893 break; 894 } 895 896 if (!entity.validate()) { 897 numInvalidEntities++; 898 899 // Add this field to the list of failed cells, in order to give the user feedback 900 failedcells = addNonValidatingCells( failedcells, entity, flow ) 901 902 // Also create a full list of errors 903 def currentErrors = getHumanReadableErrors( entity ) 904 if( currentErrors ) { 905 currentErrors.each { 906 errors += "(" + entityName + ") " + it.value; 907 } 908 } 909 } 910 } 911 } 912 } 821 822 // loop through all entities to validate them and add them to failedcells if an error occurs 823 def numInvalidEntities = 0; 824 def errors = []; 825 826 if (flow.inferDesign) { 827 828 println 'Entered infer design...' 829 830 // find the indices of the classes of interest in the records 831 def sampleIdx = table[0].findIndexOf{it.class.name == 'dbnp.studycapturing.Sample'} 832 def samplingEventIdx = table[0].findIndexOf{it.class.name == 'dbnp.studycapturing.SamplingEvent'} 833 def subjectIdx = table[0].findIndexOf{it.class.name == 'dbnp.studycapturing.Subject'} 834 835 // Check for duplicate samples 836 def samples = table.collect{it[sampleIdx]} 837 838 def uniques = [] as Set 839 def duplicates = [] as Set 840 841 // this approach separates the unique from the duplicate entries 842 samples*.name.each { 843 uniques.add(it) || duplicates.add(it) 844 } 845 846 duplicates.each{ duplicateName -> 847 samples.findAll{it.name == duplicateName}.each{ sample -> 848 numInvalidEntities++ 849 failedcells = addNonValidatingCells(failedcells, sample, flow) 850 errors += "(Sample) duplicate name: $duplicateName" 851 } 852 } 853 854 // A closure that returns a sub list of entities from a list that have 855 // unique values of a property indicated by propertyName 856 def uniqueEntitiesByProperty = { entities, propertyName -> 857 858 entities*."$propertyName".unique().collect { uniquePropertyValue -> 859 860 entities.find{ it."$propertyName" == uniquePropertyValue } 861 862 } 863 } 864 865 def addToCollectionIfNonexistent = { parent, collectionName, entity, propertyName -> 866 867 if (!parent[collectionName].find{it[propertyName] == entity[propertyName]}) 868 parent."addTo${collectionName.capitalize()}" entity 869 870 } 871 872 // collect unique subjects and sampling events from table 873 def uniqueSubjects = 874 uniqueEntitiesByProperty(table.collect{it[subjectIdx]}, 'name') 875 uniqueSubjects.each{ 876 addToCollectionIfNonexistent study, 'subjects', it, 'name' 877 it.species = Term.findByName('Homo sapiens') 878 } 879 880 def uniqueSamplingEvents = 881 uniqueEntitiesByProperty(table.collect{it[samplingEventIdx]}, 'startTime') 882 uniqueSamplingEvents.each{ 883 it.setFieldValue( 'sampleTemplate', flow.sampleForm.template.Sample.name ) 884 } 885 886 // create an event group for each unique sampling event (not much of a group, is it ...) 887 def eventGroups = uniqueSamplingEvents.collect{ 888 889 def eventGroupName = "Sampling_${it.sampleTemplate.name}_${new RelTime(it.startTime).toString()}" 890 891 def eventGroup = study.eventGroups.find{it.name == eventGroupName} ?: //EventGroup.findByParentAndName(study, eventGroupName) ?: 892 new EventGroup(name: eventGroupName) 893 894 eventGroup.addToSamplingEvents it 895 896 if (!study.eventGroups.find{it == eventGroup}) 897 study.addToEventGroups eventGroup 898 899 if (!it.parent) study.addToSamplingEvents it 900 901 println eventGroup.name 902 903 eventGroup 904 905 } 906 907 table.each{ record -> 908 909 Sample sample = record[sampleIdx] 910 911 // gather all sample related entities 912 def correspondingSamplingEvent = uniqueSamplingEvents.find {it.startTime == record[samplingEventIdx].startTime} 913 def correspondingSubject = uniqueSubjects.find{it.name == record[subjectIdx].name} 914 def correspondingEventGroup = eventGroups.find{correspondingSamplingEvent in it.samplingEvents} 915 916 addToCollectionIfNonexistent correspondingSamplingEvent, 'samples', sample, 'name' 917 918 sample.parentSubject = correspondingSubject 919 920 correspondingEventGroup.addToSamplingEvents correspondingSamplingEvent 921 922 if (!correspondingEventGroup.subjects.find{it.name == correspondingSubject.name}) 923 correspondingEventGroup.addToSubjects correspondingSubject 924 925 addToCollectionIfNonexistent study, 'samples', sample, 'name' 926 927 } 928 929 } else { 930 // Add all samples 931 table.each { record -> 932 record.each { entity -> 933 if( entity ) { 934 // Determine entity class and add a parent. Add the entity to the study 935 def preferredIdentifier = importerService.givePreferredIdentifier( entity.class ); 936 def equalClosure = { it.getIdentifier() == entity.getIdentifier() } 937 def entityName = entity.class.name[ entity.class.name.lastIndexOf( "." ) + 1 .. -1 ] 938 939 entity.parent = study 940 941 switch( entity.class ) { 942 case Sample: 943 if( !study.samples?.find( equalClosure ) ) { 944 study.addToSamples( entity ); 945 } 946 947 // If an eventgroup is created, add it to the study 948 // The eventgroup must have a unique name, but the user shouldn't be bothered with it 949 // Add 'group ' + samplename and it that is not unique, add a number to it 950 if( entity.parentEventGroup ) { 951 study.addToEventGroups( entity.parentEventGroup ) 952 953 entity.parentEventGroup.name = "Group " + entity.name 954 while( !entity.parentEventGroup.validate() ) { 955 //entity.parentEventGroup.getErrors().each { println it } 956 entity.parentEventGroup.name += "" + Math.floor( Math.random() * 100 ) 957 } 958 } 959 960 break; 961 case Subject: 962 if( !study.samples?.find( equalClosure ) ) { 963 964 if( preferredIdentifier ) { 965 // Subjects without a name should just be called 'subject' 966 if( !entity.getFieldValue( preferredIdentifier.name ) ) 967 entity.setFieldValue( preferredIdentifier.name, "Subject" ); 968 969 // Subjects should have unique names; if the user has entered the same name multiple times, 970 // the subject will be renamed 971 def baseName = entity.getFieldValue( preferredIdentifier.name ) 972 def counter = 2; 973 974 while( study.subjects?.find { it.getFieldValue( preferredIdentifier.name ) == entity.getFieldValue( preferredIdentifier.name ) } ) { 975 entity.setFieldValue( preferredIdentifier.name, baseName + " (" + counter++ + ")" ) 976 } 977 } 978 979 study.addToSubjects( entity ); 980 981 } 982 983 break; 984 case Event: 985 if( !study.events?.find( equalClosure ) ) { 986 study.addToEvents( entity ); 987 } 988 break; 989 case SamplingEvent: 990 // Sampling events have a 'sampleTemplate' value, which should be filled by the 991 // template that is chosen for samples. 992 if( !entity.getFieldValue( 'sampleTemplate' ) ) { 993 entity.setFieldValue( 'sampleTemplate', flow.sampleForm.template.Sample.name ) 994 } 995 996 if( !study.samplingEvents?.find( equalClosure ) ) { 997 study.addToSamplingEvents( entity ); 998 } 999 break; 1000 } 1001 1002 if (!entity.validate()) { 1003 numInvalidEntities++; 1004 1005 // Add this field to the list of failed cells, in order to give the user feedback 1006 failedcells = addNonValidatingCells( failedcells, entity, flow ) 1007 1008 // Also create a full list of errors 1009 def currentErrors = getHumanReadableErrors( entity ) 1010 if( currentErrors ) { 1011 currentErrors.each { 1012 errors += "(" + entityName + ") " + it.value; 1013 } 1014 } 1015 } 1016 } 1017 } 1018 } 1019 } 913 1020 914 1021 flow.imported.numInvalidEntities = numInvalidEntities + failedcells?.size(); … … 1231 1338 return errors 1232 1339 } 1233 1234 // TEMPORARY ACTION TO TEST CORRECT STUDY DESIGN INFERRING: SHOULD BE REMOVED WHEN DONE1235 def testMethod = {1236 1237 ////////////////////////////////////////////////////////////////////////1238 // Functionality mimics intermediate results from simple wizard //1239 ////////////////////////////////////////////////////////////////////////1240 1241 def data = [//['sample name', 'subject', 'timepoint'],1242 [ '97___N_151_HAKA_1', 'N_151_HAKA', '0w'],1243 [ '98___N_163_QUJO_3', 'N_163_QUJO', '2w'],1244 [ '99___N_151_HAKA_2', 'N_151_HAKA', '1w'],1245 ['100___N_163_QUJO_4', 'N_163_QUJO', '3w'],1246 ['101___N_151_HAKA_3', 'N_151_HAKA', '2w'],1247 ['102___N_163_QUJO_2', 'N_163_QUJO', '1w'],1248 ['103___U_031_SMGI_1', 'U_031_SMGI', '0w'],1249 ['104___U_031_SMGI_3', 'U_031_SMGI', '2w'],1250 ['105___N_163_QUJO_1', 'N_163_QUJO', '0w'],1251 ['106___U_031_SMGI_4', 'U_031_SMGI', '3w'],1252 ['107___N_151_HAKA_4', 'N_151_HAKA', '3w'],1253 ['108___U_031_SMGI_2', 'U_031_SMGI', '1w'],1254 ['109___N_021_THAA_2', 'N_021_THAA', '1w'],1255 ['110___U_029_DUJA_2', 'U_029_DUJA', '1w'],1256 ['111___U_029_DUJA_3', 'U_029_DUJA', '2w'],1257 ['112___N_021_THAA_3', 'N_021_THAA', '2w'],1258 ['113___U_029_DUJA_4', 'U_029_DUJA', '3w'],1259 ['114___N_045_SNSU_1', 'N_045_SNSU', '0w'],1260 ['115___N_021_THAA_1', 'N_021_THAA', '0w'],1261 ['116___N_045_SNSU_2', 'N_045_SNSU', '1w'],1262 ['117___N_045_SNSU_3', 'N_045_SNSU', '2w'],1263 ['118___N_045_SNSU_4', 'N_045_SNSU', '3w'],1264 ['119___N_021_THAA_4', 'N_021_THAA', '3w'],1265 ['120___U_029_DUJA_1', 'U_029_DUJA', '0w'],1266 ['121___U_060_BRGE_3', 'U_060_BRGE', '2w'],1267 ['122___N_018_WIHA_1', 'N_018_WIHA', '0w'],1268 ['123___N_022_HUCA_3', 'N_022_HUCA', '2w'],1269 ['124___N_022_HUCA_2', 'N_022_HUCA', '1w']]1270 1271 def sampleTemplate = Template.findByName ('Human blood sample')1272 def subjectTemplate = Template.findByName ('Human')1273 def samplingEventTemplate = Template.findByName ('Blood extraction')1274 // def eventTemplate = Template.findByName ('Diet treatment')1275 1276 1277 // Table is a collection of records. A records contains entities of type1278 // Sample, Subject, and SamplingEvent. This mimics the output of1279 // importerService.importOrUpdateDataBySampleIdentifier1280 def table = data.collect { row ->1281 1282 [ new Sample( name: row[0], template: sampleTemplate),1283 new Subject(name: row[1], template: subjectTemplate),1284 new SamplingEvent(template: samplingEventTemplate).setFieldValue('startTime', row[2])1285 // new Event(template: eventTemplate)1286 ]1287 1288 }1289 1290 ////////////////////////////////////////////////////////////////////////1291 // Functionality below should be inserted into simple wizard1292 // We'll assume entities with pre-existing preferred identifiers have1293 // already been loaded from the db so that updating will work.1294 ////////////////////////////////////////////////////////////////////////1295 1296 def inferStudyDesign = { study ->1297 1298 // Check for duplicate samples1299 def samples = table.collect{it[0]}1300 1301 def uniques = [] as Set1302 def duplicates = [] as Set1303 1304 // this approach separates the unique from the duplicate entries1305 samples*.name.each {1306 uniques.add(it) || duplicates.add(it)1307 }1308 1309 duplicates.each{ duplicateName ->1310 samples.findAllByName(duplicateName).each{ sample ->1311 numInvalidEntities++1312 failedcells = addNonValidatingCells(failedcells, sample, flow)1313 errors += "(Sample) duplicate name: $duplicateName"1314 }1315 }1316 1317 // A closure that returns a sub list of entities from a list that have1318 // unique values of a property indicated by propertyName1319 def uniqueEntitiesByProperty = { entities, propertyName ->1320 1321 entities*."$propertyName".unique().collect { uniquePropertyValue ->1322 1323 entities.find{ it."$propertyName" == uniquePropertyValue }1324 1325 }1326 }1327 1328 // collect unique subjects and sampling events from table1329 def uniqueSubjects =1330 uniqueEntitiesByProperty(table.collect{it[1]}, 'name')1331 def uniqueSamplingEvents =1332 uniqueEntitiesByProperty(table.collect{it[2]}, 'startTime')1333 1334 // create an event group for each unique sampling event (not much of a group, is it ...)1335 uniqueSamplingEvents.each{1336 new EventGroup(name: "Sampling_${it.name}_${it.startTime}").addToSamplingEvents(it)1337 study.addToEventGroups eventGroup1338 }1339 1340 def addToCollectionIfNecessary = { parent, collectionName, entity, propertyName ->1341 1342 if (!parent.'collectionName'.find{it.'propertyName' == entity.'propertyName'})1343 parent."addTo${collectionName.toUpperCase()}" entity1344 1345 }1346 1347 table.each{ record ->1348 1349 Sample sample = record[0]1350 1351 // gather all sample related entities1352 def correspondingSamplingEvent = uniqueSamplingEvents.findByStartTime(record[2].startTime)1353 def correspondingSubject = uniqueSubjects.findByName(record[1].name)1354 def correspondingEventGroup = correspondingSamplingEvent.eventGroup1355 1356 correspondingSamplingEvent.addToSamples sample1357 correspondingSubject.addToSamples sample1358 correspondingEventGroup.addToSamples sample1359 1360 if (!correspondingEventGroup.subjects.find{it.name == correspondingSubject.name})1361 correspondingEventGroup.addToSubjects correspondingSubject1362 1363 study.addToSamples sample1364 }1365 }1366 1367 // inferStudyDesign(study)1368 1369 println 'hoi'1370 render 'bla'1371 1372 }1373 1340 } -
trunk/grails-app/views/common/_topnav.gsp
r1829 r1838 15 15 <ul class="subnav"> 16 16 <li><g:link controller="simpleWizard" action="index">A complete study with straightforward design</g:link></li> 17 <li><g:link controller="simpleWizard" action="index" params="[inferDesign: true]">A complete study with inferred design</g:link></li> 17 18 <li><g:link controller="gdtImporter" action="index">A part of the study design</g:link></li> 18 19 <li><g:link controller="gdtImporter" action="index">A list of studies (choose Study)</g:link></li>
Note: See TracChangeset
for help on using the changeset viewer.