Changeset 1984


Ignore:
Timestamp:
Sep 1, 2011, 11:10:31 AM (8 years ago)
Author:
taco@…
Message:

Update for the visualization controller

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/visualization/VisualizeController.groovy

    r1983 r1984  
    1717import dbnp.studycapturing.*;
    1818import grails.converters.JSON
    19 import org.dbnp.gdt.TemplateField
     19import org.dbnp.gdt.*
    2020
    2121class VisualizeController {
    2222        def authenticationService
     23        def moduleCommunicationService
    2324       
    2425        /**
     
    3132        def getStudies = {
    3233                def studies = Study.giveReadableStudies( authenticationService.getLoggedInUser() );
    33                
    3434                render studies as JSON
    3535        }
    3636       
    3737        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
    5094                render fields as JSON
    5195        }
     
    57101       
    58102        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
    84261        }
    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    }
    86477}
Note: See TracChangeset for help on using the changeset viewer.