Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Features
- Added ability to use posts to sequence methods [2555](https://github.com/GMOD/Apollo/pull/2558).
- Added system info web service [2557](https://github.com/GMOD/Apollo/pull/2557).
- Add "merged from" comment to merged in transcript and gene [2567](https://github.com/GMOD/Apollo/issues/2567).
- Added support for "obsolete", and partials in the interface for GFF3s [2573](https://github.com/GMOD/Apollo/pull/2573).

Bug Fixes:

Expand Down
72 changes: 72 additions & 0 deletions grails-app/controllers/org/bbop/apollo/AnnotatorController.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ class AnnotatorController {
feature.name = data.name
feature.symbol = data.symbol
feature.description = data.description
feature.isObsolete = data.obsolete
if(data.containsKey("obsolete")) {
feature.isObsolete = data.getBoolean("obsolete")
}
Expand Down Expand Up @@ -328,6 +329,76 @@ class AnnotatorController {
render updateFeatureContainer
}

/**
* updates shallow properties of gene / feature
* @return
*/
@RestApiMethod(description = "Update partial fmin / famx", path = "/annotator/updatePartials", verb = RestApiVerb.POST)
@RestApiParams(params = [
@RestApiParam(name = "username", type = "email", paramType = RestApiParamType.QUERY)
, @RestApiParam(name = "password", type = "password", paramType = RestApiParamType.QUERY)
, @RestApiParam(name = "uniquename", type = "string", paramType = RestApiParamType.QUERY, description = "Uniquename (UUID) of the feature we are editing")
, @RestApiParam(name = "data", type = "string", paramType = RestApiParamType.QUERY, description = "Annotation Info object")
]
)
@Transactional
def updatePartials() {
log.debug "update partials ${params.data}"
JSONObject data = permissionService.handleInput(request, params)
if (!permissionService.hasPermissions(data, PermissionEnum.WRITE)) {
render status: HttpStatus.UNAUTHORIZED
return
}
Feature feature = Feature.findByUniqueName(data.uniquename)
FeatureLocation featureLocation = feature.featureLocation

boolean isFminPartial = feature.featureLocation.isFminPartial
boolean isFmaxPartial = feature.featureLocation.isFmaxPartial

JSONObject originalFeatureJsonObject = featureService.convertFeatureToJSON(feature)
FeatureOperation featureOperation
if(data.containsKey(FeatureStringEnum.IS_FMIN_PARTIAL.value)
&&
data.getBoolean(FeatureStringEnum.IS_FMIN_PARTIAL.value) != isFminPartial
){
featureOperation = FeatureOperation.SET_PARTIAL_FMIN
// featureLocation.isFminPartial = data.getBoolean(FeatureStringEnum.IS_FMIN_PARTIAL.value)
featureService.setPartialFmin(feature,data.getBoolean(FeatureStringEnum.IS_FMIN_PARTIAL.value).booleanValue(),feature.featureLocation.fmin)
}
else
if(data.containsKey(FeatureStringEnum.IS_FMAX_PARTIAL.value)
&&
data.getBoolean(FeatureStringEnum.IS_FMAX_PARTIAL.value) != isFmaxPartial
){
featureOperation = FeatureOperation.SET_PARTIAL_FMAX
featureService.setPartialFmax(feature,data.getBoolean(FeatureStringEnum.IS_FMAX_PARTIAL.value).booleanValue(),feature.featureLocation.fmax)
}
else{
throw new AnnotationException("Partials have not changed, so not doing anything")
}
featureLocation.save(flush: true, failOnError: true,insert:false)

JSONObject updateFeatureContainer = jsonWebUtilityService.createJSONFeatureContainer();
// its either a gene or

User user = permissionService.getCurrentUser(data)
JSONObject currentFeatureJsonObject = featureService.convertFeatureToJSON(feature)

JSONArray oldFeaturesJsonArray = new JSONArray()
oldFeaturesJsonArray.add(originalFeatureJsonObject)
JSONArray newFeaturesJsonArray = new JSONArray()
newFeaturesJsonArray.add(currentFeatureJsonObject)
featureEventService.addNewFeatureEvent(featureOperation,
feature.name,
feature.uniqueName,
data,
oldFeaturesJsonArray,
newFeaturesJsonArray,
user)

render updateFeatureContainer
}


@RestApiMethod(description = "Update exon boundaries", path = "/annotator/setExonBoundaries", verb = RestApiVerb.POST)
@RestApiParams(params = [
Expand Down Expand Up @@ -991,6 +1062,7 @@ class AnnotatorController {
if (!compareNullToBlank(feature.symbol,data.symbol)) return FeatureOperation.SET_SYMBOL
if (!compareNullToBlank(feature.description,data.description)) return FeatureOperation.SET_DESCRIPTION
if (!compareNullToBlank(feature.status,data.status)) return FeatureOperation.SET_STATUS
if(feature.isObsolete != data.obsolete ) return FeatureOperation.SET_OBSOLETE

log.warn("Updated generic feature")
null
Expand Down
14 changes: 4 additions & 10 deletions grails-app/domain/org/bbop/apollo/FeatureLocation.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,15 @@ class FeatureLocation {
static belongsTo = [Feature]


static hasMany = [
featureLocationPublications: Publication
]


public boolean equals(Object other) {
boolean equals(Object other) {
if (this.is(other)) return true
if (getClass() != other.class) return false
FeatureLocation castOther = (FeatureLocation) other;

return ((this.getFeature() == castOther.getFeature()) || (this.getFeature() != null && castOther.getFeature() != null && this.getFeature().equals(castOther.getFeature()))) && (this.getLocgroup() == castOther.getLocgroup()) && (this.getRank() == castOther.getRank());
}

public int hashCode() {
int hashCode() {
int result = 17;

result = 37 * result + (getFeature() == null ? 0 : this.getFeature().hashCode());
Expand All @@ -63,10 +58,10 @@ class FeatureLocation {
* We use this as an artificial accessor in case the property has not been calculatd
* @return
*/
public Integer calculateLength(){
Integer calculateLength(){
return fmax-fmin
}
public FeatureLocation generateClone() {
FeatureLocation generateClone() {
FeatureLocation cloned = new FeatureLocation();
cloned.sequence = this.sequence;
cloned.feature = this.feature;
Expand All @@ -79,7 +74,6 @@ class FeatureLocation {
cloned.residueInfo = this.residueInfo;
cloned.locgroup = this.locgroup;
cloned.rank = this.rank;
cloned.featureLocationPublications = this.featureLocationPublications;
return cloned;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,9 @@ class ChadoHandlerService {
endTime = System.currentTimeMillis()
log.debug "Time taken to create Chado featureloc for feature fmin: ${feature.fmin} fmax: ${feature.fmax}: ${endTime - startTime} ms"
exportStatisticsMap['featureloc_count'] += 1
feature.featureLocation.featureLocationPublications.each { featureLocationPublication ->
createChadoFeaturelocPub(chadoFeatureLoc, featureLocationPublication)
}
// feature.featureLocation.featureLocationPublications.each { featureLocationPublication ->
// createChadoFeaturelocPub(chadoFeatureLoc, featureLocationPublication)
// }
return chadoFeatureLoc
}

Expand Down
59 changes: 49 additions & 10 deletions grails-app/services/org/bbop/apollo/FeatureService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.bbop.apollo.alteration.SequenceAlterationInContext
import org.bbop.apollo.geneProduct.GeneProduct
import org.bbop.apollo.go.GoAnnotation
import org.bbop.apollo.gwt.shared.FeatureStringEnum
import org.bbop.apollo.history.FeatureOperation
import org.bbop.apollo.sequence.SequenceTranslationHandler
import org.bbop.apollo.sequence.Strand
import org.bbop.apollo.sequence.TranslationTable
Expand Down Expand Up @@ -1966,6 +1967,9 @@ public void setTranslationEnd(Transcript transcript, int translationEnd) {
if (gsolFeature.symbol) {
jsonFeature.put(FeatureStringEnum.SYMBOL.value, gsolFeature.symbol);
}
if (gsolFeature.isObsolete) {
jsonFeature.put(FeatureStringEnum.OBSOLETE.value, gsolFeature.isObsolete);
}
if (gsolFeature.description) {
jsonFeature.put(FeatureStringEnum.DESCRIPTION.value, gsolFeature.description);
}
Expand Down Expand Up @@ -2356,20 +2360,21 @@ public void setTranslationEnd(Transcript transcript, int translationEnd) {

@Timed
JSONObject convertFeatureLocationToJSON(FeatureLocation gsolFeatureLocation) throws JSONException {
JSONObject jsonFeatureLocation = new JSONObject();
JSONObject jsonFeatureLocation = new JSONObject()
if (gsolFeatureLocation.id) {
jsonFeatureLocation.put(FeatureStringEnum.ID.value, gsolFeatureLocation.id);
jsonFeatureLocation.put(FeatureStringEnum.ID.value, gsolFeatureLocation.id)
}
jsonFeatureLocation.put(FeatureStringEnum.FMIN.value, gsolFeatureLocation.getFmin());
jsonFeatureLocation.put(FeatureStringEnum.FMAX.value, gsolFeatureLocation.getFmax());
if (gsolFeatureLocation.isIsFminPartial()) {
jsonFeatureLocation.put(FeatureStringEnum.IS_FMIN_PARTIAL.value, true);
jsonFeatureLocation.put(FeatureStringEnum.FMIN.value, gsolFeatureLocation.getFmin())
jsonFeatureLocation.put(FeatureStringEnum.FMAX.value, gsolFeatureLocation.getFmax())
if(gsolFeatureLocation.getIsFminPartial()){
jsonFeatureLocation.put(FeatureStringEnum.IS_FMIN_PARTIAL.value, gsolFeatureLocation.getIsFminPartial())
}
if (gsolFeatureLocation.isIsFmaxPartial()) {
jsonFeatureLocation.put(FeatureStringEnum.IS_FMAX_PARTIAL.value, true);

if(gsolFeatureLocation.getIsFmaxPartial()){
jsonFeatureLocation.put(FeatureStringEnum.IS_FMAX_PARTIAL.value, gsolFeatureLocation.getIsFmaxPartial())
}
jsonFeatureLocation.put(FeatureStringEnum.STRAND.value, gsolFeatureLocation.getStrand());
return jsonFeatureLocation;
jsonFeatureLocation.put(FeatureStringEnum.STRAND.value, gsolFeatureLocation.getStrand())
return jsonFeatureLocation
}

@Transactional
Expand Down Expand Up @@ -3584,4 +3589,38 @@ public void setTranslationEnd(Transcript transcript, int translationEnd) {

return false
}

@Transactional
def setPartialFmin(Feature feature,boolean fminPartial,int fmin){
FeatureLocation featureLocation = feature.featureLocation
if(fmin==featureLocation.fmin){
featureLocation.isFminPartial = fminPartial
featureLocation.save()
}

List<Feature> childFeatures = feature.parentFeatureRelationships*.childFeature
if(childFeatures){
for(childFeature in childFeatures){
setPartialFmin(childFeature,fminPartial,fmin)
}
}
}

@Transactional
def setPartialFmax(Feature feature,boolean fmaxPartial,int fmax){
FeatureLocation featureLocation = feature.featureLocation
if(fmax==featureLocation.fmax){
featureLocation.isFmaxPartial = fmaxPartial
featureLocation.save()
}

List<Feature> childFeatures = feature.parentFeatureRelationships*.childFeature
if(childFeatures){
for(childFeature in childFeatures){
setPartialFmax(childFeature,fmaxPartial,fmax)
}
}

}

}
15 changes: 12 additions & 3 deletions grails-app/services/org/bbop/apollo/Gff3HandlerService.groovy
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package org.bbop.apollo

import org.apache.commons.lang.WordUtils
import org.bbop.apollo.geneProduct.GeneProduct
import org.bbop.apollo.go.GoAnnotation
import org.bbop.apollo.gwt.shared.FeatureStringEnum
import org.bbop.apollo.sequence.Strand
import org.grails.plugins.metrics.groovy.Timed
import org.springframework.format.datetime.DateFormatter
import java.text.SimpleDateFormat


Expand Down Expand Up @@ -53,6 +50,9 @@ class Gff3HandlerService {
writeObject.attributesToExport.add(FeatureStringEnum.COMMENTS.value);
writeObject.attributesToExport.add(FeatureStringEnum.DATE_CREATION.value);
writeObject.attributesToExport.add(FeatureStringEnum.DATE_LAST_MODIFIED.value);
writeObject.attributesToExport.add(FeatureStringEnum.IS_FMIN_PARTIAL.value);
writeObject.attributesToExport.add(FeatureStringEnum.IS_FMAX_PARTIAL.value);
writeObject.attributesToExport.add(FeatureStringEnum.OBSOLETE.value);

if (!writeObject.file.canWrite()) {
throw new IOException("Cannot write GFF3 to: " + writeObject.file.getAbsolutePath());
Expand Down Expand Up @@ -355,6 +355,15 @@ class Gff3HandlerService {
String productString = geneProductService.convertGeneProductsToGff3String(feature.geneProducts)
attributes.put(FeatureStringEnum.GENE_PRODUCT.value, encodeString(productString))
}
if (writeObject.attributesToExport.contains(FeatureStringEnum.IS_FMIN_PARTIAL.value) && feature.featureLocation.isFminPartial) {
attributes.put(FeatureStringEnum.IS_FMIN_PARTIAL.value, feature.featureLocation.isFminPartial.toString())
}
if (writeObject.attributesToExport.contains(FeatureStringEnum.OBSOLETE.value) && feature.isObsolete) {
attributes.put(FeatureStringEnum.OBSOLETE.value, feature.isObsolete.toString())
}
if (writeObject.attributesToExport.contains(FeatureStringEnum.IS_FMAX_PARTIAL.value) && feature.featureLocation.isFmaxPartial) {
attributes.put(FeatureStringEnum.IS_FMAX_PARTIAL.value, feature.featureLocation.isFmaxPartial.toString())
}
if (writeObject.attributesToExport.contains(FeatureStringEnum.STATUS.value) && feature.getStatus() != null) {
attributes.put(FeatureStringEnum.STATUS.value, encodeString(feature.getStatus().value));
}
Expand Down
3 changes: 3 additions & 0 deletions src/groovy/org/bbop/apollo/history/FeatureOperation.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum FeatureOperation {
SET_TRANSLATION_ENDS,
SET_LONGEST_ORF,
FLIP_STRAND,
SET_OBSOLETE,
REMOVE_CDS,
SET_READTHROUGH_STOP_CODON,
UNSET_READTHROUGH_STOP_CODON,
Expand All @@ -32,6 +33,8 @@ enum FeatureOperation {
DISSOCIATE_TRANSCRIPT_FROM_GENE,
ASSOCIATE_FEATURE_TO_GENE,
DISSOCIATE_FEATURE_FROM_GENE,
SET_PARTIAL_FMIN,
SET_PARTIAL_FMAX,

// structural data
SET_SYMBOL(false),
Expand Down
Loading