Changeset 754
- Timestamp:
- Jul 30, 2010, 3:05:41 PM (13 years ago)
- Location:
- trunk/grails-app
- Files:
-
- 1 deleted
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/conf/BootStrapStudies.groovy
r703 r754 167 167 ecCode:"2007117.c", 168 168 startDate: Date.parse('yyyy-MM-dd','2008-01-02'), 169 ) 170 .with { if (!validate()) { errors.each { println it} } else save()} 169 ).with { if (!validate()) { errors.each { println it} } else save()} 171 170 172 171 mouseStudy.setFieldValue('Description', "C57Bl/6 mice were fed a high fat (45 en%) or low fat (10 en%) diet after a four week run-in on low fat diet.");// After 1 week 10 mice that received a low fat diet were given an IP leptin challenge and 10 mice of the low-fat group received placebo injections. The same procedure was performed with mice that were fed the high-fat diet. After 4 weeks the procedure was repeated. In total 80 mice were culled." ) … … 179 178 ) 180 179 .setFieldValue( 'Diet','low fat') 181 .with { if (!validate()) { errors.each { println it} } else save()}182 180 183 181 def evHF = new Event( … … 187 185 ) 188 186 .setFieldValue( 'Diet','high fat' ) 189 .with { if (!validate()) { errors.each { println it} } else save()}190 187 191 188 def evBV = new Event( … … 195 192 ) 196 193 .setFieldValue( 'Control','true' ) 197 .with { if (!validate()) { errors.each { println it} } else save()}198 194 199 195 def evBL = new Event( … … 203 199 ) 204 200 .setFieldValue( 'Control','false' ) 205 .with { if (!validate()) { errors.each { println it} } else save()}206 201 207 202 def evLF4 = new Event( … … 211 206 ) 212 207 .setFieldValue( 'Diet','low fat') 213 .with { if (!validate()) { errors.each { println it} } else save()}214 208 215 209 def evHF4 = new Event( … … 219 213 ) 220 214 .setFieldValue( 'Diet','high fat' ) 221 .with { if (!validate()) { errors.each { println it} } else save()}222 215 223 216 def evBV4 = new Event( … … 227 220 ) 228 221 .setFieldValue( 'Control','true' ) 229 .with { if (!validate()) { errors.each { println it} } else save()}230 222 231 223 def evBL4 = new Event( … … 235 227 ) 236 228 .setFieldValue( 'Control','false' ) 237 .with { if (!validate()) { errors.each { println it} } else save()}238 229 239 230 def evS = new SamplingEvent( … … 242 233 template: liverSamplingEventTemplate) 243 234 .setFieldValue('Sample weight',5F) 244 .with { if (!validate()) { errors.each { println it} } else save()}245 235 246 236 def evS4 = new SamplingEvent( … … 249 239 template: liverSamplingEventTemplate) 250 240 .setFieldValue('Sample weight',5F) 251 .with { if (!validate()) { errors.each { println it} } else save()}252 241 253 242 // Add events to study … … 263 252 .addToSamplingEvents(evS) 264 253 .addToSamplingEvents(evS4) 265 .save() 254 .with { if (!validate()) { errors.each { println it} } else save()} 255 256 // Extra check if the SamplingEvents are saved correctly 257 evS.with { if (!validate()) { errors.each { println it} } else save()} 258 evS4.with { if (!validate()) { errors.each { println it} } else save()} 266 259 267 260 def LFBV1 = new EventGroup(name:"10% fat + vehicle for 1 week") 268 261 .addToEvents(evLF) 269 262 .addToEvents(evBV) 270 .addToEvents(evS) 271 .with { if (!validate()) { errors.each { println it} } else save()} 263 .addToSamplingEvents(evS) 272 264 273 265 def LFBL1 = new EventGroup(name:"10% fat + leptin for 1 week") 274 266 .addToEvents(evLF) 275 267 .addToEvents(evBL) 276 .addToEvents(evS) 277 .with { if (!validate()) { errors.each { println it} } else save()} 268 .addToSamplingEvents(evS) 278 269 279 270 def HFBV1 = new EventGroup(name:"45% fat + vehicle for 1 week") 280 271 .addToEvents(evHF) 281 272 .addToEvents(evBV) 282 .addToEvents(evS) 283 .with { if (!validate()) { errors.each { println it} } else save()} 273 .addToSamplingEvents(evS) 284 274 285 275 def HFBL1 = new EventGroup(name:"45% fat + leptin for 1 week") 286 276 .addToEvents(evHF) 287 277 .addToEvents(evBL) 288 .addToEvents(evS) 289 .with { if (!validate()) { errors.each { println it} } else save()} 278 .addToSamplingEvents(evS) 290 279 291 280 def LFBV4 = new EventGroup(name:"10% fat + vehicle for 4 weeks") 292 281 .addToEvents(evLF4) 293 282 .addToEvents(evBV4) 294 .addToEvents(evS4) 295 .with { if (!validate()) { errors.each { println it} } else save()} 283 .addToSamplingEvents(evS4) 296 284 297 285 def LFBL4 = new EventGroup(name:"10% fat + leptin for 4 weeks") 298 286 .addToEvents(evLF4) 299 287 .addToEvents(evBL4) 300 .addToEvents(evS4) 301 .with { if (!validate()) { errors.each { println it} } else save()} 288 .addToSamplingEvents(evS4) 302 289 303 290 def HFBV4 = new EventGroup(name:"45% fat + vehicle for 4 weeks") 304 291 .addToEvents(evHF4) 305 292 .addToEvents(evBV4) 306 .addToEvents(evS4) 307 .with { if (!validate()) { errors.each { println it} } else save()} 293 .addToSamplingEvents(evS4) 308 294 309 295 def HFBL4 = new EventGroup(name:"45% fat + leptin for 4 weeks") 310 296 .addToEvents(evHF4) 311 297 .addToEvents(evBL4) 312 .addToEvents(evS4) 313 .with { if (!validate()) { errors.each { println it} } else save()} 314 298 .addToSamplingEvents(evS4) 299 315 300 // Add subjects and samples and compose EventGroups 316 301 def x=1 317 20.times {302 80.times { 318 303 def currentSubject = new Subject( 319 304 name: "A" + x++, … … 325 310 .setFieldValue("Age", 17) 326 311 .setFieldValue("Cage", "" + (int)(x/2)) 327 .with { if (!validate()) { errors.each { println it} } else save(flush:true)}328 312 329 313 mouseStudy.addToSubjects(currentSubject) … … 344 328 name: currentSubject.name + '_B', 345 329 material: bloodTerm, 346 330 template: humanBloodSampleTemplate, 347 331 parentSubject: currentSubject, 348 332 parentEvent: x > 40 ? evS4 : evS 349 333 ); 350 currentSample.setFieldValue( "Text on vial", "T" + (Math.random() * 100L) ) 351 334 currentSample.setFieldValue( "Text on vial", "T" + (Math.random() * 100L) ) 352 335 mouseStudy.addToSamples(currentSample).with { if (!validate()) { errors.each { println it} } else save()} 353 336 } … … 363 346 .addToEventGroups(HFBV4) 364 347 .addToEventGroups(HFBL4) 348 .with { if (!validate()) { errors.each { println it} } else save()} 365 349 366 350 // Add persons and publications to study 367 def studyperson1 = new StudyPerson( person: person1, role: role1 ) .save();368 def studyperson2 = new StudyPerson( person: person2, role: role2 ) .save();351 def studyperson1 = new StudyPerson( person: person1, role: role1 ) 352 def studyperson2 = new StudyPerson( person: person2, role: role2 ) 369 353 370 354 mouseStudy … … 373 357 .addToPublications( publication1 ) 374 358 .addToPublications( publication2 ) 375 . save()359 .with { if (!validate()) { errors.each { println it} } else save()} 376 360 377 361 // Add example human study … … 406 390 407 391 rootGroup.addToEvents fastingEvent 408 rootGroup.addTo Events bloodSamplingEvent392 rootGroup.addToSamplingEvents bloodSamplingEvent 409 393 rootGroup.save() 410 394 … … 422 406 .setFieldValue("Weight", Math.random() * 150F) 423 407 .setFieldValue("BMI", 20 + Math.random() * 10F) 424 .with { if (!validate()) { errors.each { println it} } else save()}425 408 426 409 rootGroup.addToSubjects currentSubject 427 410 rootGroup.save() 428 411 429 412 def currentSample = new Sample( 430 413 name: currentSubject.name + '_B', 431 414 material: bloodTerm, 432 415 template: humanBloodSampleTemplate, 433 416 parentSubject: currentSubject, 434 417 parentEvent: bloodSamplingEvent 435 418 ); 436 currentSample.setFieldValue( "Text on vial", "T" + (Math.random() * 100L) ) 437 438 humanStudy.addToSubjects(currentSubject).addToSamples(currentSample).with { if (!validate()) { errors.each { println it} } else save()} 419 currentSample.setFieldValue( "Text on vial", "T" + (Math.random() * 100L) ) 420 421 humanStudy.addToSubjects(currentSubject).addToSamples(currentSample) 422 .with { if (!validate()) { errors.each { println it} } else save()} 439 423 } 440 424 … … 445 429 446 430 // Add persons to study 447 def studyperson3 = new StudyPerson( person: person1, role: role2 ) .save();431 def studyperson3 = new StudyPerson( person: person1, role: role2 ) 448 432 449 433 humanStudy 450 434 .addToPersons( studyperson3 ) 451 452 . save()435 .addToPublications( publication2 ) 436 .with { if (!validate()) { errors.each { println it} } else save()} 453 437 454 438 // Add clinical data ==> to be moved to SAM … … 519 503 } 520 504 521 505 mouseStudy.addToAssays(lipidAssayRef); 522 506 mouseStudy.save() 523 507 -
trunk/grails-app/domain/dbnp/studycapturing/Assay.groovy
r690 r754 6 6 * this data can be found. 7 7 */ 8 class Assay { 8 class Assay implements Serializable { 9 10 /** The name of the assay, which should indicate the measurements represented in this assay to the user. */ 9 11 String name 12 13 /** The dbNP module in which the assay omics data can be found. */ 10 14 AssayModule module 11 long externalAssayID // the assay ID the assay has in the external module12 15 16 /** 17 The assay ID which is used in the dbNP submodule which contains the actual omics data of this assay. 18 This ID is generated in GSCF, but is used in the submodules to refer to this particular Assay. 19 */ 20 long externalAssayID 21 22 // An Assay always belongs to one study. 13 23 static belongsTo = [parent: Study] 14 24 25 // An Assay can have many samples on which it is performed, but all samples should be within the 'parent' Study. 15 26 static hasMany = [samples: Sample] 16 27 -
trunk/grails-app/domain/dbnp/studycapturing/AssayModule.groovy
r690 r754 4 4 * This entity describes actual dbNP submodule instances: what type of data they store, and how to reach them 5 5 */ 6 class AssayModule { 6 class AssayModule implements Serializable { 7 8 /** The name of the module, for user-reference purposes */ 7 9 String name 10 11 /** The type of the module */ 8 12 AssayType type 13 14 /** A descriptive string describing the 'platform' of the assay data in the module */ 9 15 String platform 16 17 /** The base URL at which the module instance is located */ 10 18 String url 11 19 -
trunk/grails-app/domain/dbnp/studycapturing/AssayType.groovy
r654 r754 2 2 3 3 /** 4 * Enum describing the different assay types (aka omicssubmodules).4 * Enum describing the different assay types (aka known dbNP submodules). 5 5 * 6 6 * Revision information: … … 9 9 * $Date$ 10 10 */ 11 public enum AssayType {11 public enum AssayType implements Serializable { 12 12 TRANSCRIPTOMICS('Transcriptomics'), 13 13 METABOLOMICS('Metabolomics'), -
trunk/grails-app/domain/dbnp/studycapturing/Event.groovy
r701 r754 1 1 package dbnp.studycapturing 2 3 import groovy.time.*4 2 5 3 /** … … 13 11 * $Date$ 14 12 */ 15 class Event extends TemplateEntity implements Serializable { 16 long startTime // start time of the event, relative to the start time of the study 17 long endTime // end time of the event, relative to the start time of the study 13 class Event extends TemplateEntity { 18 14 19 // TODO: assure the Event has a parent study in validate() 15 static belongsTo = [parent : Study] 16 17 /** Start time of the event, relative to the start time of the study */ 18 long startTime 19 /** end time of the event, relative to the start time of the study */ 20 long endTime 20 21 21 22 /** … … 41 42 } 42 43 44 static mapping = { 45 46 // Specify that subclasses for Event should have their own database table. 47 // This is done because otherwise we run into troubles with the SamplingEvent references from Study. 48 tablePerHierarchy false 49 } 50 43 51 /** 44 52 * return the domain fields for this domain class 45 * @return List 53 * @return List<TemplateField> 46 54 */ 47 55 static List<TemplateField> giveDomainFields() { return Event.domainFields } 48 56 57 // To improve performance, the domain fields list is stored as a static final variable in the class. 49 58 static final List<TemplateField> domainFields = [ 50 59 new TemplateField( … … 59 68 60 69 /** 61 * get the duration70 * Get the duration of the event as RelTime 62 71 * @return RelTime 63 72 */ … … 65 74 return new RelTime(startTime, endTime) 66 75 } 67 68 76 69 77 /** … … 85 93 86 94 /** 87 * get a prettified duration88 * @return String89 */90 static def getPrettyDuration(RelTime duration) {91 return duration.toPrettyString();92 }93 94 def getPrettyDuration() {95 getPrettyDuration(getDuration())96 }97 98 /**99 95 * Get human readable string representing the duration between startTime and endTime, rounded to one unit (weeks/days/hours etc.) 100 96 * … … 113 109 } 114 110 111 /** 112 * Checks whether this Event is part of one or more of the given EventGroups 113 * @param groups 114 * @return 115 */ 115 116 def belongsToGroup(Collection<EventGroup> groups) { 116 117 def eventFound = false; -
trunk/grails-app/domain/dbnp/studycapturing/EventGroup.groovy
r496 r754 10 10 */ 11 11 class EventGroup implements Serializable { 12 13 static belongsTo = [parent : Study] 14 12 15 String name 13 16 14 17 static hasMany = [ 15 18 subjects: Subject, 16 events: Event 19 events: Event, 20 samplingEvents: SamplingEvent 17 21 ] 18 22 -
trunk/grails-app/domain/dbnp/studycapturing/Person.groovy
r540 r754 2 2 3 3 /** 4 * 888 888 888 888 8888888888 8888888b. 8888888888 5 * 888 o 888 888 888 888 888 Y88b 888 6 * 888 d8b 888 888 888 888 888 888 888 7 * 888 d888b 888 8888888888 8888888 888 d88P 8888888 8 * 888d88888b888 888 888 888 8888888P" 888 9 * 88888P Y88888 888 888 888 888 T88b 888 10 * 8888P Y8888 888 888 888 888 T88b 888 11 * 888P Y888 888 888 8888888888 888 T88b 8888888888 12 * 13 * 8888888 .d8888b. 88888888888 888 888 8888888888 14 * 888 d88P Y88b 888 888 888 888 15 * 888 Y88b. 888 888 888 888 16 * 888 "Y888b. 888 8888888888 8888888 17 * 888 "Y88b. 888 888 888 888 18 * 888 "888 888 888 888 888 19 * 888 Y88b d88P 888 888 888 888 20 * 8888888 "Y8888P" 888 888 888 8888888888 21 * 22 * 888888 d8888 888 888 d8888 8888888b. .d88888b. .d8888b. 23 * "88b d88888 888 888 d88888 888 "Y88b d88P" "Y88b d88P Y88b 24 * 888 d88P888 888 888 d88P888 888 888 888 888 888 888 25 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 26 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 27 * 888 d88P 888 Y88o88P d88P 888 888 888 888 888 888 888 28 * 88P d8888888888 Y888P d8888888888 888 .d88P Y88b. .d88P Y88b d88P 29 * 888 d88P 888 Y8P d88P 888 8888888P" "Y88888P" "Y8888P" 30 * .d88P 31 * .d88P" 32 * 888P" 33 * 34 * .d8888b. 888 .d8888b. 888 .d8888b. 888 35 * d88P Y88b 888 d88P Y88b 888 d88P Y88b 888 36 * .d88P 888 .d88P 888 .d88P 888 37 * .d88P" 888 .d88P" 888 .d88P" 888 38 * 888" 888 888" 888 888" 888 39 * 888 Y8P 888 Y8P 888 Y8P 40 * " " " 41 * 888 888 888 888 888 888 42 * 43 * 44 * TODO: add PROPER class and method documentation, just like have 45 * agreed upon hundreds of times!!!! 4 * The Person class represents a person who is related to one ore more studies, such as a PI, a lab analyst etc. 5 * Those people do not neccessarily have an account in GSCF, the Study/Persons/Affiliations administration 6 * is independent of GSCF usernames and accounts. 46 7 */ 47 48 8 class Person implements Serializable { 49 9 String title -
trunk/grails-app/domain/dbnp/studycapturing/PersonAffiliation.groovy
r540 r754 2 2 3 3 /** 4 * 888 888 888 888 8888888888 8888888b. 8888888888 5 * 888 o 888 888 888 888 888 Y88b 888 6 * 888 d8b 888 888 888 888 888 888 888 7 * 888 d888b 888 8888888888 8888888 888 d88P 8888888 8 * 888d88888b888 888 888 888 8888888P" 888 9 * 88888P Y88888 888 888 888 888 T88b 888 10 * 8888P Y8888 888 888 888 888 T88b 888 11 * 888P Y888 888 888 8888888888 888 T88b 8888888888 12 * 13 * 8888888 .d8888b. 88888888888 888 888 8888888888 14 * 888 d88P Y88b 888 888 888 888 15 * 888 Y88b. 888 888 888 888 16 * 888 "Y888b. 888 8888888888 8888888 17 * 888 "Y88b. 888 888 888 888 18 * 888 "888 888 888 888 888 19 * 888 Y88b d88P 888 888 888 888 20 * 8888888 "Y8888P" 888 888 888 8888888888 21 * 22 * 888888 d8888 888 888 d8888 8888888b. .d88888b. .d8888b. 23 * "88b d88888 888 888 d88888 888 "Y88b d88P" "Y88b d88P Y88b 24 * 888 d88P888 888 888 d88P888 888 888 888 888 888 888 25 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 26 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 27 * 888 d88P 888 Y88o88P d88P 888 888 888 888 888 888 888 28 * 88P d8888888888 Y888P d8888888888 888 .d88P Y88b. .d88P Y88b d88P 29 * 888 d88P 888 Y8P d88P 888 8888888P" "Y88888P" "Y8888P" 30 * .d88P 31 * .d88P" 32 * 888P" 33 * 34 * .d8888b. 888 .d8888b. 888 .d8888b. 888 35 * d88P Y88b 888 d88P Y88b 888 d88P Y88b 888 36 * .d88P 888 .d88P 888 .d88P 888 37 * .d88P" 888 .d88P" 888 .d88P" 888 38 * 888" 888 888" 888 888" 888 39 * 888 Y8P 888 Y8P 888 Y8P 40 * " " " 41 * 888 888 888 888 888 888 42 * 43 * 44 * TODO: add PROPER class and method documentation, just like have 45 * agreed upon hundreds of times!!!! 4 * The PersonAffiliation class is an attribute of a Person, it represents an affiliation where she/he works for. 5 * PersonAffiliation is an independent list of affiliations, and does not neccessarily belong to one Person. 46 6 */ 7 class PersonAffiliation implements Serializable { 47 8 48 class PersonAffiliation implements Serializable {49 9 String institute 50 10 String department -
trunk/grails-app/domain/dbnp/studycapturing/PersonRole.groovy
r540 r754 2 2 3 3 /** 4 * 888 888 888 888 8888888888 8888888b. 8888888888 5 * 888 o 888 888 888 888 888 Y88b 888 6 * 888 d8b 888 888 888 888 888 888 888 7 * 888 d888b 888 8888888888 8888888 888 d88P 8888888 8 * 888d88888b888 888 888 888 8888888P" 888 9 * 88888P Y88888 888 888 888 888 T88b 888 10 * 8888P Y8888 888 888 888 888 T88b 888 11 * 888P Y888 888 888 8888888888 888 T88b 8888888888 12 * 13 * 8888888 .d8888b. 88888888888 888 888 8888888888 14 * 888 d88P Y88b 888 888 888 888 15 * 888 Y88b. 888 888 888 888 16 * 888 "Y888b. 888 8888888888 8888888 17 * 888 "Y88b. 888 888 888 888 18 * 888 "888 888 888 888 888 19 * 888 Y88b d88P 888 888 888 888 20 * 8888888 "Y8888P" 888 888 888 8888888888 21 * 22 * 888888 d8888 888 888 d8888 8888888b. .d88888b. .d8888b. 23 * "88b d88888 888 888 d88888 888 "Y88b d88P" "Y88b d88P Y88b 24 * 888 d88P888 888 888 d88P888 888 888 888 888 888 888 25 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 26 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 27 * 888 d88P 888 Y88o88P d88P 888 888 888 888 888 888 888 28 * 88P d8888888888 Y888P d8888888888 888 .d88P Y88b. .d88P Y88b d88P 29 * 888 d88P 888 Y8P d88P 888 8888888P" "Y88888P" "Y8888P" 30 * .d88P 31 * .d88P" 32 * 888P" 33 * 34 * .d8888b. 888 .d8888b. 888 .d8888b. 888 35 * d88P Y88b 888 d88P Y88b 888 d88P Y88b 888 36 * .d88P 888 .d88P 888 .d88P 888 37 * .d88P" 888 .d88P" 888 .d88P" 888 38 * 888" 888 888" 888 888" 888 39 * 888 Y8P 888 Y8P 888 Y8P 40 * " " " 41 * 888 888 888 888 888 888 42 * 43 * 44 * TODO: add PROPER class and method documentation, just like have 45 * agreed upon hundreds of times!!!! 4 * The role of a person, as specified in a StudyPerson relation. 5 * Person roles form an independent 'roles list' and are therefore not coupled to a specific StudyPerson relation with belongsTo. 6 * Generally, there will only be a few PersonRoles such as PI, lab analyst etc. 46 7 */ 8 class PersonRole implements Serializable { 47 9 48 class PersonRole implements Serializable { 10 /** The name of the role, such as Project Leader or PI */ 49 11 String name 50 12 -
trunk/grails-app/domain/dbnp/studycapturing/Publication.groovy
r540 r754 2 2 3 3 /** 4 * 888 888 888 888 8888888888 8888888b. 8888888888 5 * 888 o 888 888 888 888 888 Y88b 888 6 * 888 d8b 888 888 888 888 888 888 888 7 * 888 d888b 888 8888888888 8888888 888 d88P 8888888 8 * 888d88888b888 888 888 888 8888888P" 888 9 * 88888P Y88888 888 888 888 888 T88b 888 10 * 8888P Y8888 888 888 888 888 T88b 888 11 * 888P Y888 888 888 8888888888 888 T88b 8888888888 12 * 13 * 8888888 .d8888b. 88888888888 888 888 8888888888 14 * 888 d88P Y88b 888 888 888 888 15 * 888 Y88b. 888 888 888 888 16 * 888 "Y888b. 888 8888888888 8888888 17 * 888 "Y88b. 888 888 888 888 18 * 888 "888 888 888 888 888 19 * 888 Y88b d88P 888 888 888 888 20 * 8888888 "Y8888P" 888 888 888 8888888888 21 * 22 * 888888 d8888 888 888 d8888 8888888b. .d88888b. .d8888b. 23 * "88b d88888 888 888 d88888 888 "Y88b d88P" "Y88b d88P Y88b 24 * 888 d88P888 888 888 d88P888 888 888 888 888 888 888 25 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 26 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 888 27 * 888 d88P 888 Y88o88P d88P 888 888 888 888 888 888 888 28 * 88P d8888888888 Y888P d8888888888 888 .d88P Y88b. .d88P Y88b d88P 29 * 888 d88P 888 Y8P d88P 888 8888888P" "Y88888P" "Y8888P" 30 * .d88P 31 * .d88P" 32 * 888P" 33 * 34 * .d8888b. 888 .d8888b. 888 .d8888b. 888 35 * d88P Y88b 888 d88P Y88b 888 d88P Y88b 888 36 * .d88P 888 .d88P 888 .d88P 888 37 * .d88P" 888 .d88P" 888 .d88P" 888 38 * 888" 888 888" 888 888" 888 39 * 888 Y8P 888 Y8P 888 Y8P 40 * " " " 41 * 888 888 888 888 888 888 42 * 43 * 44 * TODO: add PROPER class and method documentation, just like have 45 * agreed upon hundreds of times!!!! 4 * The Publication class represents a PubMed-registered publication. 5 * Publication entries should be created using the study wizard, which connects to PubMed to fill in the fields. 6 * Since a Publication can apply to multiple studies, the entries in this table form an independent 'library' 7 * and are not connected to Study instances via a cascading relation. 46 8 */ 47 48 9 class Publication implements Serializable { 49 10 String title 50 11 String pubMedID 51 String DOI 12 String DOI // document identifier, see dx.doi.org 52 13 String authorsList 53 14 String comments -
trunk/grails-app/domain/dbnp/studycapturing/RelTime.groovy
r580 r754 2 2 * RelTime Domain Class 3 3 * 4 * Contains useful functions for the RelTime templatefield 4 * A RelTime is a TemplateFieldType that specifies a relative time aka timespan. 5 * The timespan is saved as a long value representing the number of seconds in the timespan. 6 * A human-readable representation of this number is generated, which renders e.g. '4d 2h' for 4 days 2 hours. 7 * Also, a parser is implemented which can interpret such entries when they are entered by the user. 8 * 9 * This class is purely a helper class to manipulate long fields that represent relative times. 10 * There will be no data in the database in the table that is created for this class (probably named rel_time). 5 11 * 6 12 * @author Robert Horlings -
trunk/grails-app/domain/dbnp/studycapturing/Sample.groovy
r697 r754 11 11 //static searchable = { [only: ['name']] } 12 12 13 static belongsTo = [ parent : Study] 13 // A Sample always belongs to one study. 14 static belongsTo = [parent : Study] 14 15 16 // A Sample optionally has a parent Subject from which it was taken, this Subject should be in the same parent study. 15 17 Subject parentSubject 18 19 // Also, it has a parent SamplingEvent describing the actual sampling, also within the same parent study. 16 20 SamplingEvent parentEvent 17 21 … … 26 30 */ 27 31 static List<TemplateField> giveDomainFields() { return Sample.domainFields } 32 33 // We have to specify an ontology list for the material property. However, at compile time, this ontology does of course not exist. 34 // Therefore, the ontology is added at runtime in the bootstrap, possibly downloading the ontology properties if it is not present in the database yet. 28 35 static List<TemplateField> domainFields = [ 29 36 new TemplateField( … … 40 47 41 48 static constraints = { 49 // The parent subject is optional, e.g. in a biobank of samples the subject could be unknown or non-existing. 42 50 parentSubject(nullable:true) 51 52 // The material domain field is optional 43 53 material(nullable: true) 44 54 45 // Check sif the externalSampleId (currently defined as name) is really unique within each parent study of this sample.55 // Check if the externalSampleId (currently defined as name) is really unique within each parent study of this sample. 46 56 // This feature is tested by integration test SampleTests.testSampleUniqueNameConstraint 47 57 name(unique:['parent']) -
trunk/grails-app/domain/dbnp/studycapturing/SamplingEvent.groovy
r654 r754 4 4 * The SamplingEvent class describes a sampling event, an event that also results in one or more samples. 5 5 * 6 * NOTE: according to documentation, super classes and subclasses share the same table.6 * NOTE: according to Grails documentation, super classes and subclasses share the same table. 7 7 * thus, we could merge the sampling with the Event super class and include a boolean 8 8 * However, using a separate class makes it more clear in the code that Event and SamplingEvent are treated differently 9 9 */ 10 class SamplingEvent extends TemplateEntity { 10 11 11 class SamplingEvent extends Event { 12 // A SamplingEvent always belongs to one study. 13 // Although this is technically inherited from Event, we have to specify it here again. 14 // Otherwise, Grails expects the SamplingEvent to be referenced in Study.events, 15 // where it is actually referenced in Study.samplingEvents 16 static belongsTo = [parent : Study] 17 18 static hasMany = [samples : Sample] 19 20 /** Start time of the event, relative to the start time of the study */ 21 long startTime 22 23 /** Duration of the sampling event, if it has any (default is 0) */ 24 long duration 12 25 13 26 static constraints = { 27 duration(default: 0L) 14 28 } 29 30 /** 31 * return the domain fields for this domain class 32 * @return List<TemplateField> 33 */ 34 static List<TemplateField> giveDomainFields() { return SamplingEvent.domainFields } 35 36 // To improve performance, the domain fields list is stored as a static final variable in the class. 37 static final List<TemplateField> domainFields = [ 38 new TemplateField( 39 name: 'startTime', 40 type: TemplateFieldType.RELTIME, 41 comment: "Please enter the start time as a relative time from study start date."+RelTime.getHelpText()), 42 new TemplateField( 43 name: 'duration', 44 type: TemplateFieldType.RELTIME, 45 comment: "Please enter the duration of the sampling action, if applicable. "+RelTime.getHelpText()) 46 ] 47 48 /** 49 * Get the duration of the event as RelTime 50 * @return RelTime 51 */ 52 /*RelTime getDuration() { 53 return new RelTime(duration) 54 }*/ 55 56 /** 57 * Return the start time of the event, which should be relative to the start of the study 58 * @return String a human readable representation of the start time of the event 59 */ 60 def getStartTimeString() { 61 return new RelTime(startTime).toPrettyString(); 62 } 63 64 /** 65 * Get extended, human readable string representing the duration between startTime and endTime 66 * 67 * @return String 68 */ 69 def getDurationString() { 70 return new RelTime(duration).toPrettyString(); 71 } 72 73 /** 74 * Checks whether this Event is part of one or more of the given EventGroups 75 * @param groups 76 * @return 77 */ 78 def belongsToGroup(Collection<EventGroup> groups) { 79 def eventFound = false; 80 def that = this; 81 groups.each { eventgroup -> 82 if (!eventFound) { 83 eventFound = (that.id in eventgroup.events.id); 84 } 85 } 86 87 return eventFound; 88 } 15 89 16 90 /** -
trunk/grails-app/domain/dbnp/studycapturing/Study.groovy
r667 r754 9 9 * $Date$ 10 10 */ 11 class Study extends TemplateEntity implements Serializable{11 class Study extends TemplateEntity { 12 12 static searchable = { 13 13 [only: ['title', 'Description']] 14 14 } 15 15 16 nimble.User owner 17 String title 18 String code // also enables referencing to studies from the Simple Assay Module16 nimble.User owner // The owner of the study. A new study is automatically owned by its creator. 17 String title // The title of the study 18 String code // currently used as the external study ID, e.g. to reference a study in a SAM module 19 19 Date dateCreated 20 20 Date lastUpdated … … 28 28 29 29 static hasMany = [ 30 editors: nimble.User, 31 readers: nimble.User, 30 editors: nimble.User, // Users with read/write access to the study 31 readers: nimble.User, // Users with only read access to the study 32 32 subjects: Subject, 33 samplingEvents: SamplingEvent, 33 34 events: Event, 34 samplingEvents: SamplingEvent,35 35 eventGroups: EventGroup, 36 36 samples: Sample, … … 50 50 autoTimestamp true 51 51 } 52 53 // The external study ID is currently defined as the code of the study. 54 // It is used from within dbNP submodules to refer to particular study in this GSCF instance. 55 def getExternalStudyId() { code } 52 56 53 57 /** -
trunk/grails-app/domain/dbnp/studycapturing/StudyPerson.groovy
r540 r754 1 1 package dbnp.studycapturing 2 3 /**4 * 888 888 888 888 8888888888 8888888b. 88888888885 * 888 o 888 888 888 888 888 Y88b 8886 * 888 d8b 888 888 888 888 888 888 8887 * 888 d888b 888 8888888888 8888888 888 d88P 88888888 * 888d88888b888 888 888 888 8888888P" 8889 * 88888P Y88888 888 888 888 888 T88b 88810 * 8888P Y8888 888 888 888 888 T88b 88811 * 888P Y888 888 888 8888888888 888 T88b 888888888812 *13 * 8888888 .d8888b. 88888888888 888 888 888888888814 * 888 d88P Y88b 888 888 888 88815 * 888 Y88b. 888 888 888 88816 * 888 "Y888b. 888 8888888888 888888817 * 888 "Y88b. 888 888 888 88818 * 888 "888 888 888 888 88819 * 888 Y88b d88P 888 888 888 88820 * 8888888 "Y8888P" 888 888 888 888888888821 *22 * 888888 d8888 888 888 d8888 8888888b. .d88888b. .d8888b.23 * "88b d88888 888 888 d88888 888 "Y88b d88P" "Y88b d88P Y88b24 * 888 d88P888 888 888 d88P888 888 888 888 888 888 88825 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 88826 * 888 d88P 888 Y88b d88P d88P 888 888 888 888 888 88827 * 888 d88P 888 Y88o88P d88P 888 888 888 888 888 888 88828 * 88P d8888888888 Y888P d8888888888 888 .d88P Y88b. .d88P Y88b d88P29 * 888 d88P 888 Y8P d88P 888 8888888P" "Y88888P" "Y8888P"30 * .d88P31 * .d88P"32 * 888P"33 *34 * .d8888b. 888 .d8888b. 888 .d8888b. 88835 * d88P Y88b 888 d88P Y88b 888 d88P Y88b 88836 * .d88P 888 .d88P 888 .d88P 88837 * .d88P" 888 .d88P" 888 .d88P" 88838 * 888" 888 888" 888 888" 88839 * 888 Y8P 888 Y8P 888 Y8P40 * " " "41 * 888 888 888 888 888 88842 *43 *44 * TODO: add PROPER class and method documentation, just like have45 * agreed upon hundreds of times!!!!46 */47 2 48 3 /** … … 50 5 */ 51 6 class StudyPerson implements Serializable { 52 Person person 53 PersonRole role 7 8 // A StudyPerson relation always belongs to one study. 9 static belongsTo = [parent : Study] 10 11 /** The Person which is referenced in the Study */ 12 Person person 13 14 /** The role this Person has in the Study */ 15 PersonRole role 54 16 55 17 static constraints = { -
trunk/grails-app/domain/dbnp/studycapturing/Subject.groovy
r667 r754 12 12 * $Date$ 13 13 */ 14 class Subject extends TemplateEntity implements Serializable{14 class Subject extends TemplateEntity { 15 15 // uncommented due to searchable issue 16 16 // @see http://jira.codehaus.org/browse/GRAILSPLUGINS-1577 17 17 //static searchable = { [only: ['name']] } 18 18 19 // A Subject always belongs to one Study 20 static belongsTo = [parent : Study] 21 22 /** The name of the subject, which should be unique within the study */ 19 23 String name 24 25 /** The species of the subject. In the domainFields property, the ontologies from which this term may come are specified. */ 20 26 Term species 27 28 static constraints = { 29 // Ensure that the subject name is unique within the study 30 name(unique:['parent']) 31 } 32 21 33 22 34 /** … … 26 38 static List<TemplateField> giveDomainFields() { return Subject.domainFields; } 27 39 40 // We have to specify an ontology list for the species property. However, at compile time, this ontology does of course not exist. 41 // Therefore, the ontology is added at runtime in the bootstrap, possibly downloading the ontology properties if it is not present in the database yet. 28 42 static List<TemplateField> domainFields = [ 29 43 new TemplateField( -
trunk/grails-app/domain/dbnp/studycapturing/Template.groovy
r556 r754 1 1 package dbnp.studycapturing 2 import java.lang.reflect.Method3 2 4 3 /** 5 * The Template class describes a study template, which is basically an extension of the study capture entities 6 * in terms of extra fields (described by classes that extend the TemplateField class). 7 * At this moment, only extension of the study and subject entities is implemented. 4 * The Template class describes a TemplateEntity template, which is basically an extension of the study capture entities 5 * in terms of extra fields (which are described by classes that extend the TemplateField class). 6 * Study, Subject, Sample and Event are all TemplateEntities. 7 * 8 * Within a Template, we have two different types of fields: 'domain fields' and 'template fields'. 9 * The domain fields are TemplateFields which are given by the TemplateEntity itself and therefore always present 10 * in any instance of that TemplateEntity. They are specified by implementing TemplateEntity.giveDomainFields() 11 * The template fields are TemplateFields which are added specifically by the Template. They are specified 12 * in the fields property of the Template object which is referenced by the TemplateEntity.template property. 8 13 * 9 14 * Revision information: … … 13 18 */ 14 19 class Template implements Serializable { 20 21 /** The name of the template */ 15 22 String name 23 24 /** A string describing the template to other users */ 16 25 String description 26 27 /** The target TemplateEntity for this template */ 17 28 Class entity 18 //nimble.User owner 29 30 /** The owner of the template. If the owner is not defined, it is a shared/public template */ 31 nimble.User owner 32 33 /** The template fields which are the members of this template. This is a List to preserve the field order */ 19 34 List fields 20 35 static hasMany = [fields: TemplateField] 21 36 22 37 static constraints = { 38 39 owner(nullable: true, blank: true) 23 40 description(nullable: true, blank: true) 24 41 … … 49 66 // outcommented for now due to bug in Grails / Hibernate 50 67 // see http://jira.codehaus.org/browse/GRAILS-6020 68 // This is to verify that the template name is unique with respect to the parent entity. 69 // TODO: this probably has to change in the case of private templates of different users, 70 // which can co-exist with the same name. See also TemplateField 51 71 // name(unique:['entity']) 52 72 } -
trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy
r725 r754 5 5 6 6 /** 7 * TemplateEntity Domain Class 7 * The TemplateEntity domain Class is a superclass for all template-enabled study capture entities, including 8 * Study, Subject, Sample and Event. This class provides functionality for storing the different TemplateField 9 * values and returning the combined list of 'domain fields' and 'template fields' of a TemplateEntity. 10 * For an explanation of those terms, see the Template class. 11 * 12 * @see dbnp.studycapturing.Template 8 13 * 9 14 * Revision information: … … 13 18 */ 14 19 abstract class TemplateEntity implements Serializable { 20 21 /** The actual template of this TemplateEntity instance */ 15 22 Template template 23 24 // Maps for storing the different template field values 16 25 Map templateStringFields = [:] 17 26 Map templateTextFields = [:] … … 45 54 46 55 static mapping = { 56 57 // Specify that each TemplateEntity-subclassing entity should have its own tables to store TemplateField values. 58 // This results in a lot of tables, but performance is presumably better because in most queries, only values of 59 // one specific entity will be retrieved. Also, because of the generic nature of these tables, they can end up 60 // containing a lot of records (there is a record for each entity instance for each property, instead of a record 61 // for each instance as is the case with 'normal' straightforward database tables. Therefore, it's better to split 62 // out the data to many tables. 47 63 tablePerHierarchy false 48 64 65 // Make sure that the text fields are really stored as TEXT, so that those Strings can have an arbitrary length. 49 66 templateTextFields type: 'text' 50 67 } 51 68 69 // Inject the service for storing files (for TemplateFields of TemplateFieldType FILE). 52 70 def fileService 53 71 -
trunk/grails-app/domain/dbnp/studycapturing/TemplateField.groovy
r556 r754 4 4 5 5 /** 6 * This is the class for template fields. These should be part of one or more templates via Template.fields 6 * A TemplateField is a specification for either a 'domain field' of a subclass of TemplateEntity or a 7 * 'template field' for a specific Template. See the Template class for an explanation of these terms. 8 * The TemplateField class contains all information which is needed to specify what kind of data can be stored 9 * in this particular field, such as the TemplateFieldType, the name, the ontologies from which terms can derive 10 * in case of an ONTOLOGYTERM field, the list entries in case of a STRINGLIST fields, and so on. 11 * The actual values of the template fields are stored in instances of subclasses of the TemplateEntity class. 12 * For example, if there exists a Study template with a 'description' TemplateField as a member of Template.fields, 13 * the actual description for each Study would be stored in the inherited templateStringFields map of that Study instance. 14 * 15 * One TemplateField can belong to many Templates, but they have to be the same entity as the TemplateField itself. 7 16 * 8 17 * Revision information: … … 12 21 */ 13 22 class TemplateField implements Serializable { 23 24 /** The name of the TemplateField, by which it is represented to the user. */ 14 25 String name 26 27 /** The type of this TemplateField, such as STRING, ONTOLOGYTERM etc. */ 15 28 TemplateFieldType type 16 Class entity 29 30 /** The entity for which this TemplateField is meant. Only Templates for this entity can contain this TemplateField */ 31 Class entity 32 33 /** The unit of the values of this TemplateField (optional) */ 17 34 String unit 18 String comment // help string for the user interface 35 36 /** The help string which is shown in the user interface to describe this template field (optional, TEXT) */ 37 String comment 38 39 /** The different list entries for a STRINGLIST TemplateField. This property is only used if type == TemplateFieldType.STRINGLIST */ 19 40 List listEntries 41 42 /** Indicates whether this field is required to be filled out or not */ 20 43 boolean required 44 45 /** Indicates whether this field is the preferred identifier for the resulting templated entity. 46 This is for example used when importing to match entries in the database against the ones that are being imported. */ 21 47 boolean preferredIdentifier 22 48 23 49 static hasMany = [ 24 50 listEntries: TemplateFieldListItem, // to store the entries to choose from when the type is 'item from predefined list' 25 ontologies: Ontology 51 ontologies: Ontology // to store the ontologies to choose from when the type is 'ontology term' 26 52 ] 27 53 28 54 static constraints = { 29 // TODO: verify that TemplateField names are unique within templates of each super entity 55 56 // outcommented for now due to bug in Grails / Hibernate 57 // see http://jira.codehaus.org/browse/GRAILS-6020 58 // This is to verify that TemplateField names are unique within templates of each super entity 59 // TODO: this probably has to change in the case of private templates of different users, 60 // which can co-exist with the same name. See also Template 61 // name(unique:['entity']) 62 30 63 name(nullable: false, blank: false) 31 64 type(nullable: false, blank: false) … … 38 71 39 72 static mapping = { 40 // TODO: this doesn't seem to work in Postgres73 // Make sure the comments can be Strings of arbitrary length 41 74 comment type: 'text' 42 75 } -
trunk/grails-app/domain/dbnp/studycapturing/TemplateFieldListItem.groovy
r496 r754 2 2 3 3 /** 4 * TemplateFieldListItem Domain Class 4 * TemplateFieldListItem Domain Class. Used to represent the list items in a STRINGLIST TemplateField. 5 5 * 6 6 * Revision information: … … 10 10 */ 11 11 class TemplateFieldListItem implements Serializable { 12 13 // A TemplateFieldListItem always belongs to one TemplateField of TemplateFieldType STRINGLIST 14 static belongsTo = [parent : TemplateField] 15 16 /** The caption of the list item */ 12 17 String name 13 18 -
trunk/grails-app/domain/dbnp/studycapturing/TemplateFieldType.groovy
r559 r754 2 2 3 3 /** 4 * Enum describing the type of a templated field.4 * Enum describing the type of a TemplateField. 5 5 * Revision information: 6 6 * $Rev$ … … 21 21 BOOLEAN('Boolean') 22 22 // TODO: add a timezone-aware date type to use for study start date 23 // TODO: add a BOOLEAN type (checkbox)24 23 25 24 String name -
trunk/grails-app/views/query/selectsample.gsp
r497 r754 68 68 <td> ${sample.material}</td> 69 69 70 <td> ${event.get PrettyDuration(event.startTime)} </td>70 <td> ${event.getStartTimeString()} </td> 71 71 72 72 <td> -
trunk/grails-app/views/study/show.gsp
r629 r754 450 450 events = studyInstance.events + studyInstance.samplingEvents; 451 451 sortedEvents = events.sort( { a, b -> 452 a.startTime == b.startTime ?453 a.getDuration().getValue() <=> b.getDuration().getValue() :454 452 //a.startTime == b.startTime ? 453 //a.getDuration().getValue() <=> b.getDuration().getValue() : 454 a.startTime <=> b.startTime 455 455 } as Comparator ) 456 456 %> … … 463 463 </td> 464 464 </g:if> 465 <td>${ new RelTime(event.startTime).toPrettyString()}</td>466 <td>${event.get PrettyDuration()}</td>465 <td>${event.getStartTimeString()}</td> 466 <td>${event.getDurationString()}</td> 467 467 <td>${event.template.name}</td> 468 468 <td>
Note: See TracChangeset
for help on using the changeset viewer.