Ignore:
Timestamp:
Mar 30, 2012, 3:35:57 PM (7 years ago)
Author:
work@…
Message:
  • implemented getSamplesForAssay api call
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/domain/dbnp/studycapturing/Sample.groovy

    r2153 r2199  
    11package dbnp.studycapturing
     2
    23import java.util.ArrayList;
    34
     
    1314 */
    1415class Sample extends TemplateEntity {
    15         static belongsTo = [
    16                 // A Sample always belongs to one study.
    17                 parent                  : Study,
    18 
    19                 // A Sample optionally has a parent Subject from which it was taken, this Subject should be in the same parent study.
    20                 parentSubject   : Subject,
    21 
    22                 // Also, it has a parent SamplingEvent describing the actual sampling, also within the same parent study.
    23                 parentEvent             : SamplingEvent,
    24 
    25                 // And it has a parent EventGroup which tied it to its parent subject and parent event
    26                 parentEventGroup: EventGroup
    27 
    28                 // We can't have parentAssay since a Sample can belong to multiple Assays
    29         ]
    30 
    31         String name             // should be unique with respect to the parent study (which can be inferred)
    32         Term material           // material of the sample (should normally be bound to the BRENDA ontology)
    33        
    34         /**
    35         * UUID of this sample
    36         */
    37         String sampleUUID
    38        
    39         /**
    40         * return the domain fields for this domain class
    41         * @return List
    42         */
    43         static List<TemplateField> giveDomainFields() { return Sample.domainFields }
    44 
    45         // We have to specify an ontology list for the material property. However, at compile time, this ontology does of course not exist.
    46         // Therefore, the ontology is added at runtime in the bootstrap, possibly downloading the ontology properties if it is not present in the database yet.
    47         static List<TemplateField> domainFields = [
    48                 new TemplateField(
    49                         name: 'name',
    50                         type: TemplateFieldType.STRING,
    51                         preferredIdentifier: true,
    52                         required: true
    53                 ),
    54                 new TemplateField(
    55                         name: 'material',
    56                         type: TemplateFieldType.ONTOLOGYTERM,
    57                         comment: "The material is based on the BRENDA tissue / enzyme source ontology, a structured controlled vocabulary for the source of an enzyme. It comprises terms for tissues, cell lines, cell types and cell cultures from uni- and multicellular organisms. If a material is missing, please add it by using 'add more'"
    58                 )
    59         ]
    60 
    61         static constraints = {
    62                 // The parent subject is optional, e.g. in a biobank of samples the subject could be unknown or non-existing.
    63                 parentSubject(nullable:true)
    64 
    65                 // The same holds for parentEvent
    66                 parentEvent(nullable:true)
    67 
    68                 // and for parentEventGroup
    69                 parentEventGroup(nullable:true)
    70 
    71                 // The material domain field is optional
    72                 material(nullable: true)
    73 
    74                 sampleUUID(nullable: true, unique: true)
    75 
    76                 // Check if the externalSampleId (currently defined as name) is really unique within each parent study of this sample.
    77                 // This feature is tested by integration test SampleTests.testSampleUniqueNameConstraint
    78                 name(unique:['parent'])
    79 
    80                 // Same, but also when the other sample is not even in the database
    81                 // This feature is tested by integration test SampleTests.testSampleUniqueNameConstraintAtValidate
    82                 name(validator: { field, obj, errors ->
    83                         // 'obj' refers to the actual Sample object
    84 
    85                         // define a boolean
    86                         def error = false
    87 
    88                         // check whether obj.parent.samples is not null at this stage to avoid null pointer exception
    89                         if (obj.parent) {
    90 
    91                                 if (obj.parent.samples) {
    92 
    93                                         // check if there is exactly one sample with this name in the study (this one)
    94                                         if (obj.parent.samples.findAll{ it.name == obj.name}.size() > 1) {
    95                                                 error = true
    96                                                 errors.rejectValue(
    97                                                         'name',
    98                                                         'sample.UniqueNameViolation',
    99                                                         [obj.name, obj.parent] as Object[],
    100                                                         'Sample name {0} appears multiple times in study {1}'
    101                                                         )
    102                                         }
    103                                 }
    104                         }
    105                         else {
    106                                 // if there is no parent study defined, fail immediately
    107                                 error = true
    108                         }
    109 
    110                         // got an error, or not?
    111                         return (!error)
    112                 })
    113         }
     16    static belongsTo = [
     17            // A Sample always belongs to one study.
     18            parent: Study,
     19
     20            // A Sample optionally has a parent Subject from which it was taken, this Subject should be in the same parent study.
     21            parentSubject: Subject,
     22
     23            // Also, it has a parent SamplingEvent describing the actual sampling, also within the same parent study.
     24            parentEvent: SamplingEvent,
     25
     26            // And it has a parent EventGroup which tied it to its parent subject and parent event
     27            parentEventGroup: EventGroup
     28
     29            // We can't have parentAssay since a Sample can belong to multiple Assays
     30    ]
     31
     32    String name             // should be unique with respect to the parent study (which can be inferred)
     33    Term material            // material of the sample (should normally be bound to the BRENDA ontology)
     34
     35    /**
     36    * UUID of this sample
     37    */
     38    String sampleUUID
     39
     40    /**
     41    * return the domain fields for this domain class
     42    * @return List
     43    */
     44    static List<TemplateField> giveDomainFields() { return Sample.domainFields }
     45
     46    // We have to specify an ontology list for the material property. However, at compile time, this ontology does of course not exist.
     47    // Therefore, the ontology is added at runtime in the bootstrap, possibly downloading the ontology properties if it is not present in the database yet.
     48    static List<TemplateField> domainFields = [
     49            new TemplateField(
     50                    name: 'name',
     51                    type: TemplateFieldType.STRING,
     52                    preferredIdentifier: true,
     53                    required: true
     54            ),
     55            new TemplateField(
     56                    name: 'material',
     57                    type: TemplateFieldType.ONTOLOGYTERM,
     58                    comment: "The material is based on the BRENDA tissue / enzyme source ontology, a structured controlled vocabulary for the source of an enzyme. It comprises terms for tissues, cell lines, cell types and cell cultures from uni- and multicellular organisms. If a material is missing, please add it by using 'add more'"
     59            )
     60    ]
     61
     62    static constraints = {
     63        // The parent subject is optional, e.g. in a biobank of samples the subject could be unknown or non-existing.
     64        parentSubject(nullable: true)
     65
     66        // The same holds for parentEvent
     67        parentEvent(nullable: true)
     68
     69        // and for parentEventGroup
     70        parentEventGroup(nullable: true)
     71
     72        // The material domain field is optional
     73        material(nullable: true)
     74
     75        sampleUUID(nullable: true, unique: true)
     76
     77        // Check if the externalSampleId (currently defined as name) is really unique within each parent study of this sample.
     78        // This feature is tested by integration test SampleTests.testSampleUniqueNameConstraint
     79        name(unique: ['parent'])
     80
     81        // Same, but also when the other sample is not even in the database
     82        // This feature is tested by integration test SampleTests.testSampleUniqueNameConstraintAtValidate
     83        name(validator: { field, obj, errors ->
     84            // 'obj' refers to the actual Sample object
     85
     86            // define a boolean
     87            def error = false
     88
     89            // check whether obj.parent.samples is not null at this stage to avoid null pointer exception
     90            if (obj.parent) {
     91
     92                if (obj.parent.samples) {
     93
     94                    // check if there is exactly one sample with this name in the study (this one)
     95                    if (obj.parent.samples.findAll { it.name == obj.name}.size() > 1) {
     96                        error = true
     97                        errors.rejectValue(
     98                                'name',
     99                                'sample.UniqueNameViolation',
     100                                [obj.name, obj.parent] as Object[],
     101                                'Sample name {0} appears multiple times in study {1}'
     102                        )
     103                    }
     104                }
     105            }
     106            else {
     107                // if there is no parent study defined, fail immediately
     108                error = true
     109            }
     110
     111            // got an error, or not?
     112            return (!error)
     113        })
     114    }
    114115
    115116    static mapping = {
     
    117118
    118119        // Workaround for bug http://jira.codehaus.org/browse/GRAILS-6754
    119         templateTextFields type: 'text'
    120     }
    121 
    122         static getSamplesFor( event ) {
    123                 return  Sample.findAll( 'from Sample s where s.parentEvent =:event', [event:event] )
    124         }
    125 
    126         /**
    127          * Returns all assays this samples has been processed in
    128          * @return      List of assays
    129         */
    130         public List getAssays() {
    131                 return Assay.executeQuery( 'select distinct a from Assay a inner join a.samples s where s = :sample', ['sample': this] )
    132         }
    133        
    134         def String toString() {
    135                 return name
    136         }
    137 
    138         /**
    139         * Basic equals method to check whether objects are equals, by comparing the ids
    140         * @param o              Object to compare with
    141         * @return               True iff the id of the given Sample is equal to the id of this Sample
    142         */
    143    public boolean equals( Object o ) {
    144            if( o == null )
    145                    return false;
    146                    
    147            if( !( o instanceof Sample ) )
    148                    return false
    149            
    150            Sample s = (Sample) o;
    151            
    152            return this.is(s) || this.id == s.id
    153    }
    154        
    155         /**
    156         * Returns the UUID of this sample and generates one if needed
    157         */
    158         public String giveUUID() {
    159                 if( !this.sampleUUID ) {
    160                         this.sampleUUID = UUID.randomUUID().toString();
    161                         if( !this.save(flush:true) ) {
    162                                 //println "Couldn't save sample UUID: " + this.getErrors();
    163                         }
    164                 }
    165                
    166                 return this.sampleUUID;
    167         }
    168        
    169         /**
    170         * Returns a human readable string of a list of samples, with a maximum number
    171         * of characters
    172         *
    173         * @param sampleList List with Sample objects
    174         * @param maxChars maximum number of characters returned
    175         * @return human readble string with at most maxChars characters, representing the samples given.
    176         */
    177    public static String trimSampleNames(ArrayList sampleList, Integer maxChars) {
    178            def simpleSamples = sampleList.name.join(', ');
    179            def showSamples
    180 
    181            // If the subjects will fit, show them all
    182            if (!maxChars || simpleSamples.size() < maxChars) {
    183                    showSamples = simpleSamples;
    184            } else {
    185                    // Always add the first name
    186                    def sampleNames = sampleList[0]?.name;
    187 
    188                    // Continue adding names until the length is to long
    189                    def id = 0;
    190                    sampleList.each { sample ->
    191                            if (id > 0) {
    192                                    if (sampleNames?.size() + sample.name?.size() < maxChars - 15) {
    193                                            sampleNames += ", " + sample.name;
    194                                    } else {
    195                                            return;
    196                                    }
    197                            }
    198                            id++;
    199                    }
    200 
    201                    // Add a postfix
    202                    sampleNames += " and " + (sampleList?.size() - id) + " more";
    203 
    204                    showSamples = sampleNames;
    205            }
    206 
    207            return showSamples
    208    }
     120        templateTextFields type: 'text'
     121    }
     122
     123    static getSamplesFor(event) {
     124        return Sample.findAll('from Sample s where s.parentEvent =:event', [event: event])
     125    }
     126
     127    /**
     128     * Returns all assays this samples has been processed in
     129     * @return List of assays
     130    */
     131    public List getAssays() {
     132        return Assay.executeQuery('select distinct a from Assay a inner join a.samples s where s = :sample', ['sample': this])
     133    }
     134
     135    def String toString() {
     136        return name
     137    }
     138
     139    /**
     140     * Basic equals method to check whether objects are equals, by comparing the ids
     141     * @param o Object to compare with
     142     * @return True iff the id of the given Sample is equal to the id of this Sample
     143     */
     144    public boolean equals(Object o) {
     145        if (o == null)
     146            return false;
     147
     148        if (!(o instanceof Sample))
     149            return false
     150
     151        Sample s = (Sample) o;
     152
     153        return this.is(s) || this.id == s.id
     154    }
     155
     156    /**
     157    * Returns the UUID of this sample and generates one if needed
     158    */
     159    public String giveUUID() {
     160        if (!this.sampleUUID) {
     161            this.sampleUUID = UUID.randomUUID().toString();
     162            if (!this.save(flush: true)) {
     163                //println "Couldn't save sample UUID: " + this.getErrors();
     164            }
     165        }
     166
     167        return this.sampleUUID;
     168    }
     169
     170    /**
     171     * Returns a human readable string of a list of samples, with a maximum number
     172     * of characters
     173     *
     174     * @param sampleList List with Sample objects
     175     * @param maxChars maximum number of characters returned
     176     * @return human readble string with at most maxChars characters, representing the samples given.
     177     */
     178    public static String trimSampleNames(ArrayList sampleList, Integer maxChars) {
     179        def simpleSamples = sampleList.name.join(', ');
     180        def showSamples
     181
     182        // If the subjects will fit, show them all
     183        if (!maxChars || simpleSamples.size() < maxChars) {
     184            showSamples = simpleSamples;
     185        } else {
     186            // Always add the first name
     187            def sampleNames = sampleList[0]?.name;
     188
     189            // Continue adding names until the length is to long
     190            def id = 0;
     191            sampleList.each { sample ->
     192                if (id > 0) {
     193                    if (sampleNames?.size() + sample.name?.size() < maxChars - 15) {
     194                        sampleNames += ", " + sample.name;
     195                    } else {
     196                        return;
     197                    }
     198                }
     199                id++;
     200            }
     201
     202            // Add a postfix
     203            sampleNames += " and " + (sampleList?.size() - id) + " more";
     204
     205            showSamples = sampleNames;
     206        }
     207
     208        return showSamples
     209    }
    209210
    210211    public static String generateSampleName(flow, subject, eventGroup, samplingEvent) {
     
    228229
    229230    /**
    230         * groovy / java equivalent of php's ucwords function
    231         *
    232         * Capitalize all first letters of separate words
    233         *
    234         * @param String
    235         * @return String
    236         */
    237         public static ucwords(String text) {
    238                 def newText = ''
    239 
    240                 // change case to lowercase
    241                 text = text.toLowerCase()
    242 
    243                 // iterate through words
    244                 text.split(" ").each() {
    245                         newText += it[0].toUpperCase() + it.substring(1) + " "
    246                 }
    247 
    248                 return newText.substring(0, newText.size()-1)
    249         }
     231    * groovy / java equivalent of php's ucwords function
     232    *
     233    * Capitalize all first letters of separate words
     234    *
     235    * @param String
     236    * @return String
     237    */
     238    public static ucwords(String text) {
     239        def newText = ''
     240
     241        // change case to lowercase
     242        text = text.toLowerCase()
     243
     244        // iterate through words
     245        text.split(" ").each() {
     246            newText += it[0].toUpperCase() + it.substring(1) + " "
     247        }
     248
     249        return newText.substring(0, newText.size() - 1)
     250    }
    250251}
Note: See TracChangeset for help on using the changeset viewer.