-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d0462fc
commit cafee0a
Showing
4 changed files
with
461 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
vcell-rest/src/main/java/org/vcell/restq/handlers/SpatialResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package org.vcell.restq.handlers; | ||
|
||
import cbit.util.xml.VCLoggerException; | ||
import cbit.vcell.biomodel.BioModel; | ||
import cbit.vcell.mapping.MappingException; | ||
import cbit.vcell.mapping.SimulationContext; | ||
import cbit.vcell.parser.ExpressionException; | ||
import cbit.vcell.solver.Simulation; | ||
import cbit.vcell.solver.SolverException; | ||
import cbit.vcell.solver.TimeBounds; | ||
import cbit.vcell.solver.UniformOutputTimeSpec; | ||
import jakarta.enterprise.context.RequestScoped; | ||
import jakarta.ws.rs.*; | ||
import jakarta.ws.rs.core.HttpHeaders; | ||
import jakarta.ws.rs.core.MediaType; | ||
import net.lingala.zip4j.ZipFile; | ||
import org.eclipse.microprofile.openapi.annotations.Operation; | ||
import org.jboss.resteasy.reactive.PartType; | ||
import org.jboss.resteasy.reactive.RestForm; | ||
import org.vcell.sbml.SBMLFakeSpatialBioModel; | ||
import org.vcell.sbml.vcell.SBMLExporter; | ||
import org.vcell.sbml.vcell.SBMLImporter; | ||
import org.w3c.www.http.HTTP; | ||
|
||
import java.beans.PropertyVetoException; | ||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.file.Files; | ||
|
||
@Path("/api/v1/spatial") | ||
@RequestScoped | ||
public class SpatialResource { | ||
public SpatialResource() { } | ||
|
||
@GET | ||
@Path("/retrieveFiniteVolumeInputFromSpatialModel") | ||
@Operation(operationId = "retrieveFiniteVolumeInputFromSpatialModel", summary = "Retrieve finite volume input from spatial model") | ||
@Consumes(MediaType.MULTIPART_FORM_DATA) | ||
@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||
public File retrieveFiniteVolumeInputFromSpatialModel(@RestForm File sbmlFile) { | ||
try { | ||
File workingDir = Files.createTempDirectory("vcell-").toFile(); | ||
File zipFile = Files.createTempFile("finite-volume", ".zip").toFile(); | ||
sbmlToFiniteVolumeInput(sbmlFile, workingDir); | ||
ZipFile zip = new ZipFile(zipFile); | ||
|
||
zip.addFolder(workingDir); | ||
zip.close(); | ||
|
||
return zipFile; | ||
}catch (Exception e){ | ||
throw new WebApplicationException("Error processing spatial model", HTTP.INTERNAL_SERVER_ERROR); | ||
} | ||
} | ||
|
||
public record FiniteVolumeInput( | ||
@RestForm @PartType(MediaType.APPLICATION_OCTET_STREAM) | ||
File zipFile | ||
) { } | ||
|
||
|
||
|
||
public static void sbmlToFiniteVolumeInput(File sbmlFile, File outputDir) throws IOException, MappingException, VCLoggerException, PropertyVetoException, SolverException, ExpressionException { | ||
SBMLExporter.MemoryVCLogger vcl = new SBMLExporter.MemoryVCLogger(); | ||
boolean bValidateSBML = true; | ||
InputStream is = new FileInputStream(sbmlFile); | ||
SBMLImporter importer = new SBMLImporter(is, vcl, bValidateSBML); | ||
BioModel bioModel = importer.getBioModel(); | ||
bioModel.updateAll(false); | ||
|
||
final double duration = 5.0; // endpoint arg | ||
final double time_step = 0.1; // endpoint arg | ||
//final ISize meshSize = new ISize(10, 10, 10); // future endpoint arg | ||
SimulationContext simContext = bioModel.getSimulationContext(0); | ||
Simulation sim = new Simulation(simContext.getMathDescription(), simContext); | ||
sim.getSolverTaskDescription().setTimeBounds(new TimeBounds(0.0, duration)); | ||
sim.getSolverTaskDescription().setOutputTimeSpec(new UniformOutputTimeSpec(time_step)); | ||
|
||
SBMLFakeSpatialBioModel.writeInputFilesOnly(outputDir, sim); | ||
} | ||
|
||
} |
133 changes: 133 additions & 0 deletions
133
vcell-rest/src/test/java/org/vcell/restq/apiclient/SpacialResourceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package org.vcell.restq.apiclient; | ||
|
||
import cbit.util.xml.VCLoggerException; | ||
import cbit.vcell.mapping.MappingException; | ||
import cbit.vcell.parser.ExpressionException; | ||
import cbit.vcell.resource.PropertyLoader; | ||
import cbit.vcell.solver.AnnotatedFunction; | ||
import cbit.vcell.solver.SolverException; | ||
import cbit.vcell.solvers.FunctionFileGenerator; | ||
import io.quarkus.test.junit.QuarkusTest; | ||
import io.quarkus.test.keycloak.client.KeycloakTestClient; | ||
import jakarta.inject.Inject; | ||
import net.lingala.zip4j.ZipFile; | ||
import org.apache.commons.io.FileUtils; | ||
import org.eclipse.microprofile.config.inject.ConfigProperty; | ||
import org.jose4j.lang.JoseException; | ||
import org.junit.jupiter.api.*; | ||
import org.testcontainers.shaded.com.google.common.io.Files; | ||
import org.vcell.restclient.ApiClient; | ||
import org.vcell.restclient.ApiException; | ||
import org.vcell.restclient.api.SpatialResourceApi; | ||
import org.vcell.restq.TestEndpointUtils; | ||
import org.vcell.restq.config.CDIVCellConfigProvider; | ||
import org.vcell.restq.db.AgroalConnectionFactory; | ||
import org.vcell.restq.handlers.SpatialResource; | ||
import org.vcell.util.DataAccessException; | ||
|
||
import java.beans.PropertyVetoException; | ||
import java.io.File; | ||
import java.io.FileReader; | ||
import java.io.IOException; | ||
import java.sql.SQLException; | ||
import java.util.Arrays; | ||
import java.util.Scanner; | ||
import java.util.Vector; | ||
|
||
@QuarkusTest | ||
public class SpacialResourceTest { | ||
@ConfigProperty(name = "quarkus.http.test-port") | ||
Integer testPort; | ||
|
||
@Inject | ||
AgroalConnectionFactory agroalConnectionFactory; | ||
|
||
KeycloakTestClient keycloakClient = new KeycloakTestClient(); | ||
|
||
private ApiClient aliceAPIClient; | ||
private static String previousServerID; | ||
private static String previousMongoHost; | ||
private static String previousMongoPort; | ||
private static String previousMongoDB; | ||
|
||
@BeforeAll | ||
public static void setupConfig(){ | ||
PropertyLoader.setConfigProvider(new CDIVCellConfigProvider()); | ||
previousServerID = PropertyLoader.getProperty(PropertyLoader.vcellServerIDProperty, null); | ||
PropertyLoader.setProperty(PropertyLoader.vcellServerIDProperty, "TEST2"); | ||
|
||
previousMongoDB = PropertyLoader.getProperty(PropertyLoader.mongodbDatabase, null); | ||
PropertyLoader.setProperty(PropertyLoader.mongodbDatabase, "test"); | ||
|
||
previousMongoHost = PropertyLoader.getProperty(PropertyLoader.mongodbHostInternal, null); | ||
PropertyLoader.setProperty(PropertyLoader.mongodbHostInternal, "localhost"); | ||
|
||
previousMongoPort = PropertyLoader.getProperty(PropertyLoader.mongodbPortInternal, null); | ||
PropertyLoader.setProperty(PropertyLoader.mongodbPortInternal, "9080"); | ||
} | ||
|
||
@AfterAll | ||
public static void resetConfig(){ | ||
if (previousServerID != null) {PropertyLoader.setProperty(PropertyLoader.vcellServerIDProperty, previousServerID);}; | ||
if (previousMongoHost != null) {PropertyLoader.setProperty(PropertyLoader.mongodbHostInternal, previousMongoHost);} | ||
if (previousMongoDB != null) {PropertyLoader.setProperty(PropertyLoader.mongodbDatabase, previousMongoDB);} | ||
if (previousMongoPort != null) {PropertyLoader.setProperty(PropertyLoader.mongodbPortInternal, previousMongoPort);} | ||
} | ||
|
||
@BeforeEach | ||
public void createClients() throws JoseException { | ||
aliceAPIClient = TestEndpointUtils.createAuthenticatedAPIClient(keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.alice); | ||
} | ||
|
||
@AfterEach | ||
public void removeOIDCMappings() throws SQLException, DataAccessException { | ||
TestEndpointUtils.removeAllMappings(agroalConnectionFactory); | ||
} | ||
|
||
// Ensure the round trip from request to resulting Zip is equivalent to a local run of input file generation | ||
@Test | ||
public void testSpacialSBMLResults() throws ApiException, IOException, VCLoggerException, SolverException, ExpressionException, PropertyVetoException, MappingException { | ||
SpatialResourceApi spatialResourceApi = new SpatialResourceApi(aliceAPIClient); | ||
File sbmlFile = TestEndpointUtils.getResourceFile("/TinySpacialProject_Application0.xml"); | ||
|
||
File zip = spatialResourceApi.retrieveFiniteVolumeInputFromSpatialModel(sbmlFile); | ||
File unzipDir = Files.createTempDir(); | ||
File outputDir = Files.createTempDir(); | ||
|
||
SpatialResource.sbmlToFiniteVolumeInput(sbmlFile, outputDir); | ||
|
||
ZipFile zipFile = new ZipFile(zip); | ||
zipFile.extractAll(unzipDir.getAbsolutePath()); | ||
zipFile.close(); | ||
|
||
unzipDir = unzipDir.listFiles()[0]; | ||
|
||
for (int i = 0; i < outputDir.listFiles().length; i++) { | ||
File output = outputDir.listFiles()[i]; | ||
File unzip = Arrays.stream(unzipDir.listFiles()).filter( | ||
f -> f.getName().split("\\.")[1].equals(output.getName().split("\\.")[1]) | ||
).findFirst().orElse(null); | ||
if (output.getName().split("\\.")[1].equals("functions")){ | ||
Vector<AnnotatedFunction> outPutAnnotated = FunctionFileGenerator.readFunctionsFile(output, "0"); | ||
Vector<AnnotatedFunction> unzipAnnotated = FunctionFileGenerator.readFunctionsFile(unzip, "0"); | ||
for (int j = 0; j < outPutAnnotated.size(); j++) { | ||
Assertions.assertTrue(outPutAnnotated.get(j).compareEqual(unzipAnnotated.get(j))); | ||
} | ||
} else if (output.getName().split("\\.")[1].equals("fvinput")) { | ||
Scanner outputReader = new Scanner(output); | ||
Scanner unzipReader = new Scanner(unzip); | ||
|
||
while (outputReader.hasNextLine()){ | ||
String outputLine = outputReader.nextLine(); | ||
String unzipLine = unzipReader.nextLine(); | ||
// Don't compare the file path | ||
if (!outputLine.contains("FILE")){ | ||
Assertions.assertEquals(outputLine, unzipLine); | ||
} | ||
} | ||
} else{ | ||
Assertions.assertTrue(FileUtils.contentEquals(output, unzip)); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.