Skip to content

Commit

Permalink
issue #121 #8 - more elaborate unit tests for unit polishing
Browse files Browse the repository at this point in the history
  • Loading branch information
Schmoho committed Jun 11, 2024
1 parent 7e30b2b commit 043fbdb
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 118 deletions.
199 changes: 126 additions & 73 deletions src/main/java/edu/ucsd/sbrg/bigg/polishing/UnitPolishing.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ public class UnitPolishing {
public static final CVTerm CV_TERM_DESCRIBED_BY_PUBMED_GROWTH_UNIT = new CVTerm(CVTerm.Qualifier.BQB_IS_DESCRIBED_BY, Registry.createURI("pubmed", 7986045));
public static final String GROWTH_UNIT_ID = "mmol_per_gDW_per_hr";
public static final String GROWTH_UNIT_NAME = "Millimoles per gram (dry weight) per hour";
public static final CVTerm CV_TERM_IS_UO_MOLE = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000040"));
public static final CVTerm CV_TERM_IS_UO_SECOND = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000032"));
public static final CVTerm CV_TERM_IS_VERSION_OF_UO_SECOND = new CVTerm(CVTerm.Qualifier.BQB_IS_VERSION_OF, Registry.createURI("unit", "UO:0000032"));
public static final CVTerm CV_TERM_IS_SUBSTANCE_UNIT = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000006"));
public static final CVTerm CV_TERM_IS_TIME_UNIT = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000003"));
public static final CVTerm CV_TERM_IS_VOLUME_UNIT = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000095"));
public static final CVTerm CV_TERM_IS_UO_SECOND = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000010"));
public static final CVTerm CV_TERM_IS_UO_HOUR = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000032"));
public static final CVTerm CV_TERM_IS_UO_MMOL = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000040"));
public static final CVTerm CV_TERM_IS_UO_GRAM = new CVTerm(CVTerm.Qualifier.BQB_IS, Registry.createURI("unit", "UO:0000021"));
public static final CVTerm CV_TERM_IS_VERSION_OF_UO_SECOND = new CVTerm(CVTerm.Qualifier.BQB_IS_VERSION_OF, Registry.createURI("unit", "UO:0000010"));
public static final CVTerm CV_TERM_IS_VERSION_OF_UO_MOLE = new CVTerm(CVTerm.Qualifier.BQB_IS_VERSION_OF, Registry.createURI("unit", "UO:0000013"));

AbstractProgressBar progress;
Model model;
Expand All @@ -38,108 +44,155 @@ public void polishListOfUnitDefinitions() {
progress.DisplayBar("Polishing Unit Definitions (2/9) "); // "Processing unit definitions");
int udCount = model.getUnitDefinitionCount();
var unitDefinitions = model.getListOfUnitDefinitions();

var growth = createGrowthUnitDefinition();
annotateGrowthUnitDefinition(growth);

setModelUnits(unitDefinitions);
setSubstanceUnit(unitDefinitions, growth);
setTimeUnit(growth);
setModelUnits(growth, unitDefinitions);

UnitDefinition substanceUnits = model.getSubstanceUnitsInstance();
if (!model.isSetExtentUnits()) {
if (!model.isSetExtentUnits())
model.setExtentUnits(substanceUnits.getId());
}
if (!model.isSetSubstanceUnits()) {

if (!model.isSetSubstanceUnits())
model.setSubstanceUnits(substanceUnits.getId());
}

while (progress.getCallNumber() < udCount) {
progress.DisplayBar("Polishing Unit Definitions (2/9) ");
}
}

/**
* Adds basic unit definitions to model, if not present
*
* @return Millimoles per gram (dry weight) per hour {@link UnitDefinition}
* Using a growth unit as the template for equivalence, find a potentially already existing
* growth unit.
*/
private Optional<UnitDefinition> findGrowthUnit(ListOf<UnitDefinition> uds, UnitDefinition growth) {
return uds.stream().filter(u -> UnitDefinition.areEquivalent(u, growth)).findFirst();
}

/**
* This unit will be created if no other growth unit can be extracted from the model.
*/
private UnitDefinition defaultGrowthUnitDefinition() {
var growth = new UnitDefinition(model.getLevel(), model.getVersion());
growth.setId(GROWTH_UNIT_ID);
growth.setName(GROWTH_UNIT_NAME);
ModelBuilder.buildUnit(growth, 1d, -3, Unit.Kind.MOLE, 1d);
ModelBuilder.buildUnit(growth, 1d, 0, Unit.Kind.GRAM, -1d);
ModelBuilder.buildUnit(growth, 3600d, 0, Unit.Kind.SECOND, -1d);
return growth;
}

private UnitDefinition createGrowthUnitDefinition() {
var growth = model.getUnitDefinition(GROWTH_UNIT_ID);
if (growth == null) {
growth = model.createUnitDefinition(GROWTH_UNIT_ID);
logger.finest(MESSAGES.getString("ADDED_UNIT_DEF"));
}
if (growth.getUnitCount() < 1) {
ModelBuilder.buildUnit(growth, 1d, -3, Unit.Kind.MOLE, 1d);
ModelBuilder.buildUnit(growth, 1d, 0, Unit.Kind.GRAM, -1d);
ModelBuilder.buildUnit(growth, 3600d, 0, Unit.Kind.SECOND, -1d);
}
if (!growth.isSetName()) {
growth.setName(GROWTH_UNIT_NAME);
}
if (!growth.isSetMetaId()) {
var growth = defaultGrowthUnitDefinition();
var otherGrowth = findGrowthUnit(model.getListOfUnitDefinitions(), growth).orElse(growth);
if (!growth.isSetMetaId())
growth.setMetaId(growth.getId());
annotateGrowthUnitDefinition(growth);
if (otherGrowth.equals(growth) && null != model.getUnitDefinition(GROWTH_UNIT_ID)) {
model.getUnitDefinition(GROWTH_UNIT_ID).setId(GROWTH_UNIT_ID + "__preexisting");
}
model.addUnitDefinition(growth);
return growth;
}

private CVTerm genericUnitAnnotation(Unit u) {
return new CVTerm(CVTerm.Qualifier.BQB_IS_VERSION_OF,
u.getKind().getUnitOntologyIdentifier());
}

private void annotateGrowthUnitDefinition(UnitDefinition growth) {
growth.addCVTerm(CV_TERM_DESCRIBED_BY_PUBMED_GROWTH_UNIT);
getUnitByKind(growth, Unit.Kind.MOLE)
.filter(unit -> unit.getScale() == -3)
.ifPresent(unit -> unit.addCVTerm(CV_TERM_IS_UO_MOLE));
getUnitByKind(growth, Unit.Kind.GRAM)
.ifPresent(unit -> unit.addCVTerm(new CVTerm(
CVTerm.Qualifier.BQB_IS_VERSION_OF,
unit.getKind().getUnitOntologyIdentifier())));
getUnitByKind(growth, Unit.Kind.MOLE).ifPresent(
u -> {
switch (u.getScale()) {
case -3: u.addCVTerm(CV_TERM_IS_UO_MMOL); break;
default:
u.addCVTerm(this.genericUnitAnnotation(u));
}
}
);
getUnitByKind(growth, Unit.Kind.GRAM).ifPresent(this::genericUnitAnnotation);
getUnitByKind(growth, Unit.Kind.SECOND).ifPresent(
u -> {
switch (Double.valueOf(u.getMultiplier()).intValue()) {
case 1: u.addCVTerm(CV_TERM_IS_UO_SECOND); break;
case 3600: u.addCVTerm(CV_TERM_IS_UO_HOUR); break;
default:
u.addCVTerm(this.genericUnitAnnotation(u));
}
});
}


/**
* Sets substance, volume and time units for model from the models unit definitions, if not set
* Sets substance, volume and time units for model from the models unit definitions,
* or the growth unit,
* if not set.
*/
private void setModelUnits(ListOf<UnitDefinition> unitDefinitions) {
private void setModelUnits(UnitDefinition growth, ListOf<UnitDefinition> unitDefinitions) {
var substanceUnits = model.getSubstanceUnitsInstance();
if (substanceUnits == null && unitDefinitions.get(UnitDefinition.SUBSTANCE) != null) {
model.setSubstanceUnits(UnitDefinition.SUBSTANCE);
}
if (substanceUnits == null)
if (unitDefinitions.get(UnitDefinition.SUBSTANCE) != null)
model.setSubstanceUnits(UnitDefinition.SUBSTANCE);
else
model.setSubstanceUnits(createSubstanceUnit(growth));
model.getSubstanceUnitsInstance().addCVTerm(CV_TERM_IS_SUBSTANCE_UNIT);
var timeUnits = model.getTimeUnitsInstance();
if (timeUnits == null)
if (unitDefinitions.get(UnitDefinition.TIME) != null)
model.setTimeUnits(UnitDefinition.TIME);
else
model.setTimeUnits(createTimeUnit(growth));
model.getTimeUnitsInstance().addCVTerm(CV_TERM_IS_TIME_UNIT);
var volumeUnits = model.getVolumeUnitsInstance();
if (volumeUnits == null && unitDefinitions.get(UnitDefinition.VOLUME) != null) {
if (volumeUnits == null && unitDefinitions.get(UnitDefinition.VOLUME) != null)
model.setVolumeUnits(UnitDefinition.VOLUME);
}
var timeUnits = model.getTimeUnitsInstance();
if (timeUnits == null && unitDefinitions.get(UnitDefinition.TIME) != null) {
model.setTimeUnits(UnitDefinition.TIME);
}
if (null != volumeUnits)
model.getVolumeUnitsInstance().addCVTerm(CV_TERM_IS_VOLUME_UNIT);
}

private void setSubstanceUnit(ListOf<UnitDefinition> unitDefinitions, UnitDefinition growth) {
if (null == model.getSubstanceUnitsInstance()) {
if (unitDefinitions.get(UnitDefinition.SUBSTANCE) != null) {
model.setSubstanceUnits(UnitDefinition.SUBSTANCE);
} else {
final var substanceUnits = model.createUnitDefinition(UnitDefinition.SUBSTANCE);
substanceUnits.setName("Millimoles per gram (dry weight)");
getUnitByKind(growth, Unit.Kind.GRAM).ifPresent(unit -> substanceUnits.addUnit(safeClone(unit)));
getUnitByKind(growth, Unit.Kind.MOLE).ifPresent(unit -> substanceUnits.addUnit(safeClone(unit)));
model.setSubstanceUnits(substanceUnits);
}
}
private UnitDefinition createSubstanceUnit(UnitDefinition growth) {
final var substanceUnits = model.createUnitDefinition(UnitDefinition.SUBSTANCE);
getUnitByKind(growth, Unit.Kind.GRAM).ifPresentOrElse(
unit -> substanceUnits.addUnit(safeClone(unit)),
() -> {
var u = substanceUnits.createUnit(Unit.Kind.GRAM);
u.setMultiplier(1);
u.setExponent(-1d);
u.setScale(0);
u.addCVTerm(CV_TERM_IS_UO_GRAM);
});
getUnitByKind(growth, Unit.Kind.MOLE).ifPresentOrElse(
unit -> substanceUnits.addUnit(safeClone(unit)),
() -> {
var u = substanceUnits.createUnit(Unit.Kind.MOLE);
u.setMultiplier(1);
u.setExponent(1d);
u.setScale(-3);
u.addCVTerm(CV_TERM_IS_UO_MMOL);
u.addCVTerm(CV_TERM_IS_VERSION_OF_UO_MOLE);
});
return substanceUnits;
}

private void setTimeUnit(UnitDefinition growth) {
if (null == model.getTimeUnitsInstance() ) {
getUnitByKind(growth, Unit.Kind.SECOND)
.ifPresent(unit -> {
var timeUnitDefinition = model.createUnitDefinition(UnitDefinition.TIME);
timeUnitDefinition.setName("Hour");
model.setTimeUnits(timeUnitDefinition.getId());
var timeUnit = safeClone(unit);
timeUnit.setExponent(1d);
timeUnitDefinition.addUnit(timeUnit);
timeUnit.addCVTerm(CV_TERM_IS_UO_SECOND);
timeUnit.addCVTerm(CV_TERM_IS_VERSION_OF_UO_SECOND);
});
}
private UnitDefinition createTimeUnit(UnitDefinition growth) {
final var timeUnitDefinition = model.createUnitDefinition(UnitDefinition.TIME);
getUnitByKind(growth, Unit.Kind.SECOND).ifPresentOrElse(
unit -> {
var timeUnit = safeClone(unit);
if(timeUnit.getExponent() < 0)
timeUnit.setExponent(timeUnit.getExponent() * -1);
timeUnitDefinition.addUnit(timeUnit);
},
() -> {
var timeUnit = timeUnitDefinition.createUnit(Unit.Kind.SECOND);
timeUnit.setMultiplier(3600);
timeUnit.setScale(0);
timeUnit.setExponent(1d);
timeUnit.addCVTerm(CV_TERM_IS_UO_HOUR);
timeUnit.addCVTerm(CV_TERM_IS_VERSION_OF_UO_SECOND);
timeUnitDefinition.setName("Hour");
});
return timeUnitDefinition;
}

private Optional<Unit> getUnitByKind(UnitDefinition ud, Unit.Kind kind) {
Expand Down
14 changes: 8 additions & 6 deletions src/test/java/edu/ucsd/sbrg/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import edu.ucsd.sbrg.bigg.ModelPolisherOptions;
import edu.ucsd.sbrg.bigg.Parameters;
import org.sbml.jsbml.AbstractNamedSBase;
import org.sbml.jsbml.AbstractSBase;
import org.sbml.jsbml.CVTerm;

import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -87,11 +88,11 @@ public static void assertCVTermIsPresent(AbstractNamedSBase entity,
assertTrue(false, message);
}

public static void assertCVTermsArePresent(AbstractNamedSBase entity,
CVTerm.Type t,
CVTerm.Qualifier q,
Collection<String> uris,
String message) {
public static void assertCVTermsArePresent(AbstractSBase entity,
CVTerm.Type t,
CVTerm.Qualifier q,
Collection<String> uris,
String message) {
var cvTerms = entity.getCVTerms();
for(var term : cvTerms) {
// this is just an awkward way to implement set difference, sorry bout that
Expand All @@ -109,7 +110,8 @@ public static void assertCVTermsArePresent(AbstractNamedSBase entity,
return;
}
}
assertTrue(false, message);
assertTrue(false, message
+ "Instead: " + entity.getCVTerms().toString());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import static edu.ucsd.sbrg.TestUtils.initParameters;
import static org.junit.jupiter.api.Assertions.*;

public class BiGGAnnotationTest extends BiGGDBTest {
public class BiGGAnnotationTest extends BiGGDBContainerTest {

@Test
public void annotatePublication() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.time.Duration;

@Testcontainers
public abstract class BiGGDBTest {
public abstract class BiGGDBContainerTest {

static final GenericContainer bigg = new GenericContainer(DockerImageName.parse("preloaded_bigg:latest"))
.withExposedPorts(5432)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import static edu.ucsd.sbrg.TestUtils.assertCVTermIsPresent;
import static org.junit.jupiter.api.Assertions.*;

public class CompartmentAnnotationTest extends BiGGDBTest {
public class CompartmentAnnotationTest extends BiGGDBContainerTest {


@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import static edu.ucsd.sbrg.TestUtils.initParameters;
import static org.junit.jupiter.api.Assertions.*;

public class ModelAnnotationTest extends BiGGDBTest {
public class ModelAnnotationTest extends BiGGDBContainerTest {

@Test
public void basicModelAnnotation() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import static edu.ucsd.sbrg.TestUtils.initParameters;
import static org.junit.jupiter.api.Assertions.*;

public class ReactionAnnotationTest extends BiGGDBTest {
public class ReactionAnnotationTest extends BiGGDBContainerTest {

@Test
public void getBiGGIdFromResourcesTest() {
Expand Down Expand Up @@ -50,7 +50,7 @@ public void getBiGGIdFromResourcesTest() {
var gPlugin = (GroupsModelPlugin) m.getPlugin(GroupsConstants.shortLabel);
assertEquals(0, gPlugin.getGroupCount());

new ReactionAnnotation(r1).annotate();
new ReactionAnnotation(r1).annotate();
new ReactionAnnotation(r2).annotate();
new ReactionAnnotation(r3).annotate();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import static edu.ucsd.sbrg.TestUtils.*;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class SpeciesAnnotationTest extends BiGGDBTest {
public class SpeciesAnnotationTest extends BiGGDBContainerTest {

@BeforeEach
public void init() {
Expand Down
Loading

0 comments on commit 043fbdb

Please sign in to comment.