Changeset 1984
- Timestamp:
- Sep 1, 2011, 11:10:31 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/visualization/VisualizeController.groovy
r1983 r1984 17 17 import dbnp.studycapturing.*; 18 18 import grails.converters.JSON 19 import org.dbnp.gdt. TemplateField19 import org.dbnp.gdt.* 20 20 21 21 class VisualizeController { 22 22 def authenticationService 23 def moduleCommunicationService 23 24 24 25 /** … … 31 32 def getStudies = { 32 33 def studies = Study.giveReadableStudies( authenticationService.getLoggedInUser() ); 33 34 34 render studies as JSON 35 35 } 36 36 37 37 def getFields = { 38 def entities = [ Study, Subject, Event, SamplingEvent, Sample, Assay ] 39 def fields = []; 40 41 entities.each { entity -> 42 def entityFields = TemplateField.findAll( "from TemplateField where entity = ?", [ entity ] ); 43 def domainFields = entity.giveDomainFields(); 44 45 ( domainFields + entityFields ).each { field -> 46 fields << [ "id": field.name, "source": "GSCF", "category": entity.toString(), "name": field.name ] 47 } 48 } 49 38 def input_object 39 def studies 40 41 try{ 42 input_object = JSON.parse(params.get('data')) 43 studies = input_object.get('studies').id 44 } catch(Exception e) { 45 // TODO: properly handle this exception 46 println e 47 } 48 49 def fields = []; 50 studies.each { 51 /* 52 Gather fields related to this study from GSCF. 53 This requires: 54 - a study. 55 - a category variable, e.g. "events". 56 - a type variable, either "domainfields" or "templatefields". 57 */ 58 def study = Study.get(it) 59 fields += getFields(study, "subjects", "domainfields") 60 fields += getFields(study, "subjects", "templatefields") 61 fields += getFields(study, "events", "domainfields") 62 fields += getFields(study, "events", "templatefields") 63 fields += getFields(study, "samplingEvents", "domainfields") 64 fields += getFields(study, "samplingEvents", "templatefields") 65 fields += getFields(study, "assays", "domainfields") 66 fields += getFields(study, "assays", "templatefields") 67 fields += getFields(study, "samples", "domainfields") 68 fields += getFields(study, "samples", "domainfields") 69 70 71 /* 72 Gather fields related to this study from modules. 73 This will use the getMeasurements RESTful service. That service returns measurement types, AKA features. 74 It does not actually return measurements (the getMeasurementData call does). 75 The getFields method (or rather, the getMeasurements service) requires one or more assays and will return all measurement 76 types related to these assays. 77 So, the required variables for such a call are: 78 - a source variable, which can be obtained from AssayModule.list() (use the 'name' field) 79 - a list of assays, which can be obtained with study.getAssays() 80 */ 81 AssayModule.list().each { module -> 82 def list = [] 83 list = getFields(module.name, study.getAssays()) 84 if(list!=null){ 85 if(list.size()!=0){ 86 fields += list 87 } 88 } 89 } 90 91 // TODO: Maybe we should add study's own fields 92 } 93 50 94 render fields as JSON 51 95 } … … 57 101 58 102 def getData = { 59 def data = [ 60 "type": "barchart", 61 "x": [ "0", "1", "6", "9", "12" ], 62 "xaxis": [ "title": "time", "unit": "weeks" ], 63 "yaxis": [ "title": "adipose tissue", "unit": "mg" ], 64 "series": [ 65 [ 66 "name": "epididymal", 67 "y": [ 200, 400, 390, 405, 500 ], 68 "error": [ 0.5, 0.2, 0.4, 0.5 ] 69 ], 70 [ 71 "name": "visceral", 72 "y": [ 160, 200, 220, 220, 600 ], 73 "error": [ 0.5, 0.2, 0.4, 0.5 ] 74 ], 75 [ 76 "name": "subcutaneous", 77 "y": [ 160, 200, 230, 300, 600 ], 78 "error": [ 0.5, 0.2, 0.4, 0.5 ] 79 ], 80 ] 81 ] 82 83 render data as JSON 103 println params 104 def input_object 105 def studies 106 def rows 107 def columns 108 def vizualisation_type 109 110 try{ 111 input_object = JSON.parse(params.get('data')) 112 studies = input_object.get('studies') 113 rows = input_object.get('rows') 114 columns = input_object.get('columns') 115 vizualisation_type = "barchart" 116 } catch(Exception e) { 117 // TODO: properly handle this exception 118 println e 119 } 120 121 def data = [:] 122 123 Collection row_data = [] 124 Collection column_data = [] 125 studies.each { 126 // TODO: Get rid of code duplication 127 def study = Study.get(it.id) 128 rows.eachWithIndex { r, index -> 129 println " - field "+r 130 def case_switch 131 def input_id = r.id.split(",") 132 def field_id = input_id[0] 133 def source_module = input_id[1] 134 def field_type = input_id[2] 135 def field_name = input_id[3] 136 def templatefield_source 137 if(source_module=="GSCF"){ 138 if(field_type!=TemplateField.class.toString()){ 139 case_switch = "domain" 140 } else { 141 templatefield_source = input_id[4] 142 } 143 row_data[index] = getFieldData(study, case_switch, field_id, field_name, source_module, templatefield_source, field_type) 144 } else { 145 // Grabbing field data from a module 146 row_data[index] = getFieldData(study, "", field_id, "", source_module, "", "") 147 } 148 } 149 150 columns.eachWithIndex { r, index -> 151 def case_switch 152 def input_id = r.id.split(",") 153 def field_id = input_id[0] 154 def source_module = input_id[1] 155 def field_type = input_id[2] 156 def field_name = input_id[3] 157 def templatefield_source 158 159 if(source_module=="GSCF"){ 160 if(field_type!=TemplateField.class.toString()){ 161 case_switch = "domain" 162 } else { 163 templatefield_source = input_id[4] 164 } 165 column_data[index] = getFieldData(study, case_switch, field_id, field_name, source_module, templatefield_source, field_type) 166 } else { 167 // Grabbing field data from a module 168 column_data[index] = getFieldData(study, "", field_id, "", source_module, "", "") 169 } 170 } 171 } 172 173 if(row_data.size()!=0 && column_data.size()!=0 && row_data[0].size()!=0 && column_data[0].size()!=0){ 174 // Going to build the return object now 175 def return_data = [:] 176 def series = [] 177 def possible_xaxis_title = "" 178 def possible_yaxis_title = "" 179 return_data.put("type", vizualisation_type) 180 if(vizualisation_type=='barchart'){ 181 182 // Determining what different bars we need (x-axis) 183 def list_of_row_contents = [] 184 rows.eachWithIndex { r, j -> 185 row_data[j].each { datapoint -> 186 list_of_row_contents.add(datapoint) 187 } 188 } 189 def bars = [] 190 // Make the list unique and stringify the individual objects 191 list_of_row_contents.unique().each { 192 item -> 193 bars << item.toString() 194 } 195 bars.sort() 196 return_data.put("x", bars) 197 // Determining what different bars we need (x-axis) 198 199 // Determine the different categories that datapoints can fall under 200 def categories = [] 201 columns.eachWithIndex { c, i -> 202 column_data[i].each { 203 cd -> 204 categories << cd 205 } 206 } 207 categories.unique().sort() 208 209 // Looking at the actual datapoints ... 210 columns.eachWithIndex { column, column_index -> 211 // ... for each column 212 categories.each { category -> 213 def data_per_bar = [:] // To store the datapoints contained in the current category, ordered by bar 214 // Make an entry for each of the bars that will be in the barchart 215 list_of_row_contents.each { bar -> 216 data_per_bar.put(bar, 0) 217 } 218 rows.eachWithIndex { row, row_index -> 219 // ... check for each row what it contains for each bar and category combination 220 // TODO: properly determine axis titles 221 if(possible_xaxis_title==""){ 222 possible_xaxis_title = row.id.split(',')[3] 223 } 224 list_of_row_contents.each { bar -> 225 // Check for the current bar, how many datapoints each category has 226 column_data[column_index].eachWithIndex { cd, cdi -> 227 if(bar==row_data[row_index][cdi] && cd==category){ 228 // Apparently this column contains a datapoint, whose entry in the relevant row equals the bar we are currently looking for and whose column equals the category that we are currently checking for. What this means is that the current datapoint should be included in this series 229 data_per_bar.put(bar, data_per_bar.get(bar)+1) 230 } 231 } 232 } 233 } 234 // Now add the data in the correct order (corresponding to bar order, so that the values end up in the right bar) 235 def data_per_bar_sorted = [] 236 list_of_row_contents.each { bar -> 237 data_per_bar_sorted.add(data_per_bar.get(bar)) 238 } 239 series.add(["name":category.toString(),"y":data_per_bar_sorted]) 240 } 241 } 242 243 if(possible_yaxis_title==""){ 244 // TODO: properly determine axis titles 245 possible_yaxis_title = "Amount" 246 if(possible_xaxis_title!=""){ 247 possible_yaxis_title += " of each "+possible_xaxis_title 248 } 249 } 250 return_data.put("yaxis", ["title" : possible_yaxis_title, "unit" : "..."]) 251 return_data.put("xaxis", ["title" : possible_xaxis_title, "unit": "..."]) 252 return_data.put("series", series) 253 data = return_data 254 } 255 } else { 256 // TODO: handle this exception properly 257 // We couldn't get any data to display... 258 } 259 println "\n\nReturn object: "+(data as JSON)+" ... " 260 render data as JSON 84 261 } 85 262 263 def getFieldData(study, case_switch, field_id, field_name, source, templatefield_source, field_type){ 264 if(source=="GSCF"){ 265 if(case_switch=="domain"){ 266 if(!study.getProperty(field_type)){ 267 // TODO: handle this exception properly 268 println "getFieldData: domainfield: Requested property '"+field_type+"' does not appear to exist in the study '"+study+"'." 269 return 270 } 271 def domain_objects = study.getProperty(field_type) // Simple way of getting at the relevant domain objects 272 273 if(domain_objects==null){ 274 // TODO: handle this exception properly 275 println "getFieldData: domainfield: A problem occurred... Nothing was collected." 276 } 277 278 // Get the value of the requested field out of the domain objects 279 def dat = [] 280 domain_objects.each{ 281 try{ 282 dat.add(it.getFieldValue(field_name)) 283 //println "getFieldData: domainfield: *** It appears as though we were successful" 284 } catch(Exception e){ 285 // TODO: handle this exception properly 286 println "getFieldData: domainfield: A problem occurred... "+e 287 } 288 } 289 return dat 290 } else { 291 TemplateField tf 292 try{ 293 tf = TemplateField.get(field_id) 294 } catch (Exception e){ 295 // TODO: handle this exception properly 296 println "getFieldData: templatefield: A problem occurred... "+e 297 } 298 def dat = [] 299 def collection 300 if(templatefield_source=="subjects"){ 301 collection = study.getSubjects() 302 } 303 if(templatefield_source=="assays"){ 304 collection = study.getAssays() 305 } 306 if(templatefield_source=="events"){ 307 collection = study.getEvents() 308 } 309 if(templatefield_source=="samplingEvents"){ 310 collection = study.getSamplingEvents() 311 } 312 if(templatefield_source=="samples"){ 313 collection = study.getSamples() 314 } 315 if(collection==null){ 316 // TODO: handle this exception properly 317 println "getFieldData: templatefield: A problem occurred... Nothing was collected." 318 } 319 collection.each { 320 try{ 321 dat.add(it.getFieldValue(tf.name)) 322 } catch(Exception e){ 323 // TODO: handle this exception properly 324 println "getFieldData: templatefield: A problem occurred... "+e 325 } 326 } 327 return dat 328 } 329 } else { 330 // Request for module data 331 def dat = [] 332 333 // User requested a particular feature 334 study.getAssays().each { assay -> 335 // Request for a particular assay and a particular feature 336 def urlVars = "assayToken="+assay.assayUUID+"&measurementToken="+field_id 337 def callUrl 338 AssayModule.list().each { module -> 339 if(source==module.name){ 340 try { 341 callUrl = module.url + "/rest/getMeasurementData/query?"+urlVars 342 def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl ); 343 // First element contains sampletokens 344 // Second element contains the featurename 345 // Third element contains the measurement value 346 // NOTE: There is no need to couple a measurement value to a sampletoken, because that just doesn't produce interesting data 347 json[2].each { val -> 348 dat << val 349 } 350 } catch(Exception e){ 351 // TODO: handle this exception properly 352 println "No success with\n\t"+callUrl+"\n"+e 353 return null 354 } 355 } 356 } 357 } 358 return dat 359 } 360 } 361 362 def getFields(source, assays){ 363 /* 364 Gather fields related to this study from modules. 365 This will use the getMeasurements RESTful service. That service returns measurement types, AKA features. 366 It does not actually return measurements (the getMeasurementData call does). 367 The getFields method (or rather, the getMeasurements service) requires one or more assays and will return all measurement 368 types related to these assays. 369 So, the required variables for such a call are: 370 - a source variable, which can be obtained from AssayModule.list() (use the 'name' field) 371 - a list of assays, which can be obtained with study.getAssays() 372 */ 373 def collection = [] 374 def callUrl = "" 375 376 // Making a different call for each assay 377 // TODO: Change this to one call that requests fields for all assays, when you get that to work (in all cases) 378 assays.each { assay -> 379 def urlVars = "assayToken="+assay.assayUUID 380 AssayModule.list().each { module -> 381 if(source==module.name){ 382 try { 383 callUrl = module.url + "/rest/getMeasurements/query?"+urlVars 384 def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl ); 385 json.each{ jason -> 386 collection.add(jason) 387 } 388 } catch(Exception e){ 389 // Todo: properly handle this exception 390 println "No success with\n\t"+callUrl+"\n"+e 391 return null 392 } 393 } 394 } 395 } 396 397 def fields = [] 398 // Formatting the data 399 collection.each { field -> 400 fields << [ "id": field+","+source+","+"feature"+","+field, "source": source, "category": "feature", "name": source+" feature "+field ] 401 } 402 return fields 403 } 404 405 def getFields(study, category, type){ 406 /* 407 Gather fields related to this study from GSCF. 408 This requires: 409 - a study. 410 - a category variable, e.g. "events". 411 - a type variable, either "domainfields" or "templatefields". 412 */ 413 414 // Collecting the data from it's source 415 def collection 416 def fields = [] 417 def source = "GSCF" 418 419 // Gathering the data 420 if(category=="subjects"){ 421 if(type=="domainfields"){ 422 collection = Subject.giveDomainFields() 423 } 424 if(type=="templatefields"){ 425 collection = study.giveSubjectTemplates().fields 426 } 427 } 428 if(category=="events"){ 429 if(type=="domainfields"){ 430 collection = Event.giveDomainFields() 431 } 432 if(type=="templatefields"){ 433 collection = study.giveEventTemplates().fields 434 } 435 } 436 if(category=="samplingEvents"){ 437 if(type=="domainfields"){ 438 collection = SamplingEvent.giveDomainFields() 439 } 440 if(type=="templatefields"){ 441 collection = study.giveSamplingEventTemplates().fields 442 } 443 } 444 if(category=="samples"){ 445 if(type=="domainfields"){ 446 collection = Sample.giveDomainFields() 447 } 448 if(type=="templatefields"){ 449 collection = study.giveEventTemplates().fields 450 } 451 } 452 if(category=="assays"){ 453 if(type=="domainfields"){ 454 collection = Event.giveDomainFields() 455 } 456 if(type=="templatefields"){ 457 collection = study.giveEventTemplates().fields 458 } 459 } 460 461 // Formatting the data 462 if(type=="domainfields"){ 463 collection.each { field -> 464 fields << [ "id": field.name+","+source+","+category+","+field.name, "source": source, "category": category, "name": category.capitalize()+" "+field.name ] 465 } 466 } 467 if(type=="templatefields"){ 468 collection.each { field -> 469 for(int i = 0; i < field.size(); i++){ 470 fields << [ "id": field[i].id+","+source+","+TemplateField.toString()+","+field[i].name+","+category, "source": source, "category": category, "name": category.capitalize()+" "+field[i].name ] 471 } 472 } 473 } 474 475 return fields 476 } 86 477 }
Note: See TracChangeset
for help on using the changeset viewer.