Skip to content

Commit 1c82fb5

Browse files
committed
Mark ExperimentalFactor as auto-generated
Remove the flag if a factor is curated in the UI.
1 parent e47e458 commit 1c82fb5

26 files changed

Lines changed: 535 additions & 265 deletions

gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/SplitExperimentServiceImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ private Collection<ExperimentalFactor> cloneExperimentalFactors( Collection<Expe
394394
clone.setType( ef.getType() );
395395
clone.getFactorValues().addAll( this.cloneFactorValues( ef.getFactorValues(), clone, old2cloneFV ) );
396396
clone.setExperimentalDesign( ed );
397+
clone.setAutoGenerated( ef.isAutoGenerated() );
397398
result.add( clone );
398399
// assert clone.getId() == null;
399400
}

gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchInfoPopulationHelperServiceImpl.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,7 @@ private <T> ExperimentalFactor createExperimentalFactor( ExpressionExperiment ee
906906
* persist
907907
*/
908908
fv.setCharacteristics( chars );
909-
experimentService.addFactorValue( ee, fv );
909+
experimentService.addFactorValue( ee, fv, true );
910910

911911
for ( T d : descriptorsToBatch.get( batchId ) ) {
912912
d2fv.put( d, fv );
@@ -924,9 +924,8 @@ private ExperimentalFactor makeFactorForBatch( ExpressionExperiment ee ) {
924924
ef.setExperimentalDesign( ed );
925925
ef.setName( ExperimentFactorUtils.BATCH_FACTOR_NAME );
926926
ef.setDescription( "Scan date or similar proxy for 'batch'" + " extracted from the raw data files." );
927-
928-
ef = this.persistFactor( ee, ef );
929-
return ef;
927+
ef.setAutoGenerated( true );
928+
return this.persistFactor( ee, ef );
930929
}
931930

932931
private ExperimentalFactor persistFactor( ExpressionExperiment ee, ExperimentalFactor factor ) {

gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchInfoPopulationServiceImpl.java

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
import ubic.gemma.model.common.description.DatabaseEntry;
3232
import ubic.gemma.model.expression.bioAssay.BioAssay;
3333
import ubic.gemma.model.expression.biomaterial.BioMaterial;
34-
import ubic.gemma.model.expression.experiment.*;
34+
import ubic.gemma.model.expression.experiment.ExperimentFactorUtils;
35+
import ubic.gemma.model.expression.experiment.ExperimentalDesign;
36+
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
37+
import ubic.gemma.model.expression.experiment.ExpressionExperiment;
3538
import ubic.gemma.persistence.service.common.auditAndSecurity.AuditEventService;
3639
import ubic.gemma.persistence.service.common.auditAndSecurity.AuditTrailService;
3740
import ubic.gemma.persistence.service.expression.bioAssay.BioAssayService;
@@ -375,33 +378,22 @@ static Map<String, String> readFastqHeaders( Path headerFile ) throws IOExceptio
375378
*/
376379
private void removeExistingBatchFactor( ExpressionExperiment ee ) {
377380
ExperimentalDesign ed = ee.getExperimentalDesign();
378-
379381
if ( ed == null ) {
380382
log.warn( ee + " does not have an experimental design, cannot remove batch factor." );
381383
return;
382384
}
383-
384-
ExperimentalFactor toRemove = null;
385-
386385
for ( ExperimentalFactor ef : ed.getExperimentalFactors() ) {
387-
388386
if ( ExperimentFactorUtils.isBatchFactor( ef ) ) {
389-
toRemove = ef;
390-
break;
391-
/*
392-
* FIXME handle the case where we somehow have two or more.
393-
*/
387+
if ( !ef.isAutoGenerated() ) {
388+
log.warn( ef + " was manually curated, not removing it." );
389+
continue;
390+
}
391+
BatchInfoPopulationServiceImpl.log.info( "Removing existing batch factor: " + ef );
392+
experimentalFactorService.remove( ef );
393+
ee.getExperimentalDesign().getExperimentalFactors().remove( ef );
394+
this.expressionExperimentService.update( ee );
394395
}
395396
}
396-
397-
if ( toRemove == null ) {
398-
return;
399-
}
400-
401-
BatchInfoPopulationServiceImpl.log.info( "Removing existing batch factor: " + toRemove );
402-
experimentalFactorService.remove( toRemove );
403-
ee.getExperimentalDesign().getExperimentalFactors().remove( toRemove );
404-
this.expressionExperimentService.update( ee );
405397
}
406398

407399
}

gemma-core/src/main/java/ubic/gemma/core/loader/expression/geo/GeoConverterImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ public void convertSubsetToExperimentalFactor( ExpressionExperiment expExp, GeoS
247247

248248
experimentalFactor.setType( FactorType.CATEGORICAL );
249249
experimentalFactor.setDescription( "Converted from GEO subset " + geoSubSet.getGeoAccession() );
250+
experimentalFactor.setAutoGenerated( true );
250251

251252
boolean duplicateExists = false;
252253
for ( ExperimentalFactor existingExperimentalFactor : existingExperimentalFactors ) {
@@ -1600,9 +1601,8 @@ private ExperimentalFactor convertReplicationToFactor( GeoReplication replicatio
16001601
result.setName( replication.getType().toString() );
16011602
result.setDescription( replication.getDescription() );
16021603
result.setType( FactorType.CATEGORICAL );
1603-
Characteristic term = this.convertReplicatationType( replication.getType() );
1604-
1605-
result.setCategory( term );
1604+
result.setCategory( this.convertReplicatationType( replication.getType() ) );
1605+
result.setAutoGenerated( true );
16061606
return result;
16071607

16081608
}
@@ -2250,8 +2250,8 @@ private ExperimentalFactor convertVariableToFactor( GeoVariable variable ) {
22502250
result.setDescription( variable.getDescription() );
22512251
Characteristic term = Characteristic.Factory.newInstance();
22522252
this.convertVariableType( term, variable.getType() );
2253-
22542253
if ( term.getCategory() != null ) result.setCategory( term );
2254+
result.setAutoGenerated( true );
22552255
return result;
22562256
}
22572257

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package ubic.gemma.core.util;
2+
3+
import org.springframework.beans.BeanWrapper;
4+
import org.springframework.beans.PropertyValue;
5+
6+
import javax.annotation.Nullable;
7+
import java.util.Objects;
8+
9+
public class BeanWrapperUtils {
10+
11+
/**
12+
* Set a property value on a {@link BeanWrapper} and return whether the value was changed.
13+
* @return if the value was changed as per {@link Objects#equals(Object, Object)}
14+
* @see BeanWrapper#setPropertyValue(PropertyValue)
15+
*/
16+
public static <T> boolean setPropertyValue( BeanWrapper bw, String property, @Nullable T newVal ) {
17+
if ( !Objects.equals( bw.getPropertyValue( property ), newVal ) ) {
18+
bw.setPropertyValue( property, newVal );
19+
return true;
20+
}
21+
return false;
22+
}
23+
}

gemma-core/src/main/java/ubic/gemma/model/expression/experiment/ExperimentalFactor.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class ExperimentalFactor extends AbstractDescribable implements SecuredCh
5353
@Deprecated
5454
private Set<Characteristic> annotations = new HashSet<>();
5555
private ExpressionExperiment securityOwner;
56+
private boolean autoGenerated;
5657

5758
/**
5859
* No-arg constructor added to satisfy javabean contract
@@ -146,6 +147,18 @@ public void setAnnotations( Set<Characteristic> annotations ) {
146147
this.annotations = annotations;
147148
}
148149

150+
151+
/**
152+
* Indicate if this factor was automatically generated.
153+
*/
154+
public boolean isAutoGenerated() {
155+
return autoGenerated;
156+
}
157+
158+
public void setAutoGenerated( boolean autoGenerated ) {
159+
this.autoGenerated = autoGenerated;
160+
}
161+
149162
@Override
150163
public boolean equals( Object obj ) {
151164
if ( this == obj )
@@ -162,7 +175,9 @@ public boolean equals( Object obj ) {
162175

163176
@Override
164177
public String toString() {
165-
return super.toString() + ( type != null ? " Type=" + type : "" );
178+
return super.toString()
179+
+ ( type != null ? " Type=" + type : "" )
180+
+ ( autoGenerated ? " [Auto-Generated]" : "" );
166181
}
167182

168183
public static final class Factory {

gemma-core/src/main/java/ubic/gemma/model/expression/experiment/FactorValueValueObject.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
import io.swagger.v3.oas.annotations.media.Schema;
1313
import lombok.Data;
1414
import lombok.EqualsAndHashCode;
15-
import ubic.gemma.model.util.ModelUtils;
1615
import ubic.gemma.model.annotations.GemmaWebOnly;
1716
import ubic.gemma.model.common.description.Characteristic;
17+
import ubic.gemma.model.util.ModelUtils;
18+
19+
import javax.annotation.Nullable;
1820

1921
/**
2022
* Each {@link FactorValue} can be associated with multiple characteristics (or with a measurement). However, for
@@ -51,6 +53,7 @@ public class FactorValueValueObject extends AbstractFactorValueValueObject {
5153
/**
5254
* It could be the id of the measurement if there is no characteristic.
5355
*/
56+
@Nullable
5457
@GemmaWebOnly
5558
private Long charId;
5659
@GemmaWebOnly

gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractService.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.*;
1313
import java.util.function.Function;
1414
import java.util.function.Supplier;
15+
import java.util.stream.Collectors;
1516
import java.util.stream.Stream;
1617

1718
import static java.util.Objects.requireNonNull;
@@ -89,6 +90,28 @@ public Collection<O> load( Collection<Long> ids ) {
8990
return mainDao.load( ids );
9091
}
9192

93+
@Override
94+
@Transactional(readOnly = true)
95+
public Collection<O> loadOrFail( Collection<Long> ids ) throws NullPointerException {
96+
return loadOrFail( ids, NullPointerException::new );
97+
}
98+
99+
@Override
100+
@Transactional(readOnly = true)
101+
public <T extends Exception> Collection<O> loadOrFail( Collection<Long> ids, Function<String, T> exceptionSupplier ) throws T {
102+
ids = new HashSet<>( ids );
103+
Collection<O> result = load( ids );
104+
if ( result.size() < ids.size() ) {
105+
for ( O o : result ) {
106+
ids.remove( o.getId() );
107+
}
108+
throw exceptionSupplier.apply( String.format( "No %s with IDs %s found.",
109+
mainDao.getElementClass().getName(),
110+
ids.stream().sorted().map( String::valueOf ).collect( Collectors.joining( ", " ) ) ) );
111+
}
112+
return result;
113+
}
114+
92115
@Override
93116
@Transactional(readOnly = true)
94117
public O load( Long id ) {

gemma-core/src/main/java/ubic/gemma/persistence/service/BaseReadOnlyService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ public interface BaseReadOnlyService<O extends Identifiable> {
4646
*/
4747
Collection<O> load( Collection<Long> ids );
4848

49+
/**
50+
* Load multiple objects or fail with a {@link NullPointerException} if any of the objects does not exist in the
51+
* persistent storage.
52+
*/
53+
Collection<O> loadOrFail( Collection<Long> ids ) throws NullPointerException;
54+
55+
<T extends Exception> Collection<O> loadOrFail( Collection<Long> ids, Function<String, T> exceptionSupplier ) throws T;
56+
4957
/**
5058
* Loads object with given ID.
5159
*

gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/BioAssaySetServiceImpl.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
import javax.annotation.Nullable;
1212
import java.util.ArrayList;
1313
import java.util.Collection;
14+
import java.util.HashSet;
1415
import java.util.function.Function;
1516
import java.util.function.Supplier;
17+
import java.util.stream.Collectors;
1618
import java.util.stream.Stream;
1719

1820
@Service
@@ -56,15 +58,40 @@ public BioAssaySet findOrFail( BioAssaySet entity ) {
5658
}
5759

5860
@Override
61+
@Transactional(readOnly = true)
5962
public Collection<BioAssaySet> load( Collection<Long> ids ) {
6063
Collection<BioAssaySet> result = new ArrayList<>();
6164
result.addAll( expressionExperimentService.load( ids ) );
6265
result.addAll( expressionExperimentSubSetService.load( ids ) );
6366
return result;
6467
}
6568

69+
@Override
70+
@Transactional(readOnly = true)
71+
public Collection<BioAssaySet> loadOrFail( Collection<Long> ids ) throws NullPointerException {
72+
return loadOrFail( ids, NullPointerException::new );
73+
}
74+
75+
@Override
76+
@Transactional(readOnly = true)
77+
public <T extends Exception> Collection<BioAssaySet> loadOrFail( Collection<Long> ids, Function<String, T> exceptionSupplier ) throws T {
78+
ids = new HashSet<>( ids );
79+
Collection<BioAssaySet> result = new ArrayList<>();
80+
result.addAll( expressionExperimentService.load( ids ) );
81+
result.addAll( expressionExperimentSubSetService.load( ids ) );
82+
if ( result.size() < ids.size() ) {
83+
for ( BioAssaySet o : result ) {
84+
ids.remove( o.getId() );
85+
}
86+
throw exceptionSupplier.apply( String.format( "No BioAssaySet with IDs %s found.",
87+
ids.stream().sorted().map( String::valueOf ).collect( Collectors.joining( ", " ) ) ) );
88+
}
89+
return result;
90+
}
91+
6692
@Nullable
6793
@Override
94+
@Transactional(readOnly = true)
6895
public BioAssaySet load( Long id ) {
6996
BioAssaySet bas;
7097
bas = expressionExperimentService.load( id );
@@ -76,6 +103,7 @@ public BioAssaySet load( Long id ) {
76103

77104
@Nonnull
78105
@Override
106+
@Transactional(readOnly = true)
79107
public BioAssaySet loadOrFail( Long id ) throws NullPointerException {
80108
BioAssaySet bas;
81109
bas = expressionExperimentService.load( id );
@@ -87,6 +115,7 @@ public BioAssaySet loadOrFail( Long id ) throws NullPointerException {
87115

88116
@Nonnull
89117
@Override
118+
@Transactional(readOnly = true)
90119
public <T extends Exception> BioAssaySet loadOrFail( Long id, Supplier<T> exceptionSupplier ) throws T {
91120
BioAssaySet bas;
92121
bas = expressionExperimentService.load( id );
@@ -98,6 +127,7 @@ public <T extends Exception> BioAssaySet loadOrFail( Long id, Supplier<T> except
98127

99128
@Nonnull
100129
@Override
130+
@Transactional(readOnly = true)
101131
public <T extends Exception> BioAssaySet loadOrFail( Long id, Function<String, T> exceptionSupplier ) throws T {
102132
BioAssaySet bas;
103133
bas = expressionExperimentService.load( id );
@@ -109,6 +139,7 @@ public <T extends Exception> BioAssaySet loadOrFail( Long id, Function<String, T
109139

110140
@Nonnull
111141
@Override
142+
@Transactional(readOnly = true)
112143
public <T extends Exception> BioAssaySet loadOrFail( Long id, Function<String, T> exceptionSupplier, String message ) throws T {
113144
BioAssaySet bas;
114145
bas = expressionExperimentService.load( id );
@@ -134,11 +165,13 @@ public long countAll() {
134165
}
135166

136167
@Override
168+
@Transactional(readOnly = true)
137169
public Stream<BioAssaySet> streamAll() {
138170
return Stream.concat( expressionExperimentService.streamAll(), expressionExperimentSubSetService.streamAll() );
139171
}
140172

141173
@Override
174+
@Transactional(readOnly = true)
142175
public Stream<BioAssaySet> streamAll( boolean createNewSession ) {
143176
return Stream.concat( expressionExperimentService.streamAll( createNewSession ), expressionExperimentSubSetService.streamAll( createNewSession ) );
144177
}

0 commit comments

Comments
 (0)