diff --git a/.github/workflows/CI-full.yml b/.github/workflows/CI-full.yml index 8402ac1df1..310f1a3573 100644 --- a/.github/workflows/CI-full.yml +++ b/.github/workflows/CI-full.yml @@ -6,19 +6,36 @@ on: tag: description: "Repository tag (e.g., 7.7.0.37)" required: true -# client_only: -# description: "Build only client images (true/false)" -# required: false -# default: "false" release: types: [published] - + env: python-version: "3.10" - + jobs: - build: + setup: + runs-on: ubuntu-22.04 + outputs: + vcell_tag: ${{ steps.set-vars.outputs.vcell_tag }} + vcell_repo_namespace: ${{ steps.set-vars.outputs.vcell_repo_namespace }} + friendly_tag: ${{ steps.set-vars.outputs.friendly_tag }} + steps: + - uses: actions/checkout@v4 + + - name: set global environment variables + id: set-vars + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "friendly_tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT + else + echo "friendly_tag=${GITHUB_REF:10}" >> $GITHUB_OUTPUT + fi + echo "vcell_tag=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + echo "vcell_repo_namespace=ghcr.io/virtualcell" >> $GITHUB_OUTPUT + + maven-build: runs-on: ubuntu-22.04 + needs: setup steps: - name: Free up VM's disk space run: | @@ -30,37 +47,12 @@ jobs: - uses: actions/checkout@v4 - - name: set global environment variables - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "FRIENDLY_TAG=${{ github.event.inputs.tag }}" >> $GITHUB_ENV - else - echo "FRIENDLY_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV - fi - echo "VCELL_TAG=`git rev-parse --short HEAD`" >> $GITHUB_ENV - echo "VCELL_REPO_NAMESPACE=ghcr.io/virtualcell" >> $GITHUB_ENV - echo "VCELL_DEPLOY_REMOTE_DIR=/share/apps/vcell3/deployed_github" >> $GITHUB_ENV - echo "VCELL_MANAGER_NODE=vcellapi.cam.uchc.edu" >> $GITHUB_ENV - - name: setup ssh-agent - uses: webfactory/ssh-agent@v0.8.0 - with: - ssh-private-key: ${{ secrets.VC_KEY }} - - name: get installer secrets - run: | - ssh-keyscan ${VCELL_MANAGER_NODE} >> ~/.ssh/known_hosts - sudo mkdir /usr/local/deploy - sudo chmod 777 /usr/local/deploy - cd /usr/local/deploy - scp ${{ secrets.CD_FULL_USER }}@${VCELL_MANAGER_NODE}:${VCELL_DEPLOY_REMOTE_DIR}/deploy_dir_2025_03_18.tar . - cd .. - sudo tar -xvf deploy/deploy_dir_2025_03_18.tar - sudo chmod 777 -R deploy - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.python-version }} cache: "pip" - + - name: Install Dependencies run: pip install -r requirements.txt @@ -81,42 +73,209 @@ jobs: java-version: '17' cache: 'maven' - - name: build and publish all images - shell: bash + - name: Maven build + run: mvn --batch-mode clean install dependency:copy-dependencies -DskipTests=true + + - name: Upload Maven artifacts + uses: actions/upload-artifact@v4 + with: + name: maven-build-output + retention-days: 1 + path: | + **/target/ + localsolvers/ + + + docker-build: + runs-on: ubuntu-22.04 + needs: [setup, maven-build] + strategy: + fail-fast: false + matrix: + image: + - name: api + dockerfile: docker/build/Dockerfile-api-dev + context: . + needs_maven: true + needs_secrets: false + - name: rest + dockerfile: vcell-rest/src/main/docker/Dockerfile.jvm + context: vcell-rest + needs_maven: true + needs_secrets: false + pre_build: "mvn --batch-mode clean install dependency:copy-dependencies -DskipTests -Dvcell.exporter=false" + - name: exporter + dockerfile: vcell-rest/src/main/docker/Dockerfile.jvm + context: vcell-rest + needs_maven: true + needs_secrets: false + pre_build: "mvn --batch-mode clean install dependency:copy-dependencies -DskipTests -Dvcell.exporter=true" + - name: webapp-dev + dockerfile: webapp-ng/Dockerfile-webapp + context: webapp-ng + needs_maven: false + needs_secrets: false + build_args: "BUILD_COMMAND=build_dev" + - name: webapp-stage + dockerfile: webapp-ng/Dockerfile-webapp + context: webapp-ng + needs_maven: false + needs_secrets: false + build_args: "BUILD_COMMAND=build_stage" + - name: webapp-prod + dockerfile: webapp-ng/Dockerfile-webapp + context: webapp-ng + needs_maven: false + needs_secrets: false + build_args: "BUILD_COMMAND=build_prod" + - name: webapp-island + dockerfile: webapp-ng/Dockerfile-webapp + context: webapp-ng + needs_maven: false + needs_secrets: false + build_args: "BUILD_COMMAND=build_island" + - name: webapp-remote + dockerfile: webapp-ng/Dockerfile-webapp + context: webapp-ng + needs_maven: false + needs_secrets: false + build_args: "BUILD_COMMAND=build_remote" + - name: db + dockerfile: docker/build/Dockerfile-db-dev + context: . + needs_maven: true + needs_secrets: false + - name: sched + dockerfile: docker/build/Dockerfile-sched-dev + context: . + needs_maven: true + needs_secrets: false + - name: submit + dockerfile: docker/build/Dockerfile-submit-dev + context: . + needs_maven: true + needs_secrets: false + - name: data + dockerfile: docker/build/Dockerfile-data-dev + context: . + needs_maven: true + needs_secrets: false + - name: mongo + dockerfile: docker/build/mongo/Dockerfile + context: docker/build/mongo + needs_maven: false + needs_secrets: false + - name: batch + dockerfile: docker/build/Dockerfile-batch-dev + context: . + needs_maven: true + needs_secrets: false + - name: opt + dockerfile: pythonCopasiOpt/Dockerfile + context: pythonCopasiOpt + needs_maven: false + needs_secrets: false + - name: clientgen + dockerfile: docker/build/Dockerfile-clientgen-dev + context: . + needs_maven: true + needs_secrets: false + needs_installer_secrets: true + - name: admin + dockerfile: docker/build/Dockerfile-admin-dev + context: . + needs_maven: true + needs_secrets: false + steps: + - name: Free up VM's disk space + run: | + sudo rm -rf /usr/local/lib/android + sudo rm -rf /usr/local/.ghcup + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/share/swift + sudo apt-get clean + + - uses: actions/checkout@v4 + + - name: setup java 17 with maven cache + if: ${{ matrix.image.pre_build }} + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + cache: 'maven' + + - name: Download Maven artifacts + if: ${{ matrix.image.needs_maven }} + uses: actions/download-artifact@v4 + with: + name: maven-build-output + path: . + + - name: setup ssh-agent for installer secrets + if: ${{ matrix.image.needs_installer_secrets }} + uses: webfactory/ssh-agent@v0.8.0 + with: + ssh-private-key: ${{ secrets.VC_KEY }} + + - name: get installer secrets + if: ${{ matrix.image.needs_installer_secrets }} + env: + VCELL_MANAGER_NODE: vcellapi.cam.uchc.edu + VCELL_DEPLOY_REMOTE_DIR: /share/apps/vcell3/deployed_github + run: | + ssh-keyscan ${VCELL_MANAGER_NODE} >> ~/.ssh/known_hosts + sudo mkdir /usr/local/deploy + sudo chmod 777 /usr/local/deploy + cd /usr/local/deploy + scp ${{ secrets.CD_FULL_USER }}@${VCELL_MANAGER_NODE}:${VCELL_DEPLOY_REMOTE_DIR}/deploy_dir_2025_03_18.tar . + cd .. + sudo tar -xvf deploy/deploy_dir_2025_03_18.tar + sudo chmod 777 -R deploy + + - name: Pre-build step + if: ${{ matrix.image.pre_build }} + run: ${{ matrix.image.pre_build }} + + - name: Log in to GHCR + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Build and push Docker image run: | - cd docker/build - echo "${{ secrets.GITHUB_TOKEN }}" | sudo docker login ghcr.io -u ${{ github.actor }} --password-stdin - echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - export BUILD_IMAGES="all" - ./build.sh ${BUILD_IMAGES} ${{ env.VCELL_REPO_NAMESPACE }} ${{ env.VCELL_TAG }} - - - name: tag as latest and push to registry - shell: bash + IMAGE_NAME="vcell-${{ matrix.image.name }}" + FULL_TAG="${{ needs.setup.outputs.vcell_repo_namespace }}/${IMAGE_NAME}:${{ needs.setup.outputs.vcell_tag }}" + BUILD_ARGS="" + if [ -n "${{ matrix.image.build_args || '' }}" ]; then + BUILD_ARGS="--build-arg ${{ matrix.image.build_args }}" + fi + echo "Building ${FULL_TAG}" + docker buildx build --platform=linux/amd64 \ + ${BUILD_ARGS} \ + -f ${{ matrix.image.dockerfile }} \ + --tag ${FULL_TAG} \ + ${{ matrix.image.context }} + docker push ${FULL_TAG} + + tag-and-push: + runs-on: ubuntu-22.04 + needs: [setup, docker-build] + steps: + - name: Log in to GHCR + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Tag and push all images run: | - export CONTAINER_SET="vcell-exporter vcell-api vcell-rest vcell-webapp-prod vcell-webapp-dev vcell-webapp-stage vcell-webapp-island vcell-batch vcell-opt vcell-clientgen vcell-data vcell-db vcell-mongo vcell-sched vcell-submit vcell-admin" - for CONTAINER in ${CONTAINER_SET};\ - do docker tag ${VCELL_REPO_NAMESPACE}/$CONTAINER:${VCELL_TAG} ${VCELL_REPO_NAMESPACE}/$CONTAINER:latest;\ - docker tag ${VCELL_REPO_NAMESPACE}/$CONTAINER:${VCELL_TAG} ${VCELL_REPO_NAMESPACE}/$CONTAINER:${FRIENDLY_TAG};\ - docker push --all-tags ${VCELL_REPO_NAMESPACE}/$CONTAINER;\ + REPO="${{ needs.setup.outputs.vcell_repo_namespace }}" + TAG="${{ needs.setup.outputs.vcell_tag }}" + FRIENDLY="${{ needs.setup.outputs.friendly_tag }}" + CONTAINERS="vcell-exporter vcell-api vcell-rest vcell-webapp-prod vcell-webapp-dev vcell-webapp-stage vcell-webapp-island vcell-webapp-remote vcell-batch vcell-opt vcell-clientgen vcell-data vcell-db vcell-mongo vcell-sched vcell-submit vcell-admin" + for CONTAINER in ${CONTAINERS}; do + docker pull ${REPO}/${CONTAINER}:${TAG} + docker tag ${REPO}/${CONTAINER}:${TAG} ${REPO}/${CONTAINER}:latest + docker tag ${REPO}/${CONTAINER}:${TAG} ${REPO}/${CONTAINER}:${FRIENDLY} + docker push --all-tags ${REPO}/${CONTAINER} done - name: Setup tmate session uses: mxschmitt/action-tmate@v3 if: ${{ failure() }} - - -# if [ "${{ github.event.inputs.client_only }}" = "true" ]; then -# echo "Building only client images" -# export BUILD_IMAGES="clientgen" -# else -# echo "Building all images" -# -# fi - -# if [ "${{ github.event.inputs.client_only }}" = "true" ]; then -# echo "Building only client images" -# export CONTAINER_SET="vcell-clientgen" -# else -# echo "Building all images" -# export CONTAINER_SET="vcell-exporter vcell-api vcell-rest vcell-webapp-prod vcell-webapp-dev vcell-webapp-stage vcell-webapp-island vcell-batch vcell-opt vcell-clientgen vcell-data vcell-db vcell-mongo vcell-sched vcell-submit vcell-admin" -# fi diff --git a/.github/workflows/site_deploy.yml b/.github/workflows/site_deploy.yml index 9087039b35..ff5ef15b7b 100644 --- a/.github/workflows/site_deploy.yml +++ b/.github/workflows/site_deploy.yml @@ -116,9 +116,15 @@ jobs: cd installers export MAC_INSTALLER=`ls *dmg` xcrun notarytool submit --output-format normal --no-progress --no-wait --team-id "${{ secrets.MACTEAMID }}" --apple-id "${{ secrets.MACID }}" --password "${{ secrets.MACPW }}" $MAC_INSTALLER > submit_output + SUBMIT_EXIT=$? echo "output returned by notarytool submit:" cat submit_output - cat submit_output | grep "id:" | cut -d ':' -f2 > UUID + cat submit_output | grep "id:" | cut -d ':' -f2 | tr -d '[:space:]' > UUID + if [[ $SUBMIT_EXIT != 0 || ! -s UUID ]]; then + echo "notarytool submit failed (exit=$SUBMIT_EXIT), no submission UUID obtained - aborting" + exit 1 + fi + echo "submission UUID: $(cat UUID)" for minutes in {1..5} do sleep 60 diff --git a/.gitignore b/.gitignore index 882ca3839a..b0ba9fb145 100644 --- a/.gitignore +++ b/.gitignore @@ -249,3 +249,7 @@ pythonData/test_data/SimID_946368938_0_.vcg pythonData/test_data/SimID_946368938_mathmodel.vcml pythonData/test_data/zarr/ + +pythonCopasiOpt/vcell-opt/.venv/ + +pythonCopasiOpt/vcell-opt/test_data/optproblem.report diff --git a/CLAUDE.md b/CLAUDE.md index f1f16ea338..b9292de83b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,14 +46,17 @@ mvn compile test-compile -pl vcell-rest -am ## OpenAPI Client Generation -OpenAPI spec is generated by Quarkus SmallRye OpenAPI from `vcell-rest` and stored in `tools/openapi.yaml`. Three clients are auto-generated: +OpenAPI spec is generated by Quarkus SmallRye OpenAPI from `vcell-rest` and stored in `tools/openapi.yaml`. Three clients are auto-generated (Java, Python, TypeScript-Angular) using OpenAPI Generator v7.1.0. ```bash -cd tools -./generate.sh # Generates Java, Python, and TypeScript-Angular clients +# Generate clients from existing tools/openapi.yaml (if spec is already up to date) +./tools/openapi-clients.sh + +# Rebuild vcell-rest, regenerate the OpenAPI spec, then generate all clients +./tools/openapi-clients.sh --update-spec ``` -- **Java client:** `vcell-restclient/` (OpenAPI Generator v7.1.0) +- **Java client:** `vcell-restclient/` - **Python client:** `python-restclient/` - **Angular client:** `webapp-ng/src/app/core/modules/openapi/` @@ -124,7 +127,7 @@ GitHub Actions (`.github/workflows/ci_cd.yml`): After major changes (especially removing/renaming user-facing features): - [ ] Check `vcell-client/UserDocumentation/` for references to changed features. This is an ad-hoc XML format compiled into JavaHelp (in-app help) and HTML published at https://vcell.org/webstart/VCell_Tutorials/VCell_Help/index.html. Update documentation to stay consistent with code. -- [ ] After regenerating OpenAPI clients (`tools/generate.sh`), compile downstream: `mvn compile test-compile -pl vcell-rest -am` +- [ ] After regenerating OpenAPI clients (`tools/openapi-clients.sh`), compile downstream: `mvn compile test-compile -pl vcell-rest -am` ## Conventions diff --git a/docker/build/Dockerfile-api-dev b/docker/build/Dockerfile-api-dev index da96024182..0f24a8a90f 100644 --- a/docker/build/Dockerfile-api-dev +++ b/docker/build/Dockerfile-api-dev @@ -69,7 +69,6 @@ ENV softwareVersion=SOFTWARE-VERSION-NOT-SET \ ssl_ignoreCertProblems=false \ serverPrefixV0="server-path-prefix-v0-not-set" \ protocol="https" \ - submit_service_host="submit" \ workingDir="/usr/local/app" ENV dbpswdfile=/run/secrets/dbpswd \ @@ -117,7 +116,6 @@ ENTRYPOINT java \ -Dvcell.smtp.emailAddress="${smtp_emailaddress}" \ -Dvcell.ssl.ignoreHostMismatch="${ssl_ignoreHostMismatch}" \ -Dvcell.ssl.ignoreCertProblems="${ssl_ignoreCertProblems}" \ - -Dvcell.submit.service.host="${submit_service_host}" \ -Dvcellapi.privateKey.file="${vcellapi_privatekeyfile}" \ -Dvcellapi.publicKey.file="${vcellapi_publickeyfile}" \ -cp "./lib/*" org.vcell.rest.VCellApiMain \ diff --git a/docker/build/Dockerfile-batch-dev b/docker/build/Dockerfile-batch-dev index 4a5d79cda8..202d3eabde 100644 --- a/docker/build/Dockerfile-batch-dev +++ b/docker/build/Dockerfile-batch-dev @@ -17,7 +17,7 @@ COPY ./vcell-server/target/vcell-server-0.0.1-SNAPSHOT.jar \ ./lib/ COPY ./nativelibs/linux64 ./nativelibs/linux64 -COPY ./localsolvers/linux64/langevin_x64 /vcellbin/ +COPY --chmod=755 ./localsolvers/linux64/langevin_x64 /vcellbin/ COPY ./docker/build/batch/JavaPreprocessor64 \ ./docker/build/batch/JavaPostprocessor64 \ ./docker/build/batch/JavaSimExe64 \ diff --git a/docker/build/Dockerfile-submit-dev b/docker/build/Dockerfile-submit-dev index 31e733efb0..c7877b5132 100644 --- a/docker/build/Dockerfile-submit-dev +++ b/docker/build/Dockerfile-submit-dev @@ -90,6 +90,8 @@ ENV softwareVersion=SOFTWARE-VERSION-NOT-SET \ slurm_langevin_timeoutPerTaskSeconds="slurm_langevin_timeoutPerTaskSeconds-not-set" \ slurm_langevin_batchMemoryLimitPerTaskMB="slurm_langevin_batchMemoryLimitPerTaskMB-not-set" \ slurm_langevin_memoryBlockSizeMB="slurm_langevin_memoryBlockSizeMB-not-set" \ + jmshost_artemis_internal=artemismq \ + jmsport_artemis_internal=61616 \ jmsblob_minsize=100000 \ vcell_ssh_cmd_cmdtimeout="cmdSrvcSshCmdTimeoutMS-not-set" \ vcell_ssh_cmd_restoretimeout="cmdSrvcSshCmdRestoreTimeoutFactor-not-set" \ @@ -167,6 +169,8 @@ ENTRYPOINT java \ -Dvcell.jms.sim.host.external="${jmshost_sim_external}" \ -Dvcell.jms.sim.port.external="${jmsport_sim_external}" \ -Dvcell.jms.sim.restport.external="${jmsrestport_sim_external}" \ + -Dvcell.jms.artemis.host.internal="${jmshost_artemis_internal}" \ + -Dvcell.jms.artemis.port.internal="${jmsport_artemis_internal}" \ -Dvcell.jms.blobMessageUseMongo=true \ -Dvcell.jms.blobMessageMinSize="${jmsblob_minsize}" \ -Dvcell.jms.user="${jmsuser}" \ diff --git a/docker/swarm/docker-compose.yml b/docker/swarm/docker-compose.yml index 92e6debdc3..faf0979e7c 100644 --- a/docker/swarm/docker-compose.yml +++ b/docker/swarm/docker-compose.yml @@ -195,7 +195,6 @@ services: - mongodb_database=test ports: - "${VCELL_DEBUG_PORT_VCELL_SUBMIT}:8000" # java remote debugging - - "8877" volumes: - "${VCELL_SIMDATADIR_HOST}:/simdata" - "${VCELL_SIMDATADIR_SECONDARY_HOST}:/simdata_secondary" diff --git a/docs/database-design-patterns.md b/docs/database-design-patterns.md new file mode 100644 index 0000000000..6eda9305b6 --- /dev/null +++ b/docs/database-design-patterns.md @@ -0,0 +1,450 @@ +# VCell Database Design Patterns + +This document describes the database design patterns used throughout VCell for table definitions, CRUD operations, connection management, and access control. New tables should follow these patterns for consistency. + +## Architecture Overview + +The database layer follows a three-tier pattern: + +``` +DatabaseServerImpl (public API, wraps TopLevel) + └── DBTopLevel / AdminDBTopLevel (connection + transaction management) + └── DbDriver subclasses (SQL generation + execution) + └── Table subclasses (schema definition + value mapping) +``` + +## Table Definitions + +### Class hierarchy + +``` +cbit.sql.Table (abstract) + ├── cbit.vcell.modeldb.VersionTable (abstract) — versioned entities with privacy/curation + │ ├── BioModelTable + │ ├── SimulationTable + │ ├── MathModelTable + │ ├── GeometryTable + │ └── ... + └── Direct subclasses — operational/non-versioned data + ├── SimulationJobTable + ├── UserTable + ├── ApiClientTable + └── ... +``` + +**Versioned tables** (`VersionTable` subclasses) store domain model objects (BioModels, Simulations) with built-in `privacy` (access control) and `versionFlag` (curation status) columns. + +**Operational tables** (direct `Table` subclasses) store runtime/transactional data like job records, user sessions, etc. These typically don't need privacy or versioning. **The new `vc_optjob` table falls into this category**, similar to `SimulationJobTable`. + +### Field declarations + +Each table declares its columns as `public final Field` members. The `Field` class carries the column name, data type, and constraints: + +```java +public class SimulationJobTable extends Table { + private static final String TABLE_NAME = "vc_simulationjob"; + public static final String REF_TYPE = "REFERENCES " + TABLE_NAME + "(id)"; + + // Singleton instance + public static final SimulationJobTable table = new SimulationJobTable(); + + // Column declarations + public final Field simRef = new Field("simRef", SQLDataType.integer, "NOT NULL " + SimulationTable.REF_TYPE + " ON DELETE CASCADE"); + public final Field submitDate = new Field("submitDate", SQLDataType.date, "NOT NULL"); + public final Field taskID = new Field("taskID", SQLDataType.integer, "NOT NULL"); + public final Field statusMsg = new Field("statusMsg", SQLDataType.varchar_4000, ""); + public final Field serverID = new Field("serverID", SQLDataType.varchar_20, "NOT NULL"); + public final Field pbsJobID = new Field("pbsJobID", SQLDataType.varchar_100, ""); + + private SimulationJobTable() { + super(TABLE_NAME); + addFields(new Field[] { simRef, submitDate, taskID, ... }); + } +} +``` + +**Key conventions:** +- Each table class has a `public static final` singleton instance (`table`) +- Fields are `public final` for direct access in SQL generation +- The base `Table` class provides the `id` field (bigint primary key) automatically +- `SQLDataType` enum maps to database-agnostic types: `integer`, `varchar_255`, `varchar_4000`, `date`, `clob_text`, etc. +- Constraints include `NOT NULL`, `REFERENCES`, and `ON DELETE CASCADE` + +### Available SQLDataType values + +There are two naming conventions for varchar types in `Field.SQLDataType`: +- **`varchar2_*`** — Oracle-native names (e.g. `varchar2_32`). Oracle generates `VARCHAR2(N)`, PostgreSQL generates `varchar(N)`. +- **`varchar_*`** — PostgreSQL-native names (e.g. `varchar_128`). Both Oracle and PostgreSQL generate `varchar(N)`. + +Either convention works for both databases. Prefer the `varchar2_*` variants for consistency with existing tables. + +| SQLDataType | Oracle | PostgreSQL | +|---|---|---| +| `integer` | NUMBER | bigint | +| `number_as_integer` | number | bigint | +| `number_as_real` | number | numeric | +| `varchar2_5` | VARCHAR2(5) | varchar(5) | +| `varchar2_10` | VARCHAR2(10) | varchar(10) | +| `varchar2_20` | VARCHAR2(20) | varchar(20) | +| `varchar2_32` | VARCHAR2(32) | varchar(32) | +| `varchar2_40` | VARCHAR2(40) | varchar(40) | +| `varchar2_64` | VARCHAR2(64) | varchar(64) | +| `varchar2_128` | VARCHAR2(128) | varchar(128) | +| `varchar2_255` | VARCHAR2(255) | varchar(255) | +| `varchar2_256` | VARCHAR2(256) | varchar(256) | +| `varchar2_512` | VARCHAR2(512) | varchar(512) | +| `varchar2_1024` | VARCHAR2(1024) | varchar(1024) | +| `varchar2_2000` | VARCHAR2(2000) | varchar(2000) | +| `varchar2_4000` | VARCHAR2(4000) | varchar(4000) | +| `varchar_10` ... `varchar_4000` | varchar(N) | varchar(N) | +| `date` | date | timestamp | +| `clob_text` | CLOB | text | +| `blob_bytea` | BLOB | bytea | +| `numeric` | NUMBER | numeric | +| `char_1` | CHAR(1) | char(1) | + +## CRUD Operations + +Each `Table` subclass implements three methods for SQL generation: + +### INSERT — `getSQLValueList()` + +Generates the VALUES clause for an INSERT statement. Takes a `KeyValue` (the new row's primary key) and the domain object to persist: + +```java +public String getSQLValueList(KeyValue key, SimulationJobStatus jobStatus, DatabaseSyntax dbSyntax) { + return "(" + + key + "," + + jobStatus.getVCSimulationIdentifier().getSimulationKey() + "," + + "current_timestamp" + "," + + jobStatus.getTaskID() + "," + + jobStatus.getSchedulerStatus().getDatabaseNumber() + "," + + "'" + TokenMangler.getSQLEscapedString(statusMsg) + "'" + "," + + // ... more fields + ")"; +} +``` + +**Conventions:** +- First value is always the primary key +- Timestamps use `current_timestamp` for server-generated times +- Strings escaped with `TokenMangler.getSQLEscapedString()` +- Dates formatted with `VersionTable.formatDateToOracle()` +- Null values written as literal `null` +- Enum values stored as integers via `.getDatabaseNumber()` + +### UPDATE — `getSQLUpdateList()` + +Generates the SET clause for an UPDATE statement: + +```java +public String getSQLUpdateList(SimulationJobStatus jobStatus, DatabaseSyntax dbSyntax) { + return + schedulerStatus + "=" + jobStatus.getSchedulerStatus().getDatabaseNumber() + "," + + statusMsg + "='" + TokenMangler.getSQLEscapedString(msg) + "'," + + latestUpdateDate + "=" + "current_timestamp"; + // Note: last field has NO trailing comma +} +``` + +### SELECT — `getXxx(ResultSet)` + +Reads a domain object from a `ResultSet`: + +```java +public SimulationJobStatus getSimulationJobStatus(ResultSet rset) throws SQLException { + KeyValue key = new KeyValue(rset.getBigDecimal(id.toString())); + KeyValue simRef = new KeyValue(rset.getBigDecimal(this.simRef.toString())); + Date submitDate = rset.getTimestamp(this.submitDate.toString()); + int schedulerStatusInt = rset.getInt(this.schedulerStatus.toString()); + SchedulerStatus status = SchedulerStatus.fromDatabaseNumber(schedulerStatusInt); + String statusMsg = rset.getString(this.statusMsg.toString()); + // ... reconstruct domain object + return new SimulationJobStatus(...); +} +``` + +**Conventions:** +- Access columns by `field.toString()` (the column name) +- Use `rset.wasNull()` after `getInt()` to distinguish 0 from NULL +- Convert BigDecimal → KeyValue for foreign keys +- Convert int → enum via `fromDatabaseNumber()` static method +- Nullable fields checked with `rset.wasNull()` or null reference check + +## DbDriver Layer + +DbDriver subclasses contain the actual SQL execution logic for a group of related tables. They are organized by domain area: + +- `SimulationJobDbDriver` — simulation job CRUD +- `BioModelDbDriver` — biomodel CRUD + related tables +- `AdminDBTopLevel` — administrative operations + +### Standard method signatures + +```java +// INSERT +public KeyValue insertSimulationJobStatus(Connection con, SimulationJobStatus jobStatus) + throws SQLException { + KeyValue key = keyFactory.getNewKey(con); + String sql = "INSERT INTO " + SimulationJobTable.table.getTableName() + + " " + SimulationJobTable.table.getSQLColumnList() + + " VALUES " + SimulationJobTable.table.getSQLValueList(key, jobStatus, dbSyntax); + executeUpdate(con, sql); + return key; +} + +// UPDATE +public void updateSimulationJobStatus(Connection con, KeyValue key, SimulationJobStatus jobStatus) + throws SQLException { + String sql = "UPDATE " + SimulationJobTable.table.getTableName() + + " SET " + SimulationJobTable.table.getSQLUpdateList(jobStatus, dbSyntax) + + " WHERE " + SimulationJobTable.table.id + "=" + key; + executeUpdate(con, sql); +} + +// SELECT +public SimulationJobStatus[] getSimulationJobStatus(Connection con, KeyValue simKey) + throws SQLException { + String sql = "SELECT * FROM " + SimulationJobTable.table.getTableName() + + " WHERE " + SimulationJobTable.table.simRef + "=" + simKey; + Statement stmt = con.createStatement(); + try { + ResultSet rset = stmt.executeQuery(sql); + while (rset.next()) { + results.add(SimulationJobTable.table.getSimulationJobStatus(rset)); + } + } finally { + stmt.close(); + } + return results.toArray(...); +} +``` + +### Helper method + +```java +protected void executeUpdate(Connection con, String sql) throws SQLException { + if (lg.isDebugEnabled()) lg.debug(sql); + Statement stmt = con.createStatement(); + try { + int rowCount = stmt.executeUpdate(sql); + if (rowCount != 1) { + throw new SQLException("Expected 1 row, got " + rowCount); + } + } finally { + stmt.close(); + } +} +``` + +## Connection & Transaction Management + +### ConnectionFactory + +`org.vcell.db.ConnectionFactory` provides connection pooling. In Quarkus (`vcell-rest`), this is implemented by `AgroalConnectionFactory` which delegates to Agroal/JDBC datasources. + +**Usage pattern:** +```java +Object lock = new Object(); +Connection con = connectionFactory.getConnection(lock); +try { + // ... perform operations + con.commit(); +} catch (SQLException e) { + con.rollback(); + throw e; +} finally { + connectionFactory.release(con, lock); +} +``` + +### DBTopLevel / AdminDBTopLevel + +These classes wrap DbDriver calls with connection management and retry logic: + +```java +public SimulationJobStatus[] getSimulationJobStatus(KeyValue simKey, boolean bEnableRetry) + throws DataAccessException, SQLException { + Object lock = new Object(); + Connection con = conFactory.getConnection(lock); + try { + return dbDriver.getSimulationJobStatus(con, simKey); + } catch (Throwable e) { + handle_DataAccessException_SQLException(e); + if (bEnableRetry && isBadConnection(con)) { + conFactory.failed(con, lock); + return getSimulationJobStatus(simKey, false); // retry once + } + throw e; + } finally { + conFactory.release(con, lock); + } +} +``` + +**Key features:** +- Automatic retry on bad connections (once) +- Connection release in `finally` block +- Exception conversion: `SQLException` → `DataAccessException` + +### DatabaseServerImpl + +The public API that Quarkus services call. Wraps `DBTopLevel`/`AdminDBTopLevel`: + +```java +@ApplicationScoped +public class DatabaseServerImpl { + private final DBTopLevel dbTopLevel; + private final AdminDBTopLevel adminDbTopLevel; + + public DatabaseServerImpl(AgroalConnectionFactory connectionFactory, KeyFactory keyFactory) { + this.dbTopLevel = new DBTopLevel(connectionFactory); + this.adminDbTopLevel = new AdminDBTopLevel(connectionFactory); + } + + public SimulationJobStatus[] getSimulationJobStatus(KeyValue simKey) + throws DataAccessException, SQLException { + return adminDbTopLevel.getSimulationJobStatus(simKey, true); + } +} +``` + +## Key Generation + +All primary keys come from a shared database sequence (`newSeq`). The key is generated **before** the INSERT: + +```java +KeyValue key = keyFactory.getNewKey(con); // SELECT nextval('newSeq') +String sql = "INSERT INTO table VALUES (" + key + ", ...)"; +``` + +The `KeyValue` class wraps a `BigDecimal` and is used throughout the codebase for all database IDs. + +## Access Control (Versioned Tables Only) + +Versioned tables (`VersionTable` subclasses) have two orthogonal concepts: + +### Privacy (GroupAccess) + +Controls who can read/modify a record: +- `GroupAccess.GROUPACCESS_ALL` (groupid=0) — public, anyone can read +- `GroupAccess.GROUPACCESS_NONE` (groupid=1) — private, owner only +- Other groupid values — shared with a specific group + +Enforced in SELECT queries via `DatabasePolicySQL.enforceOwnershipSelect()`. + +### Curation Status (VersionFlag) + +Indicates model maturity, **not** access control: +- `VersionFlag.Current` (0) — normal working copy +- `VersionFlag.Archived` (1) — frozen, not deletable +- `VersionFlag.Published` (3) — published, not deletable, publicly accessible + +**Operational tables like `vc_optjob` do not use privacy or curation status.** Access control is enforced at the REST layer by checking the `ownerRef` field. + +## Summary: Creating a New Operational Table + +To add a new table following VCell conventions (e.g., `vc_optjob`): + +1. **Create `OptJobTable extends Table`** in `cbit.vcell.messaging.db` or `cbit.vcell.modeldb` + - Declare all fields as `public final Field` + - Implement `getSQLValueList()`, `getSQLUpdateList()`, `getOptJobStatus(ResultSet)` + - Add a `public static final OptJobTable table` singleton + +2. **Create or extend a DbDriver** with INSERT/UPDATE/DELETE/SELECT methods + - Use `Table.getSQLColumnList()` and `getSQLValueList()` for INSERT + - Use `getSQLUpdateList()` for UPDATE + - Use `getOptJobStatus(ResultSet)` for SELECT + - Use `keyFactory.getNewKey(con)` for key generation + +3. **Add methods to AdminDBTopLevel** (or create a new TopLevel) with connection + retry pattern + +4. **Add public methods to DatabaseServerImpl** wrapping the TopLevel calls + +5. **Register in `SQLCreateAllTables.getVCellTables()`** — add the table singleton to the array (see below) + +6. **Regenerate `init.sql`** using `AdminCli db-create-script` (see below) + +7. **Create Oracle DDL** for production deployment (manual migration) + +## Authoritative Table Registry + +`SQLCreateAllTables.getVCellTables()` in `vcell-server` returns the authoritative list of all active tables in the database. Every table must be registered here — this array drives: + +- DDL script generation (`db-create-script`) +- Schema comparison (`db-compare-schema`) +- Full database creation/destruction (`destroyAndRecreateTables`) + +Tables are ordered by dependency (referenced tables before referencing tables) so that `CREATE TABLE` and `DROP TABLE` (in reverse) respect foreign key constraints. + +**When adding a new table**, insert it at the appropriate position in the array, after any tables it references via foreign keys. + +## Database Utilities (AdminCli) + +The `vcell-admin` module provides CLI commands (PicoCLI) for database management. These are in `org.vcell.admin.cli.db`. + +### `db-create-script` — Generate DDL from Table definitions + +Generates a SQL creation script from the Java `Table` definitions registered in `SQLCreateAllTables.getVCellTables()`. This is the canonical way to produce `init.sql` for test/dev PostgreSQL databases. + +```bash +AdminCli db-create-script \ + --database-type=postgres \ + --bootstrap-data=false \ + --create-script=vcell-rest/src/main/resources/scripts/init.sql +``` + +**Options:** +| Option | Description | +|--------|-------------| +| `--database-type` | `oracle` or `postgres` (required) | +| `--create-script` | Output file path (required) | +| `--bootstrap-data` | `true` to include INSERT statements for seed users, groups, API client (required) | +| `-d, --debug` | Enable debug logging | + +**What it generates:** +1. `CREATE TABLE` statements for every table in `getVCellTables()` (in dependency order) +2. `CREATE VIEW public.dual` (PostgreSQL ORACLE compatibility) +3. `CREATE SEQUENCE newSeq` +4. `CREATE INDEX` statements for performance-critical lookups +5. (If `--bootstrap-data=true`) INSERT statements for void/admin/test/support users, private/public groups, available status, and default API client + +**Important:** The `init.sql` file used by Quarkus testcontainers (`vcell-rest/src/main/resources/scripts/init.sql`) has two sections: + +1. **Generated DDL** (tables, view, sequence, indexes) — produced by `db-create-script --bootstrap-data=false`. The Java `Table` classes are the source of truth for this section. Do not hand-edit it. +2. **Hand-maintained seed data** (INSERT statements) — test fixtures for users, groups, identities, special users, API client, and publications required by Quarkus tests. This section is maintained manually and is not generated by `db-create-script`. + +When updating `init.sql`, regenerate only the DDL portion and preserve the seed data INSERTs. + +### `db-compare-schema` — Compare live database against Table definitions + +Compares the schema of a running database against the Java `Table` definitions. Useful for verifying that a deployed database matches the expected schema, or for identifying drift after manual DDL changes. + +```bash +AdminCli db-compare-schema +``` + +Requires database connection properties to be configured (via environment variables or `PropertyLoader`). Uses `CompareDatabaseSchema.runCompareSchemas()` to introspect the live database and diff against `getVCellTables()`. + +**Options:** +| Option | Description | +|--------|-------------| +| `-d, --debug` | Enable debug logging | + +### `db-destroy-recreate` — Drop and recreate all tables (interactive) + +**DESTRUCTIVE.** Drops all tables, sequences, and views, then recreates them. Prompts via Swing dialog for confirmation. Only for development use. + +## Schema Change Workflow + +When modifying the database schema (adding tables, columns, or indexes): + +1. **Edit the Java `Table` class** — add/modify `Field` declarations +2. **Register new tables** in `SQLCreateAllTables.getVCellTables()` if not already present +3. **Regenerate `init.sql`:** + ```bash + AdminCli db-create-script --database-type=postgres --bootstrap-data=false \ + --create-script=vcell-rest/src/main/resources/scripts/init.sql + ``` +4. **Verify** with `db-compare-schema` against a dev database if available +5. **Create production migration DDL** (Oracle `ALTER TABLE` / `CREATE TABLE` statements) for deployed databases diff --git a/docs/parameter-estimation-service.md b/docs/parameter-estimation-service.md new file mode 100644 index 0000000000..946c9d2a73 --- /dev/null +++ b/docs/parameter-estimation-service.md @@ -0,0 +1,290 @@ +# Parameter Estimation Service + +## Requirements + +Parameter estimation allows VCell users to fit model parameters to experimental data. The service must satisfy the following requirements: + +### Functional requirements + +1. **Submit optimization job.** An authenticated user submits an `OptProblem` (SBML model, experimental data, parameter bounds, optimization method) and receives a job ID. The problem is dispatched to a SLURM cluster for execution using the COPASI optimization engine. + +2. **Real-time progress reporting.** While the solver runs, the client receives periodic updates showing: + - Objective function value vs. function evaluations (displayed as a graph) + - Current best parameter values (displayed in a table) + - Progress updates every ~2 seconds via client polling + +3. **Retrieve results.** When optimization completes, the client retrieves the final optimized parameter values, objective function value, and the full progress history. + +4. **Stop running job.** A user can stop an optimization mid-run. The best parameters found up to the stop point are returned to the client, allowing the user to accept partial results when convergence is sufficient. + +5. **Job ownership.** Only the user who submitted a job can query its status, retrieve results, or stop it. + +6. **List jobs.** A user can list their optimization jobs with current status. + +### Non-functional requirements + +7. **Survive pod restarts.** Job state must be persisted so that in-flight jobs are not lost when the REST service or submit service restarts. This is routine in Kubernetes. + +8. **No single point of failure for job dispatch.** Communication between the REST service and the batch submission service must use a durable message broker, not in-memory connections. + +9. **Collision-free job IDs.** Job identifiers must be unique, using database-sequence keys rather than random numbers. + +10. **Auto-generated API clients.** The REST API must have an OpenAPI spec, and Java/Python/TypeScript clients must be auto-generated from it to stay in sync with the server. + +11. **Shared filesystem for solver I/O.** The optimization problem input, progress report, and result output are files on a shared NFS mount — matching the Python solver's file-based interface. The database tracks metadata and status; the filesystem holds the data. + +## Architecture + +``` +Desktop Client / webapp + | + | POST /api/v1/optimization (OptProblem JSON) + v +vcell-rest (Quarkus) + | 1. Validate OptProblem + | 2. Get bigint job ID from database sequence (newSeq) + | 3. Write OptProblem JSON to NFS: /simdata/parest_data/CopasiParest_{id}_optProblem.json + | 4. Insert vc_optjob row (status=SUBMITTED) + | 5. Publish OptRequestMessage to Artemis "opt-request" queue (AMQP 1.0 via SmallRye) + | 6. Return OptimizationJobStatus to client + v +Artemis broker (artemismq:61616) + | ANYCAST queue "opt-request" + | Cross-protocol: AMQP 1.0 (vcell-rest) ↔ OpenWire JMS (vcell-submit) + v +vcell-submit (OpenWire JMS via ActiveMQConnectionFactory) + | 1. Consume OptRequestMessage from "opt-request" queue + | 2. Read OptProblem file from NFS path in message + | 3. Submit SLURM job via SlurmProxy.submitOptimizationJob() + | 4. Publish OptStatusMessage to "opt-status" queue (QUEUED + htcJobId, or FAILED + error) + v +SLURM → Singularity container → vcell-opt Python solver + | Writes to NFS: + | - CopasiParest_{id}_optReport.txt (progress, written incrementally) + | - CopasiParest_{id}_optRun.json (final results) + v +Artemis broker + | ANYCAST queue "opt-status" + | vcell-submit publishes via OpenWire JMS + | vcell-rest consumes via AMQP 1.0 (SmallRye @Incoming) + v +vcell-rest (OptimizationMQ.consumeOptStatus) + | Updates vc_optjob: status=QUEUED, htcJobId from message + v +vcell-rest (polling on client request) + | 1. Client polls GET /api/v1/optimization/{id} every 2 seconds + | 2. Check vc_optjob status in database + | 3. For any active status (SUBMITTED/QUEUED/RUNNING): + | a. Read progress from report file on NFS (CopasiUtils.readProgressReportFromCSV) + | b. If progress exists and status is SUBMITTED/QUEUED: auto-promote to RUNNING + | c. If result file exists: auto-promote to COMPLETE, read Vcellopt results + | 4. Return OptimizationJobStatus with progress/results + v +Client displays progress (objective function vs iteration graph, best parameter values) +``` + +## Cross-protocol messaging through Artemis + +The optimization messaging uses **cross-protocol communication** through an Apache Artemis broker. + +**Protocol mapping:** +- **vcell-rest** uses **AMQP 1.0** via Quarkus SmallRye Reactive Messaging (`quarkus-smallrye-reactive-messaging-amqp`) +- **vcell-submit** uses **OpenWire JMS** via ActiveMQ 5.x client (`org.apache.activemq.ActiveMQConnectionFactory`) +- **Artemis** accepts both protocols on port 61616 (all-protocol acceptor) and routes messages between them + +**Queue configuration:** +- `opt-request` — ANYCAST queue. vcell-rest produces (AMQP 1.0), vcell-submit consumes (OpenWire JMS) +- `opt-status` — ANYCAST queue. vcell-submit produces (OpenWire JMS), vcell-rest consumes (AMQP 1.0) + +**Critical SmallRye AMQP settings** (in `application.properties`): + +```properties +mp.messaging.outgoing.publisher-opt-request.connector=smallrye-amqp +mp.messaging.outgoing.publisher-opt-request.address=opt-request +mp.messaging.outgoing.publisher-opt-request.capabilities=queue + +mp.messaging.incoming.subscriber-opt-status.connector=smallrye-amqp +mp.messaging.incoming.subscriber-opt-status.address=opt-status +mp.messaging.incoming.subscriber-opt-status.capabilities=queue +``` + +**Important configuration notes:** + +1. **`address` is required.** Without explicit `address=opt-request`, SmallRye defaults to using the channel name (`publisher-opt-request`) as the AMQP address. The OpenWire consumer listens on queue `opt-request`, so messages are lost silently. + +2. **`capabilities=queue` is required.** Artemis deploys queues as ANYCAST by default. Without this, SmallRye AMQP creates a MULTICAST subscription that never receives messages from the ANYCAST queue. + +3. **vcell-submit needs Artemis connection properties.** `vcell.jms.artemis.host.internal` and `vcell.jms.artemis.port.internal` must be set in the vcell-submit container. These are separate from the existing `activemqint` connection used for simulation job dispatch. + +**K8s configuration** (in vcell-fluxcd `shared.env`): +``` +jmshost_artemis_internal=artemismq +jmsport_artemis_internal=61616 +``` + +## Key design decisions + +**Database-backed job tracking.** Every optimization job gets a row in `vc_optjob`. The database is the source of truth for job lifecycle state (SUBMITTED → QUEUED → RUNNING → COMPLETE/FAILED/STOPPED). This survives pod restarts and supports multiple API replicas. + +**Filesystem for data, database for state.** The OptProblem input, result output, and progress report are files on NFS — this matches the Python solver's file-based interface and avoids putting large blobs in the database. + +**Database-sequence job IDs.** Bigint keys from the shared `newSeq` database sequence, consistent with every other VCell table. Uses the existing `KeyValue` type and `KeyFactory.getNewKey()`. + +**Filesystem-driven status promotion.** vcell-submit only sends a single `QUEUED` status message back after submitting the SLURM job. All subsequent status transitions are driven by vcell-rest reading the filesystem on each client poll: +- **SUBMITTED/QUEUED → RUNNING**: when the progress report file appears on NFS +- **RUNNING → COMPLETE**: when the result output file appears on NFS + +**COPASI progress flushing.** The Python solver uses `basico.assign_report(..., confirm_overwrite=False)` to ensure COPASI flushes progress lines incrementally during execution. Without this, COPASI buffers the entire report until completion, preventing real-time progress updates. + +## Database schema + +```sql +CREATE TABLE vc_optjob ( + id bigint PRIMARY KEY, + ownerRef bigint REFERENCES vc_userinfo(id), + status varchar(32) NOT NULL, + optProblemFile varchar(512) NOT NULL, + optOutputFile varchar(512) NOT NULL, + optReportFile varchar(512) NOT NULL, + htcJobId varchar(128), + statusMessage varchar(4000), + insertDate timestamp NOT NULL, + updateDate timestamp NOT NULL +); +``` + +Status transitions: +``` +SUBMITTED → QUEUED → RUNNING → COMPLETE + → FAILED + → STOPPED (user-initiated) +``` + +## REST API + +``` +POST /api/v1/optimization Submit optimization job +GET /api/v1/optimization List user's optimization jobs +GET /api/v1/optimization/{id} Get job status, progress, or results +POST /api/v1/optimization/{id}/stop Stop a running job +``` + +All endpoints require authentication (`@RolesAllowed("user")`) and enforce job ownership. + +### Response DTO + +```java +public record OptimizationJobStatus( + KeyValue id, + OptJobStatus status, + String statusMessage, + String htcJobId, + OptProgressReport progressReport, + Vcellopt results +) {} +``` + +### Message types + +Shared in `vcell-core` (`org.vcell.optimization` package), serialized as JSON: + +```java +public class OptRequestMessage { + public String jobId; + public String command; // "submit" or "stop" + public String optProblemFilePath; // for submit + public String optOutputFilePath; // for submit + public String optReportFilePath; // for submit + public String htcJobId; // for stop (SLURM job to cancel) +} + +public class OptStatusMessage { + public String jobId; + public OptJobStatus status; + public String statusMessage; + public String htcJobId; // set when SLURM job is submitted +} +``` + +## Progress reporting + +The desktop client displays a real-time graph of objective function value vs. function evaluations, along with the current best parameter values. + +1. The Python COPASI solver writes a TSV report file incrementally (`CopasiParest_{id}_optReport.txt`): + ``` + ["k1","k2"] ← header: JSON array of parameter names + 10 0.5 1.0 2.0 ← numEvals, objFuncValue, param1, param2, ... + 20 0.1 1.3 2.4 + 30 0.01 1.5 2.5 + ``` + +2. On each client poll, `OptimizationRestService.getOptimizationStatus()` reads this file via `CopasiUtils.readProgressReportFromCSV()`, returning an `OptProgressReport` with `progressItems` and `bestParamValues`. + +3. The client dispatches progress to `CopasiOptSolverCallbacks.setProgressReport()` via `SwingUtilities.invokeLater`, which fires a `PropertyChangeEvent` to the `RunStatusProgressDialog`. + +## Desktop client architecture + +### UI layer + +- **`ParameterEstimationRunTaskPanel`** — Main run panel. `solve()` dispatches an async task chain calling `CopasiOptimizationSolverRemote.solveRemoteApi()`. +- **`RunStatusProgressDialog`** (inner class) — Modal dialog showing evaluations, objective value, and log10(error) vs evaluations plot. + +### Solver coordination + +- **`CopasiOptimizationSolverRemote`** — Orchestrates the remote call: converts `ParameterEstimationTask` → `OptProblem`, submits via generated API client, polls every 2 seconds (10-minute timeout), dispatches progress to callbacks, handles stop. + +### Callback layer + +- **`CopasiOptSolverCallbacks`** — Bridges solver and UI via `PropertyChangeListener`. Carries `OptProgressReport` and `stopRequested`. + +### API client + +- **`OptimizationResourceApi`** (auto-generated in `vcell-restclient`) — Typed REST client generated from the OpenAPI spec via `tools/openapi-clients.sh`. +- **`VCellApiClient.getOptimizationApi()`** — Factory method providing access to the generated client. + +## Python solver (vcell-opt) + +The COPASI parameter estimation solver runs as a Singularity container on the SLURM cluster. + +- **Location:** `pythonCopasiOpt/vcell-opt/` +- **Dependencies:** `copasi-basico ^0.86`, `python-copasi ^4.45.298`, Python `^3.10` +- **Docker image:** `ghcr.io/virtualcell/vcell-opt:` (Dockerfile at `pythonCopasiOpt/Dockerfile`, Debian bookworm base) +- **Entry point:** `vcell_opt.optService.run_command(opt_file, result_file, report_file)` + +The solver reads an `OptProblem` JSON, runs COPASI parameter estimation, writes results to `_optRun.json`, and writes incremental progress to `_optReport.txt`. + +## Key files + +| File | Purpose | +|------|---------| +| `vcell-rest/.../handlers/OptimizationResource.java` | REST endpoints | +| `vcell-rest/.../services/OptimizationRestService.java` | DB CRUD and filesystem reads | +| `vcell-rest/.../activemq/OptimizationMQ.java` | AMQP 1.0 producer/consumer | +| `vcell-rest/src/main/resources/application.properties` | AMQP channel config | +| `vcell-server/.../batch/opt/OptimizationBatchServer.java` | OpenWire JMS listener, SLURM dispatch | +| `vcell-server/.../batch/sim/HtcSimulationWorker.java` | Starts opt queue listener in `init()` | +| `vcell-core/.../optimization/OptRequestMessage.java` | Request message type | +| `vcell-core/.../optimization/OptStatusMessage.java` | Status message type | +| `vcell-core/.../optimization/OptJobStatus.java` | Status enum | +| `vcell-core/.../modeldb/OptJobTable.java` | Database table definition | +| `vcell-client/.../copasi/CopasiOptimizationSolverRemote.java` | Desktop client solver | +| `pythonCopasiOpt/vcell-opt/vcell_opt/optService.py` | Python COPASI solver | +| `tools/openapi-clients.sh` | OpenAPI client generation script | + +## Tests + +| Test | Level | What it covers | +|------|-------|----------------| +| `OptimizationResourceTest` (`@Tag("Quarkus")`) | REST + DB + filesystem | Submit, poll, completion, stop, authorization, errors. Testcontainers for PostgreSQL + Keycloak. | +| `OptimizationE2ETest` (`@Tag("Quarkus")`) | Client flow | Same code path as `CopasiOptimizationSolverRemote.solveRemoteApi()` using generated API client. | +| `OptimizationCrossProtocolTest` (`@Tag("Quarkus")`) | Cross-protocol messaging | Full AMQP 1.0 ↔ OpenWire JMS round-trip through real Artemis testcontainer with OpenWire stub. | +| `SlurmProxyTest` (`@Tag("Fast")`) | SLURM script generation | Verifies optimization SLURM job script matches expected fixture. | +| `vcellopt_test.py::test_incremental_report_writing` | Solver progress flushing | Multiprocessing test verifying COPASI flushes report file incrementally. | + +## Future improvements + +- Migrate vcell-submit from ActiveMQ 5.x OpenWire client to Artemis JMS client (`jakarta.jms`) for protocol consistency +- Add dead letter and expiry address configuration for opt-request/opt-status queues in Artemis +- Add monitoring/alerting for optimization job failures +- Make the 10-minute client timeout configurable +- Add Level 3 SLURM integration test (`@Tag("SLURM_IT")`) for full end-to-end validation with real SLURM diff --git a/python-restclient/.openapi-generator/FILES b/python-restclient/.openapi-generator/FILES index 3f9b5211aa..9faadc1937 100644 --- a/python-restclient/.openapi-generator/FILES +++ b/python-restclient/.openapi-generator/FILES @@ -15,6 +15,11 @@ docs/BiomodelRef.md docs/CompositeCurve.md docs/ControlPointCurve.md docs/Coordinate.md +docs/CopasiOptimizationMethod.md +docs/CopasiOptimizationMethodOptimizationMethodType.md +docs/CopasiOptimizationParameter.md +docs/CopasiOptimizationParameterDataType.md +docs/CopasiOptimizationParameterParamType.md docs/Curve.md docs/CurveSelectionInfo.md docs/DataIdentifier.md @@ -54,11 +59,21 @@ docs/MathType.md docs/MathmodelRef.md docs/ModelType.md docs/N5ExportRequest.md +docs/OptJobStatus.md +docs/OptProblem.md +docs/OptProgressItem.md +docs/OptProgressReport.md +docs/OptResultSet.md +docs/OptimizationJobStatus.md +docs/OptimizationResourceApi.md docs/Origin.md +docs/ParameterDescription.md docs/Publication.md docs/PublicationInfo.md docs/PublicationResourceApi.md docs/PublishModelsRequest.md +docs/ReferenceVariable.md +docs/ReferenceVariableReferenceVariableType.md docs/SPECIALCLAIM.md docs/SampledCurve.md docs/SchedulerStatus.md @@ -97,9 +112,28 @@ docs/VariableDomain.md docs/VariableMode.md docs/VariableSpecs.md docs/VariableType.md +docs/Vcellopt.md +docs/VcelloptStatus.md docs/Version.md docs/VersionFlag.md test/__init__.py +test/test_copasi_optimization_method.py +test/test_copasi_optimization_method_optimization_method_type.py +test/test_copasi_optimization_parameter.py +test/test_copasi_optimization_parameter_data_type.py +test/test_copasi_optimization_parameter_param_type.py +test/test_opt_job_status.py +test/test_opt_problem.py +test/test_opt_progress_item.py +test/test_opt_progress_report.py +test/test_opt_result_set.py +test/test_optimization_job_status.py +test/test_optimization_resource_api.py +test/test_parameter_description.py +test/test_reference_variable.py +test/test_reference_variable_reference_variable_type.py +test/test_vcellopt.py +test/test_vcellopt_status.py tox.ini vcell_client/__init__.py vcell_client/api/__init__.py @@ -110,6 +144,7 @@ vcell_client/api/field_data_resource_api.py vcell_client/api/geometry_resource_api.py vcell_client/api/hello_world_api.py vcell_client/api/math_model_resource_api.py +vcell_client/api/optimization_resource_api.py vcell_client/api/publication_resource_api.py vcell_client/api/simulation_resource_api.py vcell_client/api/solver_resource_api.py @@ -132,6 +167,11 @@ vcell_client/models/biomodel_ref.py vcell_client/models/composite_curve.py vcell_client/models/control_point_curve.py vcell_client/models/coordinate.py +vcell_client/models/copasi_optimization_method.py +vcell_client/models/copasi_optimization_method_optimization_method_type.py +vcell_client/models/copasi_optimization_parameter.py +vcell_client/models/copasi_optimization_parameter_data_type.py +vcell_client/models/copasi_optimization_parameter_param_type.py vcell_client/models/curve.py vcell_client/models/curve_selection_info.py vcell_client/models/data_identifier.py @@ -166,10 +206,19 @@ vcell_client/models/math_type.py vcell_client/models/mathmodel_ref.py vcell_client/models/model_type.py vcell_client/models/n5_export_request.py +vcell_client/models/opt_job_status.py +vcell_client/models/opt_problem.py +vcell_client/models/opt_progress_item.py +vcell_client/models/opt_progress_report.py +vcell_client/models/opt_result_set.py +vcell_client/models/optimization_job_status.py vcell_client/models/origin.py +vcell_client/models/parameter_description.py vcell_client/models/publication.py vcell_client/models/publication_info.py vcell_client/models/publish_models_request.py +vcell_client/models/reference_variable.py +vcell_client/models/reference_variable_reference_variable_type.py vcell_client/models/sampled_curve.py vcell_client/models/scheduler_status.py vcell_client/models/simulation_execution_status_record.py @@ -204,6 +253,8 @@ vcell_client/models/variable_type.py vcell_client/models/vc_document_type.py vcell_client/models/vc_image_summary.py vcell_client/models/vc_simulation_identifier.py +vcell_client/models/vcellopt.py +vcell_client/models/vcellopt_status.py vcell_client/models/version.py vcell_client/models/version_flag.py vcell_client/py.typed diff --git a/python-restclient/README.md b/python-restclient/README.md index a7449b2810..f78801de66 100644 --- a/python-restclient/README.md +++ b/python-restclient/README.md @@ -118,6 +118,10 @@ Class | Method | HTTP request | Description *MathModelResourceApi* | [**get_summary**](docs/MathModelResourceApi.md#get_summary) | **GET** /api/v1/mathModel/summary/{id} | *MathModelResourceApi* | [**get_vcml**](docs/MathModelResourceApi.md#get_vcml) | **GET** /api/v1/mathModel/{id} | *MathModelResourceApi* | [**save_math_model**](docs/MathModelResourceApi.md#save_math_model) | **POST** /api/v1/mathModel | +*OptimizationResourceApi* | [**get_optimization_status**](docs/OptimizationResourceApi.md#get_optimization_status) | **GET** /api/v1/optimization/{optId} | Get status, progress, or results of an optimization job +*OptimizationResourceApi* | [**list_optimization_jobs**](docs/OptimizationResourceApi.md#list_optimization_jobs) | **GET** /api/v1/optimization | List optimization jobs for the authenticated user +*OptimizationResourceApi* | [**stop_optimization**](docs/OptimizationResourceApi.md#stop_optimization) | **POST** /api/v1/optimization/{optId}/stop | Stop a running optimization job +*OptimizationResourceApi* | [**submit_optimization**](docs/OptimizationResourceApi.md#submit_optimization) | **POST** /api/v1/optimization | Submit a new parameter estimation optimization job *PublicationResourceApi* | [**create_publication**](docs/PublicationResourceApi.md#create_publication) | **POST** /api/v1/publications | Create publication *PublicationResourceApi* | [**delete_publication**](docs/PublicationResourceApi.md#delete_publication) | **DELETE** /api/v1/publications/{id} | Delete publication *PublicationResourceApi* | [**get_publication_by_id**](docs/PublicationResourceApi.md#get_publication_by_id) | **GET** /api/v1/publications/{id} | Get publication by ID @@ -160,6 +164,11 @@ Class | Method | HTTP request | Description - [CompositeCurve](docs/CompositeCurve.md) - [ControlPointCurve](docs/ControlPointCurve.md) - [Coordinate](docs/Coordinate.md) + - [CopasiOptimizationMethod](docs/CopasiOptimizationMethod.md) + - [CopasiOptimizationMethodOptimizationMethodType](docs/CopasiOptimizationMethodOptimizationMethodType.md) + - [CopasiOptimizationParameter](docs/CopasiOptimizationParameter.md) + - [CopasiOptimizationParameterDataType](docs/CopasiOptimizationParameterDataType.md) + - [CopasiOptimizationParameterParamType](docs/CopasiOptimizationParameterParamType.md) - [Curve](docs/Curve.md) - [CurveSelectionInfo](docs/CurveSelectionInfo.md) - [DataIdentifier](docs/DataIdentifier.md) @@ -194,10 +203,19 @@ Class | Method | HTTP request | Description - [MathmodelRef](docs/MathmodelRef.md) - [ModelType](docs/ModelType.md) - [N5ExportRequest](docs/N5ExportRequest.md) + - [OptJobStatus](docs/OptJobStatus.md) + - [OptProblem](docs/OptProblem.md) + - [OptProgressItem](docs/OptProgressItem.md) + - [OptProgressReport](docs/OptProgressReport.md) + - [OptResultSet](docs/OptResultSet.md) + - [OptimizationJobStatus](docs/OptimizationJobStatus.md) - [Origin](docs/Origin.md) + - [ParameterDescription](docs/ParameterDescription.md) - [Publication](docs/Publication.md) - [PublicationInfo](docs/PublicationInfo.md) - [PublishModelsRequest](docs/PublishModelsRequest.md) + - [ReferenceVariable](docs/ReferenceVariable.md) + - [ReferenceVariableReferenceVariableType](docs/ReferenceVariableReferenceVariableType.md) - [SPECIALCLAIM](docs/SPECIALCLAIM.md) - [SampledCurve](docs/SampledCurve.md) - [SchedulerStatus](docs/SchedulerStatus.md) @@ -232,6 +250,8 @@ Class | Method | HTTP request | Description - [VariableMode](docs/VariableMode.md) - [VariableSpecs](docs/VariableSpecs.md) - [VariableType](docs/VariableType.md) + - [Vcellopt](docs/Vcellopt.md) + - [VcelloptStatus](docs/VcelloptStatus.md) - [Version](docs/Version.md) - [VersionFlag](docs/VersionFlag.md) diff --git a/python-restclient/docs/CopasiOptimizationMethod.md b/python-restclient/docs/CopasiOptimizationMethod.md new file mode 100644 index 0000000000..7edd932b14 --- /dev/null +++ b/python-restclient/docs/CopasiOptimizationMethod.md @@ -0,0 +1,29 @@ +# CopasiOptimizationMethod + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**optimization_method_type** | [**CopasiOptimizationMethodOptimizationMethodType**](CopasiOptimizationMethodOptimizationMethodType.md) | | [optional] +**optimization_parameter** | [**List[CopasiOptimizationParameter]**](CopasiOptimizationParameter.md) | | [optional] + +## Example + +```python +from vcell_client.models.copasi_optimization_method import CopasiOptimizationMethod + +# TODO update the JSON string below +json = "{}" +# create an instance of CopasiOptimizationMethod from a JSON string +copasi_optimization_method_instance = CopasiOptimizationMethod.from_json(json) +# print the JSON string representation of the object +print CopasiOptimizationMethod.to_json() + +# convert the object into a dict +copasi_optimization_method_dict = copasi_optimization_method_instance.to_dict() +# create an instance of CopasiOptimizationMethod from a dict +copasi_optimization_method_form_dict = copasi_optimization_method.from_dict(copasi_optimization_method_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/CopasiOptimizationMethodOptimizationMethodType.md b/python-restclient/docs/CopasiOptimizationMethodOptimizationMethodType.md new file mode 100644 index 0000000000..44fdccf71b --- /dev/null +++ b/python-restclient/docs/CopasiOptimizationMethodOptimizationMethodType.md @@ -0,0 +1,10 @@ +# CopasiOptimizationMethodOptimizationMethodType + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/CopasiOptimizationParameter.md b/python-restclient/docs/CopasiOptimizationParameter.md new file mode 100644 index 0000000000..c3b7f568a3 --- /dev/null +++ b/python-restclient/docs/CopasiOptimizationParameter.md @@ -0,0 +1,30 @@ +# CopasiOptimizationParameter + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**data_type** | [**CopasiOptimizationParameterDataType**](CopasiOptimizationParameterDataType.md) | | [optional] +**param_type** | [**CopasiOptimizationParameterParamType**](CopasiOptimizationParameterParamType.md) | | [optional] +**value** | **float** | | [optional] + +## Example + +```python +from vcell_client.models.copasi_optimization_parameter import CopasiOptimizationParameter + +# TODO update the JSON string below +json = "{}" +# create an instance of CopasiOptimizationParameter from a JSON string +copasi_optimization_parameter_instance = CopasiOptimizationParameter.from_json(json) +# print the JSON string representation of the object +print CopasiOptimizationParameter.to_json() + +# convert the object into a dict +copasi_optimization_parameter_dict = copasi_optimization_parameter_instance.to_dict() +# create an instance of CopasiOptimizationParameter from a dict +copasi_optimization_parameter_form_dict = copasi_optimization_parameter.from_dict(copasi_optimization_parameter_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/CopasiOptimizationParameterDataType.md b/python-restclient/docs/CopasiOptimizationParameterDataType.md new file mode 100644 index 0000000000..4181ed8bff --- /dev/null +++ b/python-restclient/docs/CopasiOptimizationParameterDataType.md @@ -0,0 +1,10 @@ +# CopasiOptimizationParameterDataType + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/CopasiOptimizationParameterParamType.md b/python-restclient/docs/CopasiOptimizationParameterParamType.md new file mode 100644 index 0000000000..a29826ad40 --- /dev/null +++ b/python-restclient/docs/CopasiOptimizationParameterParamType.md @@ -0,0 +1,10 @@ +# CopasiOptimizationParameterParamType + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/OptJobStatus.md b/python-restclient/docs/OptJobStatus.md new file mode 100644 index 0000000000..887d86b6c3 --- /dev/null +++ b/python-restclient/docs/OptJobStatus.md @@ -0,0 +1,10 @@ +# OptJobStatus + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/OptProblem.md b/python-restclient/docs/OptProblem.md new file mode 100644 index 0000000000..f1b38c2d39 --- /dev/null +++ b/python-restclient/docs/OptProblem.md @@ -0,0 +1,33 @@ +# OptProblem + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**copasi_optimization_method** | [**CopasiOptimizationMethod**](CopasiOptimizationMethod.md) | | [optional] +**data_set** | **List[List[float]]** | | [optional] +**math_model_sbml_contents** | **str** | | [optional] +**number_of_optimization_runs** | **int** | | [optional] +**parameter_description_list** | [**List[ParameterDescription]**](ParameterDescription.md) | | [optional] +**reference_variable** | [**List[ReferenceVariable]**](ReferenceVariable.md) | | [optional] + +## Example + +```python +from vcell_client.models.opt_problem import OptProblem + +# TODO update the JSON string below +json = "{}" +# create an instance of OptProblem from a JSON string +opt_problem_instance = OptProblem.from_json(json) +# print the JSON string representation of the object +print OptProblem.to_json() + +# convert the object into a dict +opt_problem_dict = opt_problem_instance.to_dict() +# create an instance of OptProblem from a dict +opt_problem_form_dict = opt_problem.from_dict(opt_problem_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/OptProgressItem.md b/python-restclient/docs/OptProgressItem.md new file mode 100644 index 0000000000..f3325a6d5c --- /dev/null +++ b/python-restclient/docs/OptProgressItem.md @@ -0,0 +1,29 @@ +# OptProgressItem + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**num_function_evaluations** | **int** | | [optional] +**obj_func_value** | **float** | | [optional] + +## Example + +```python +from vcell_client.models.opt_progress_item import OptProgressItem + +# TODO update the JSON string below +json = "{}" +# create an instance of OptProgressItem from a JSON string +opt_progress_item_instance = OptProgressItem.from_json(json) +# print the JSON string representation of the object +print OptProgressItem.to_json() + +# convert the object into a dict +opt_progress_item_dict = opt_progress_item_instance.to_dict() +# create an instance of OptProgressItem from a dict +opt_progress_item_form_dict = opt_progress_item.from_dict(opt_progress_item_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/OptProgressReport.md b/python-restclient/docs/OptProgressReport.md new file mode 100644 index 0000000000..581fefd79f --- /dev/null +++ b/python-restclient/docs/OptProgressReport.md @@ -0,0 +1,29 @@ +# OptProgressReport + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**best_param_values** | **Dict[str, float]** | | [optional] +**progress_items** | [**List[OptProgressItem]**](OptProgressItem.md) | | [optional] + +## Example + +```python +from vcell_client.models.opt_progress_report import OptProgressReport + +# TODO update the JSON string below +json = "{}" +# create an instance of OptProgressReport from a JSON string +opt_progress_report_instance = OptProgressReport.from_json(json) +# print the JSON string representation of the object +print OptProgressReport.to_json() + +# convert the object into a dict +opt_progress_report_dict = opt_progress_report_instance.to_dict() +# create an instance of OptProgressReport from a dict +opt_progress_report_form_dict = opt_progress_report.from_dict(opt_progress_report_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/OptResultSet.md b/python-restclient/docs/OptResultSet.md new file mode 100644 index 0000000000..2fc3b26f5e --- /dev/null +++ b/python-restclient/docs/OptResultSet.md @@ -0,0 +1,31 @@ +# OptResultSet + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**num_function_evaluations** | **int** | | [optional] +**objective_function** | **float** | | [optional] +**opt_parameter_values** | **Dict[str, float]** | | [optional] +**opt_progress_report** | [**OptProgressReport**](OptProgressReport.md) | | [optional] + +## Example + +```python +from vcell_client.models.opt_result_set import OptResultSet + +# TODO update the JSON string below +json = "{}" +# create an instance of OptResultSet from a JSON string +opt_result_set_instance = OptResultSet.from_json(json) +# print the JSON string representation of the object +print OptResultSet.to_json() + +# convert the object into a dict +opt_result_set_dict = opt_result_set_instance.to_dict() +# create an instance of OptResultSet from a dict +opt_result_set_form_dict = opt_result_set.from_dict(opt_result_set_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/OptimizationJobStatus.md b/python-restclient/docs/OptimizationJobStatus.md new file mode 100644 index 0000000000..778d59eecd --- /dev/null +++ b/python-restclient/docs/OptimizationJobStatus.md @@ -0,0 +1,33 @@ +# OptimizationJobStatus + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | | [optional] +**status** | [**OptJobStatus**](OptJobStatus.md) | | [optional] +**status_message** | **str** | | [optional] +**htc_job_id** | **str** | | [optional] +**progress_report** | [**OptProgressReport**](OptProgressReport.md) | | [optional] +**results** | [**Vcellopt**](Vcellopt.md) | | [optional] + +## Example + +```python +from vcell_client.models.optimization_job_status import OptimizationJobStatus + +# TODO update the JSON string below +json = "{}" +# create an instance of OptimizationJobStatus from a JSON string +optimization_job_status_instance = OptimizationJobStatus.from_json(json) +# print the JSON string representation of the object +print OptimizationJobStatus.to_json() + +# convert the object into a dict +optimization_job_status_dict = optimization_job_status_instance.to_dict() +# create an instance of OptimizationJobStatus from a dict +optimization_job_status_form_dict = optimization_job_status.from_dict(optimization_job_status_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/OptimizationResourceApi.md b/python-restclient/docs/OptimizationResourceApi.md new file mode 100644 index 0000000000..12b9f29542 --- /dev/null +++ b/python-restclient/docs/OptimizationResourceApi.md @@ -0,0 +1,299 @@ +# vcell_client.OptimizationResourceApi + +All URIs are relative to *https://vcell.cam.uchc.edu* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**get_optimization_status**](OptimizationResourceApi.md#get_optimization_status) | **GET** /api/v1/optimization/{optId} | Get status, progress, or results of an optimization job +[**list_optimization_jobs**](OptimizationResourceApi.md#list_optimization_jobs) | **GET** /api/v1/optimization | List optimization jobs for the authenticated user +[**stop_optimization**](OptimizationResourceApi.md#stop_optimization) | **POST** /api/v1/optimization/{optId}/stop | Stop a running optimization job +[**submit_optimization**](OptimizationResourceApi.md#submit_optimization) | **POST** /api/v1/optimization | Submit a new parameter estimation optimization job + + +# **get_optimization_status** +> OptimizationJobStatus get_optimization_status(opt_id) + +Get status, progress, or results of an optimization job + +### Example + +```python +import time +import os +import vcell_client +from vcell_client.models.optimization_job_status import OptimizationJobStatus +from vcell_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://vcell.cam.uchc.edu +# See configuration.py for a list of all supported configuration parameters. +configuration = vcell_client.Configuration( + host = "https://vcell.cam.uchc.edu" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Enter a context with an instance of the API client +with vcell_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = vcell_client.OptimizationResourceApi(api_client) + opt_id = 56 # int | + + try: + # Get status, progress, or results of an optimization job + api_response = api_instance.get_optimization_status(opt_id) + print("The response of OptimizationResourceApi->get_optimization_status:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling OptimizationResourceApi->get_optimization_status: %s\n" % e) +``` + + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **opt_id** | **int**| | + +### Return type + +[**OptimizationJobStatus**](OptimizationJobStatus.md) + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**401** | Not Authenticated | - | +**403** | Not Allowed | - | +**404** | Not found | - | +**500** | Data Access Exception | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **list_optimization_jobs** +> List[OptimizationJobStatus] list_optimization_jobs() + +List optimization jobs for the authenticated user + +### Example + +```python +import time +import os +import vcell_client +from vcell_client.models.optimization_job_status import OptimizationJobStatus +from vcell_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://vcell.cam.uchc.edu +# See configuration.py for a list of all supported configuration parameters. +configuration = vcell_client.Configuration( + host = "https://vcell.cam.uchc.edu" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Enter a context with an instance of the API client +with vcell_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = vcell_client.OptimizationResourceApi(api_client) + + try: + # List optimization jobs for the authenticated user + api_response = api_instance.list_optimization_jobs() + print("The response of OptimizationResourceApi->list_optimization_jobs:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling OptimizationResourceApi->list_optimization_jobs: %s\n" % e) +``` + + + +### Parameters +This endpoint does not need any parameter. + +### Return type + +[**List[OptimizationJobStatus]**](OptimizationJobStatus.md) + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**401** | Not Authenticated | - | +**403** | Not Allowed | - | +**500** | Data Access Exception | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **stop_optimization** +> OptimizationJobStatus stop_optimization(opt_id) + +Stop a running optimization job + +### Example + +```python +import time +import os +import vcell_client +from vcell_client.models.optimization_job_status import OptimizationJobStatus +from vcell_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://vcell.cam.uchc.edu +# See configuration.py for a list of all supported configuration parameters. +configuration = vcell_client.Configuration( + host = "https://vcell.cam.uchc.edu" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Enter a context with an instance of the API client +with vcell_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = vcell_client.OptimizationResourceApi(api_client) + opt_id = 56 # int | + + try: + # Stop a running optimization job + api_response = api_instance.stop_optimization(opt_id) + print("The response of OptimizationResourceApi->stop_optimization:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling OptimizationResourceApi->stop_optimization: %s\n" % e) +``` + + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **opt_id** | **int**| | + +### Return type + +[**OptimizationJobStatus**](OptimizationJobStatus.md) + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**401** | Not Authenticated | - | +**403** | Not Allowed | - | +**404** | Not found | - | +**500** | Data Access Exception | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **submit_optimization** +> OptimizationJobStatus submit_optimization(opt_problem=opt_problem) + +Submit a new parameter estimation optimization job + +### Example + +```python +import time +import os +import vcell_client +from vcell_client.models.opt_problem import OptProblem +from vcell_client.models.optimization_job_status import OptimizationJobStatus +from vcell_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://vcell.cam.uchc.edu +# See configuration.py for a list of all supported configuration parameters. +configuration = vcell_client.Configuration( + host = "https://vcell.cam.uchc.edu" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Enter a context with an instance of the API client +with vcell_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = vcell_client.OptimizationResourceApi(api_client) + opt_problem = vcell_client.OptProblem() # OptProblem | (optional) + + try: + # Submit a new parameter estimation optimization job + api_response = api_instance.submit_optimization(opt_problem=opt_problem) + print("The response of OptimizationResourceApi->submit_optimization:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling OptimizationResourceApi->submit_optimization: %s\n" % e) +``` + + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **opt_problem** | [**OptProblem**](OptProblem.md)| | [optional] + +### Return type + +[**OptimizationJobStatus**](OptimizationJobStatus.md) + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**401** | Not Authenticated | - | +**403** | Not Allowed | - | +**500** | Data Access Exception | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/python-restclient/docs/ParameterDescription.md b/python-restclient/docs/ParameterDescription.md new file mode 100644 index 0000000000..d06c02a706 --- /dev/null +++ b/python-restclient/docs/ParameterDescription.md @@ -0,0 +1,32 @@ +# ParameterDescription + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**initial_value** | **float** | | [optional] +**max_value** | **float** | | [optional] +**min_value** | **float** | | [optional] +**name** | **str** | | [optional] +**scale** | **float** | | [optional] + +## Example + +```python +from vcell_client.models.parameter_description import ParameterDescription + +# TODO update the JSON string below +json = "{}" +# create an instance of ParameterDescription from a JSON string +parameter_description_instance = ParameterDescription.from_json(json) +# print the JSON string representation of the object +print ParameterDescription.to_json() + +# convert the object into a dict +parameter_description_dict = parameter_description_instance.to_dict() +# create an instance of ParameterDescription from a dict +parameter_description_form_dict = parameter_description.from_dict(parameter_description_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/ReferenceVariable.md b/python-restclient/docs/ReferenceVariable.md new file mode 100644 index 0000000000..17bbaed75d --- /dev/null +++ b/python-restclient/docs/ReferenceVariable.md @@ -0,0 +1,29 @@ +# ReferenceVariable + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**reference_variable_type** | [**ReferenceVariableReferenceVariableType**](ReferenceVariableReferenceVariableType.md) | | [optional] +**var_name** | **str** | | [optional] + +## Example + +```python +from vcell_client.models.reference_variable import ReferenceVariable + +# TODO update the JSON string below +json = "{}" +# create an instance of ReferenceVariable from a JSON string +reference_variable_instance = ReferenceVariable.from_json(json) +# print the JSON string representation of the object +print ReferenceVariable.to_json() + +# convert the object into a dict +reference_variable_dict = reference_variable_instance.to_dict() +# create an instance of ReferenceVariable from a dict +reference_variable_form_dict = reference_variable.from_dict(reference_variable_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/ReferenceVariableReferenceVariableType.md b/python-restclient/docs/ReferenceVariableReferenceVariableType.md new file mode 100644 index 0000000000..d008ebc5f7 --- /dev/null +++ b/python-restclient/docs/ReferenceVariableReferenceVariableType.md @@ -0,0 +1,10 @@ +# ReferenceVariableReferenceVariableType + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/Vcellopt.md b/python-restclient/docs/Vcellopt.md new file mode 100644 index 0000000000..d996285ea1 --- /dev/null +++ b/python-restclient/docs/Vcellopt.md @@ -0,0 +1,31 @@ +# Vcellopt + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**opt_problem** | [**OptProblem**](OptProblem.md) | | [optional] +**opt_result_set** | [**OptResultSet**](OptResultSet.md) | | [optional] +**status** | [**VcelloptStatus**](VcelloptStatus.md) | | [optional] +**status_message** | **str** | | [optional] + +## Example + +```python +from vcell_client.models.vcellopt import Vcellopt + +# TODO update the JSON string below +json = "{}" +# create an instance of Vcellopt from a JSON string +vcellopt_instance = Vcellopt.from_json(json) +# print the JSON string representation of the object +print Vcellopt.to_json() + +# convert the object into a dict +vcellopt_dict = vcellopt_instance.to_dict() +# create an instance of Vcellopt from a dict +vcellopt_form_dict = vcellopt.from_dict(vcellopt_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/VcelloptStatus.md b/python-restclient/docs/VcelloptStatus.md new file mode 100644 index 0000000000..ddd8b79432 --- /dev/null +++ b/python-restclient/docs/VcelloptStatus.md @@ -0,0 +1,10 @@ +# VcelloptStatus + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/test/test_copasi_optimization_method.py b/python-restclient/test/test_copasi_optimization_method.py new file mode 100644 index 0000000000..fee138aac0 --- /dev/null +++ b/python-restclient/test/test_copasi_optimization_method.py @@ -0,0 +1,59 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.copasi_optimization_method import CopasiOptimizationMethod + +class TestCopasiOptimizationMethod(unittest.TestCase): + """CopasiOptimizationMethod unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> CopasiOptimizationMethod: + """Test CopasiOptimizationMethod + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `CopasiOptimizationMethod` + """ + model = CopasiOptimizationMethod() + if include_optional: + return CopasiOptimizationMethod( + optimization_method_type = 'SRES', + optimization_parameter = [ + vcell_client.models.copasi_optimization_parameter.CopasiOptimizationParameter( + data_type = 'double', + param_type = 'coolingFactor', + value = 1.337, ) + ] + ) + else: + return CopasiOptimizationMethod( + ) + """ + + def testCopasiOptimizationMethod(self): + """Test CopasiOptimizationMethod""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_copasi_optimization_method_optimization_method_type.py b/python-restclient/test/test_copasi_optimization_method_optimization_method_type.py new file mode 100644 index 0000000000..fa86dd5054 --- /dev/null +++ b/python-restclient/test/test_copasi_optimization_method_optimization_method_type.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.copasi_optimization_method_optimization_method_type import CopasiOptimizationMethodOptimizationMethodType + +class TestCopasiOptimizationMethodOptimizationMethodType(unittest.TestCase): + """CopasiOptimizationMethodOptimizationMethodType unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testCopasiOptimizationMethodOptimizationMethodType(self): + """Test CopasiOptimizationMethodOptimizationMethodType""" + # inst = CopasiOptimizationMethodOptimizationMethodType() + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_copasi_optimization_parameter.py b/python-restclient/test/test_copasi_optimization_parameter.py new file mode 100644 index 0000000000..77b93d27fa --- /dev/null +++ b/python-restclient/test/test_copasi_optimization_parameter.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.copasi_optimization_parameter import CopasiOptimizationParameter + +class TestCopasiOptimizationParameter(unittest.TestCase): + """CopasiOptimizationParameter unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> CopasiOptimizationParameter: + """Test CopasiOptimizationParameter + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `CopasiOptimizationParameter` + """ + model = CopasiOptimizationParameter() + if include_optional: + return CopasiOptimizationParameter( + data_type = 'double', + param_type = 'coolingFactor', + value = 1.337 + ) + else: + return CopasiOptimizationParameter( + ) + """ + + def testCopasiOptimizationParameter(self): + """Test CopasiOptimizationParameter""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_copasi_optimization_parameter_data_type.py b/python-restclient/test/test_copasi_optimization_parameter_data_type.py new file mode 100644 index 0000000000..b21a2dc0d9 --- /dev/null +++ b/python-restclient/test/test_copasi_optimization_parameter_data_type.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.copasi_optimization_parameter_data_type import CopasiOptimizationParameterDataType + +class TestCopasiOptimizationParameterDataType(unittest.TestCase): + """CopasiOptimizationParameterDataType unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testCopasiOptimizationParameterDataType(self): + """Test CopasiOptimizationParameterDataType""" + # inst = CopasiOptimizationParameterDataType() + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_copasi_optimization_parameter_param_type.py b/python-restclient/test/test_copasi_optimization_parameter_param_type.py new file mode 100644 index 0000000000..b2e8955453 --- /dev/null +++ b/python-restclient/test/test_copasi_optimization_parameter_param_type.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.copasi_optimization_parameter_param_type import CopasiOptimizationParameterParamType + +class TestCopasiOptimizationParameterParamType(unittest.TestCase): + """CopasiOptimizationParameterParamType unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testCopasiOptimizationParameterParamType(self): + """Test CopasiOptimizationParameterParamType""" + # inst = CopasiOptimizationParameterParamType() + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_opt_job_status.py b/python-restclient/test/test_opt_job_status.py new file mode 100644 index 0000000000..f02f0b78a1 --- /dev/null +++ b/python-restclient/test/test_opt_job_status.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.opt_job_status import OptJobStatus + +class TestOptJobStatus(unittest.TestCase): + """OptJobStatus unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testOptJobStatus(self): + """Test OptJobStatus""" + # inst = OptJobStatus() + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_opt_problem.py b/python-restclient/test/test_opt_problem.py new file mode 100644 index 0000000000..a4164b94e7 --- /dev/null +++ b/python-restclient/test/test_opt_problem.py @@ -0,0 +1,80 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.opt_problem import OptProblem + +class TestOptProblem(unittest.TestCase): + """OptProblem unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> OptProblem: + """Test OptProblem + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `OptProblem` + """ + model = OptProblem() + if include_optional: + return OptProblem( + copasi_optimization_method = vcell_client.models.copasi_optimization_method.CopasiOptimizationMethod( + optimization_method_type = 'SRES', + optimization_parameter = [ + vcell_client.models.copasi_optimization_parameter.CopasiOptimizationParameter( + data_type = 'double', + param_type = 'coolingFactor', + value = 1.337, ) + ], ), + data_set = [ + [ + 1.337 + ] + ], + math_model_sbml_contents = '', + number_of_optimization_runs = 56, + parameter_description_list = [ + vcell_client.models.parameter_description.ParameterDescription( + initial_value = 1.337, + max_value = 1.337, + min_value = 1.337, + name = '', + scale = 1.337, ) + ], + reference_variable = [ + vcell_client.models.reference_variable.ReferenceVariable( + reference_variable_type = 'dependent', + var_name = '', ) + ] + ) + else: + return OptProblem( + ) + """ + + def testOptProblem(self): + """Test OptProblem""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_opt_progress_item.py b/python-restclient/test/test_opt_progress_item.py new file mode 100644 index 0000000000..c56fb1a406 --- /dev/null +++ b/python-restclient/test/test_opt_progress_item.py @@ -0,0 +1,54 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.opt_progress_item import OptProgressItem + +class TestOptProgressItem(unittest.TestCase): + """OptProgressItem unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> OptProgressItem: + """Test OptProgressItem + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `OptProgressItem` + """ + model = OptProgressItem() + if include_optional: + return OptProgressItem( + num_function_evaluations = 56, + obj_func_value = 1.337 + ) + else: + return OptProgressItem( + ) + """ + + def testOptProgressItem(self): + """Test OptProgressItem""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_opt_progress_report.py b/python-restclient/test/test_opt_progress_report.py new file mode 100644 index 0000000000..225a57d777 --- /dev/null +++ b/python-restclient/test/test_opt_progress_report.py @@ -0,0 +1,60 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.opt_progress_report import OptProgressReport + +class TestOptProgressReport(unittest.TestCase): + """OptProgressReport unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> OptProgressReport: + """Test OptProgressReport + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `OptProgressReport` + """ + model = OptProgressReport() + if include_optional: + return OptProgressReport( + best_param_values = { + 'key' : 1.337 + }, + progress_items = [ + vcell_client.models.opt_progress_item.OptProgressItem( + num_function_evaluations = 56, + obj_func_value = 1.337, ) + ] + ) + else: + return OptProgressReport( + ) + """ + + def testOptProgressReport(self): + """Test OptProgressReport""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_opt_result_set.py b/python-restclient/test/test_opt_result_set.py new file mode 100644 index 0000000000..15dbb9cbf0 --- /dev/null +++ b/python-restclient/test/test_opt_result_set.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.opt_result_set import OptResultSet + +class TestOptResultSet(unittest.TestCase): + """OptResultSet unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> OptResultSet: + """Test OptResultSet + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `OptResultSet` + """ + model = OptResultSet() + if include_optional: + return OptResultSet( + num_function_evaluations = 56, + objective_function = 1.337, + opt_parameter_values = { + 'key' : 1.337 + }, + opt_progress_report = vcell_client.models.opt_progress_report.OptProgressReport( + best_param_values = { + 'key' : 1.337 + }, + progress_items = [ + vcell_client.models.opt_progress_item.OptProgressItem( + num_function_evaluations = 56, + obj_func_value = 1.337, ) + ], ) + ) + else: + return OptResultSet( + ) + """ + + def testOptResultSet(self): + """Test OptResultSet""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_optimization_job_status.py b/python-restclient/test/test_optimization_job_status.py new file mode 100644 index 0000000000..01b8759446 --- /dev/null +++ b/python-restclient/test/test_optimization_job_status.py @@ -0,0 +1,112 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.optimization_job_status import OptimizationJobStatus + +class TestOptimizationJobStatus(unittest.TestCase): + """OptimizationJobStatus unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> OptimizationJobStatus: + """Test OptimizationJobStatus + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `OptimizationJobStatus` + """ + model = OptimizationJobStatus() + if include_optional: + return OptimizationJobStatus( + id = '', + status = 'SUBMITTED', + status_message = '', + htc_job_id = '', + progress_report = vcell_client.models.opt_progress_report.OptProgressReport( + best_param_values = { + 'key' : 1.337 + }, + progress_items = [ + vcell_client.models.opt_progress_item.OptProgressItem( + num_function_evaluations = 56, + obj_func_value = 1.337, ) + ], ), + results = vcell_client.models.vcellopt.Vcellopt( + opt_problem = vcell_client.models.opt_problem.OptProblem( + copasi_optimization_method = vcell_client.models.copasi_optimization_method.CopasiOptimizationMethod( + optimization_method_type = 'SRES', + optimization_parameter = [ + vcell_client.models.copasi_optimization_parameter.CopasiOptimizationParameter( + data_type = 'double', + param_type = 'coolingFactor', + value = 1.337, ) + ], ), + data_set = [ + [ + 1.337 + ] + ], + math_model_sbml_contents = '', + number_of_optimization_runs = 56, + parameter_description_list = [ + vcell_client.models.parameter_description.ParameterDescription( + initial_value = 1.337, + max_value = 1.337, + min_value = 1.337, + name = '', + scale = 1.337, ) + ], + reference_variable = [ + vcell_client.models.reference_variable.ReferenceVariable( + reference_variable_type = 'dependent', + var_name = '', ) + ], ), + opt_result_set = vcell_client.models.opt_result_set.OptResultSet( + num_function_evaluations = 56, + objective_function = 1.337, + opt_parameter_values = { + 'key' : 1.337 + }, + opt_progress_report = vcell_client.models.opt_progress_report.OptProgressReport( + best_param_values = { + 'key' : 1.337 + }, + progress_items = [ + vcell_client.models.opt_progress_item.OptProgressItem( + num_function_evaluations = 56, + obj_func_value = 1.337, ) + ], ), ), + status = 'complete', + status_message = '', ) + ) + else: + return OptimizationJobStatus( + ) + """ + + def testOptimizationJobStatus(self): + """Test OptimizationJobStatus""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_optimization_resource_api.py b/python-restclient/test/test_optimization_resource_api.py new file mode 100644 index 0000000000..18048bffef --- /dev/null +++ b/python-restclient/test/test_optimization_resource_api.py @@ -0,0 +1,60 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from vcell_client.api.optimization_resource_api import OptimizationResourceApi + + +class TestOptimizationResourceApi(unittest.TestCase): + """OptimizationResourceApi unit test stubs""" + + def setUp(self) -> None: + self.api = OptimizationResourceApi() + + def tearDown(self) -> None: + pass + + def test_get_optimization_status(self) -> None: + """Test case for get_optimization_status + + Get status, progress, or results of an optimization job + """ + pass + + def test_list_optimization_jobs(self) -> None: + """Test case for list_optimization_jobs + + List optimization jobs for the authenticated user + """ + pass + + def test_stop_optimization(self) -> None: + """Test case for stop_optimization + + Stop a running optimization job + """ + pass + + def test_submit_optimization(self) -> None: + """Test case for submit_optimization + + Submit a new parameter estimation optimization job + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_parameter_description.py b/python-restclient/test/test_parameter_description.py new file mode 100644 index 0000000000..33509cfc74 --- /dev/null +++ b/python-restclient/test/test_parameter_description.py @@ -0,0 +1,57 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.parameter_description import ParameterDescription + +class TestParameterDescription(unittest.TestCase): + """ParameterDescription unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> ParameterDescription: + """Test ParameterDescription + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `ParameterDescription` + """ + model = ParameterDescription() + if include_optional: + return ParameterDescription( + initial_value = 1.337, + max_value = 1.337, + min_value = 1.337, + name = '', + scale = 1.337 + ) + else: + return ParameterDescription( + ) + """ + + def testParameterDescription(self): + """Test ParameterDescription""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_reference_variable.py b/python-restclient/test/test_reference_variable.py new file mode 100644 index 0000000000..1a7398f026 --- /dev/null +++ b/python-restclient/test/test_reference_variable.py @@ -0,0 +1,54 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.reference_variable import ReferenceVariable + +class TestReferenceVariable(unittest.TestCase): + """ReferenceVariable unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> ReferenceVariable: + """Test ReferenceVariable + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `ReferenceVariable` + """ + model = ReferenceVariable() + if include_optional: + return ReferenceVariable( + reference_variable_type = 'dependent', + var_name = '' + ) + else: + return ReferenceVariable( + ) + """ + + def testReferenceVariable(self): + """Test ReferenceVariable""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_reference_variable_reference_variable_type.py b/python-restclient/test/test_reference_variable_reference_variable_type.py new file mode 100644 index 0000000000..65c002a603 --- /dev/null +++ b/python-restclient/test/test_reference_variable_reference_variable_type.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.reference_variable_reference_variable_type import ReferenceVariableReferenceVariableType + +class TestReferenceVariableReferenceVariableType(unittest.TestCase): + """ReferenceVariableReferenceVariableType unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testReferenceVariableReferenceVariableType(self): + """Test ReferenceVariableReferenceVariableType""" + # inst = ReferenceVariableReferenceVariableType() + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_vcellopt.py b/python-restclient/test/test_vcellopt.py new file mode 100644 index 0000000000..b9d7f337d8 --- /dev/null +++ b/python-restclient/test/test_vcellopt.py @@ -0,0 +1,98 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.vcellopt import Vcellopt + +class TestVcellopt(unittest.TestCase): + """Vcellopt unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> Vcellopt: + """Test Vcellopt + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `Vcellopt` + """ + model = Vcellopt() + if include_optional: + return Vcellopt( + opt_problem = vcell_client.models.opt_problem.OptProblem( + copasi_optimization_method = vcell_client.models.copasi_optimization_method.CopasiOptimizationMethod( + optimization_method_type = 'SRES', + optimization_parameter = [ + vcell_client.models.copasi_optimization_parameter.CopasiOptimizationParameter( + data_type = 'double', + param_type = 'coolingFactor', + value = 1.337, ) + ], ), + data_set = [ + [ + 1.337 + ] + ], + math_model_sbml_contents = '', + number_of_optimization_runs = 56, + parameter_description_list = [ + vcell_client.models.parameter_description.ParameterDescription( + initial_value = 1.337, + max_value = 1.337, + min_value = 1.337, + name = '', + scale = 1.337, ) + ], + reference_variable = [ + vcell_client.models.reference_variable.ReferenceVariable( + reference_variable_type = 'dependent', + var_name = '', ) + ], ), + opt_result_set = vcell_client.models.opt_result_set.OptResultSet( + num_function_evaluations = 56, + objective_function = 1.337, + opt_parameter_values = { + 'key' : 1.337 + }, + opt_progress_report = vcell_client.models.opt_progress_report.OptProgressReport( + best_param_values = { + 'key' : 1.337 + }, + progress_items = [ + vcell_client.models.opt_progress_item.OptProgressItem( + num_function_evaluations = 56, + obj_func_value = 1.337, ) + ], ), ), + status = 'complete', + status_message = '' + ) + else: + return Vcellopt( + ) + """ + + def testVcellopt(self): + """Test Vcellopt""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_vcellopt_status.py b/python-restclient/test/test_vcellopt_status.py new file mode 100644 index 0000000000..19abdd05f1 --- /dev/null +++ b/python-restclient/test/test_vcellopt_status.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.vcellopt_status import VcelloptStatus + +class TestVcelloptStatus(unittest.TestCase): + """VcelloptStatus unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testVcelloptStatus(self): + """Test VcelloptStatus""" + # inst = VcelloptStatus() + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/vcell_client/__init__.py b/python-restclient/vcell_client/__init__.py index 97b6e5257a..e0658f3265 100644 --- a/python-restclient/vcell_client/__init__.py +++ b/python-restclient/vcell_client/__init__.py @@ -25,6 +25,7 @@ from vcell_client.api.geometry_resource_api import GeometryResourceApi from vcell_client.api.hello_world_api import HelloWorldApi from vcell_client.api.math_model_resource_api import MathModelResourceApi +from vcell_client.api.optimization_resource_api import OptimizationResourceApi from vcell_client.api.publication_resource_api import PublicationResourceApi from vcell_client.api.simulation_resource_api import SimulationResourceApi from vcell_client.api.solver_resource_api import SolverResourceApi @@ -55,6 +56,11 @@ from vcell_client.models.composite_curve import CompositeCurve from vcell_client.models.control_point_curve import ControlPointCurve from vcell_client.models.coordinate import Coordinate +from vcell_client.models.copasi_optimization_method import CopasiOptimizationMethod +from vcell_client.models.copasi_optimization_method_optimization_method_type import CopasiOptimizationMethodOptimizationMethodType +from vcell_client.models.copasi_optimization_parameter import CopasiOptimizationParameter +from vcell_client.models.copasi_optimization_parameter_data_type import CopasiOptimizationParameterDataType +from vcell_client.models.copasi_optimization_parameter_param_type import CopasiOptimizationParameterParamType from vcell_client.models.curve import Curve from vcell_client.models.curve_selection_info import CurveSelectionInfo from vcell_client.models.data_identifier import DataIdentifier @@ -89,10 +95,19 @@ from vcell_client.models.mathmodel_ref import MathmodelRef from vcell_client.models.model_type import ModelType from vcell_client.models.n5_export_request import N5ExportRequest +from vcell_client.models.opt_job_status import OptJobStatus +from vcell_client.models.opt_problem import OptProblem +from vcell_client.models.opt_progress_item import OptProgressItem +from vcell_client.models.opt_progress_report import OptProgressReport +from vcell_client.models.opt_result_set import OptResultSet +from vcell_client.models.optimization_job_status import OptimizationJobStatus from vcell_client.models.origin import Origin +from vcell_client.models.parameter_description import ParameterDescription from vcell_client.models.publication import Publication from vcell_client.models.publication_info import PublicationInfo from vcell_client.models.publish_models_request import PublishModelsRequest +from vcell_client.models.reference_variable import ReferenceVariable +from vcell_client.models.reference_variable_reference_variable_type import ReferenceVariableReferenceVariableType from vcell_client.models.specialclaim import SPECIALCLAIM from vcell_client.models.sampled_curve import SampledCurve from vcell_client.models.scheduler_status import SchedulerStatus @@ -127,5 +142,7 @@ from vcell_client.models.variable_mode import VariableMode from vcell_client.models.variable_specs import VariableSpecs from vcell_client.models.variable_type import VariableType +from vcell_client.models.vcellopt import Vcellopt +from vcell_client.models.vcellopt_status import VcelloptStatus from vcell_client.models.version import Version from vcell_client.models.version_flag import VersionFlag diff --git a/python-restclient/vcell_client/api/__init__.py b/python-restclient/vcell_client/api/__init__.py index f4e375f974..cd1b4be610 100644 --- a/python-restclient/vcell_client/api/__init__.py +++ b/python-restclient/vcell_client/api/__init__.py @@ -8,6 +8,7 @@ from vcell_client.api.geometry_resource_api import GeometryResourceApi from vcell_client.api.hello_world_api import HelloWorldApi from vcell_client.api.math_model_resource_api import MathModelResourceApi +from vcell_client.api.optimization_resource_api import OptimizationResourceApi from vcell_client.api.publication_resource_api import PublicationResourceApi from vcell_client.api.simulation_resource_api import SimulationResourceApi from vcell_client.api.solver_resource_api import SolverResourceApi diff --git a/python-restclient/vcell_client/api/optimization_resource_api.py b/python-restclient/vcell_client/api/optimization_resource_api.py new file mode 100644 index 0000000000..d237702ca0 --- /dev/null +++ b/python-restclient/vcell_client/api/optimization_resource_api.py @@ -0,0 +1,1125 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import io +import warnings + +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Dict, List, Optional, Tuple, Union, Any + +try: + from typing import Annotated +except ImportError: + from typing_extensions import Annotated + +from pydantic import StrictInt + +from typing import List, Optional + +from vcell_client.models.opt_problem import OptProblem +from vcell_client.models.optimization_job_status import OptimizationJobStatus + +from vcell_client.api_client import ApiClient +from vcell_client.api_response import ApiResponse +from vcell_client.rest import RESTResponseType + + +class OptimizationResourceApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def get_optimization_status( + self, + opt_id: StrictInt, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> OptimizationJobStatus: + """Get status, progress, or results of an optimization job + + + :param opt_id: (required) + :type opt_id: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_optimization_status_serialize( + opt_id=opt_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '404': "VCellHTTPError", + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_optimization_status_with_http_info( + self, + opt_id: StrictInt, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[OptimizationJobStatus]: + """Get status, progress, or results of an optimization job + + + :param opt_id: (required) + :type opt_id: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_optimization_status_serialize( + opt_id=opt_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '404': "VCellHTTPError", + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_optimization_status_without_preload_content( + self, + opt_id: StrictInt, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get status, progress, or results of an optimization job + + + :param opt_id: (required) + :type opt_id: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_optimization_status_serialize( + opt_id=opt_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '404': "VCellHTTPError", + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_optimization_status_serialize( + self, + opt_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> Tuple: + + _host = None + + _collection_formats: Dict[str, str] = { + + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, str] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if opt_id is not None: + _path_params['optId'] = opt_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'openId' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/optimization/{optId}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_optimization_jobs( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[OptimizationJobStatus]: + """List optimization jobs for the authenticated user + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_optimization_jobs_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[OptimizationJobStatus]", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_optimization_jobs_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[OptimizationJobStatus]]: + """List optimization jobs for the authenticated user + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_optimization_jobs_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[OptimizationJobStatus]", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_optimization_jobs_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List optimization jobs for the authenticated user + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_optimization_jobs_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[OptimizationJobStatus]", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_optimization_jobs_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> Tuple: + + _host = None + + _collection_formats: Dict[str, str] = { + + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, str] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'openId' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/optimization', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def stop_optimization( + self, + opt_id: StrictInt, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> OptimizationJobStatus: + """Stop a running optimization job + + + :param opt_id: (required) + :type opt_id: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._stop_optimization_serialize( + opt_id=opt_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '404': "VCellHTTPError", + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def stop_optimization_with_http_info( + self, + opt_id: StrictInt, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[OptimizationJobStatus]: + """Stop a running optimization job + + + :param opt_id: (required) + :type opt_id: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._stop_optimization_serialize( + opt_id=opt_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '404': "VCellHTTPError", + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def stop_optimization_without_preload_content( + self, + opt_id: StrictInt, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Stop a running optimization job + + + :param opt_id: (required) + :type opt_id: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._stop_optimization_serialize( + opt_id=opt_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '404': "VCellHTTPError", + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _stop_optimization_serialize( + self, + opt_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> Tuple: + + _host = None + + _collection_formats: Dict[str, str] = { + + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, str] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if opt_id is not None: + _path_params['optId'] = opt_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'openId' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/api/v1/optimization/{optId}/stop', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def submit_optimization( + self, + opt_problem: Optional[OptProblem] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> OptimizationJobStatus: + """Submit a new parameter estimation optimization job + + + :param opt_problem: + :type opt_problem: OptProblem + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._submit_optimization_serialize( + opt_problem=opt_problem, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def submit_optimization_with_http_info( + self, + opt_problem: Optional[OptProblem] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[OptimizationJobStatus]: + """Submit a new parameter estimation optimization job + + + :param opt_problem: + :type opt_problem: OptProblem + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._submit_optimization_serialize( + opt_problem=opt_problem, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def submit_optimization_without_preload_content( + self, + opt_problem: Optional[OptProblem] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Submit a new parameter estimation optimization job + + + :param opt_problem: + :type opt_problem: OptProblem + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._submit_optimization_serialize( + opt_problem=opt_problem, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OptimizationJobStatus", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _submit_optimization_serialize( + self, + opt_problem, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> Tuple: + + _host = None + + _collection_formats: Dict[str, str] = { + + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, str] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if opt_problem is not None: + _body_params = opt_problem + + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'openId' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/api/v1/optimization', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/python-restclient/vcell_client/models/__init__.py b/python-restclient/vcell_client/models/__init__.py index 62754c6b30..2b35842f98 100644 --- a/python-restclient/vcell_client/models/__init__.py +++ b/python-restclient/vcell_client/models/__init__.py @@ -24,6 +24,11 @@ from vcell_client.models.bio_model_summary import BioModelSummary from vcell_client.models.biomodel_ref import BiomodelRef from vcell_client.models.coordinate import Coordinate +from vcell_client.models.copasi_optimization_method import CopasiOptimizationMethod +from vcell_client.models.copasi_optimization_method_optimization_method_type import CopasiOptimizationMethodOptimizationMethodType +from vcell_client.models.copasi_optimization_parameter import CopasiOptimizationParameter +from vcell_client.models.copasi_optimization_parameter_data_type import CopasiOptimizationParameterDataType +from vcell_client.models.copasi_optimization_parameter_param_type import CopasiOptimizationParameterParamType from vcell_client.models.curve import Curve from vcell_client.models.curve_selection_info import CurveSelectionInfo from vcell_client.models.data_identifier import DataIdentifier @@ -58,10 +63,19 @@ from vcell_client.models.mathmodel_ref import MathmodelRef from vcell_client.models.model_type import ModelType from vcell_client.models.n5_export_request import N5ExportRequest +from vcell_client.models.opt_job_status import OptJobStatus +from vcell_client.models.opt_problem import OptProblem +from vcell_client.models.opt_progress_item import OptProgressItem +from vcell_client.models.opt_progress_report import OptProgressReport +from vcell_client.models.opt_result_set import OptResultSet +from vcell_client.models.optimization_job_status import OptimizationJobStatus from vcell_client.models.origin import Origin +from vcell_client.models.parameter_description import ParameterDescription from vcell_client.models.publication import Publication from vcell_client.models.publication_info import PublicationInfo from vcell_client.models.publish_models_request import PublishModelsRequest +from vcell_client.models.reference_variable import ReferenceVariable +from vcell_client.models.reference_variable_reference_variable_type import ReferenceVariableReferenceVariableType from vcell_client.models.specialclaim import SPECIALCLAIM from vcell_client.models.sampled_curve import SampledCurve from vcell_client.models.scheduler_status import SchedulerStatus @@ -96,6 +110,8 @@ from vcell_client.models.variable_mode import VariableMode from vcell_client.models.variable_specs import VariableSpecs from vcell_client.models.variable_type import VariableType +from vcell_client.models.vcellopt import Vcellopt +from vcell_client.models.vcellopt_status import VcelloptStatus from vcell_client.models.version import Version from vcell_client.models.version_flag import VersionFlag from vcell_client.models.analytic_curve import AnalyticCurve diff --git a/python-restclient/vcell_client/models/copasi_optimization_method.py b/python-restclient/vcell_client/models/copasi_optimization_method.py new file mode 100644 index 0000000000..0843cb9a23 --- /dev/null +++ b/python-restclient/vcell_client/models/copasi_optimization_method.py @@ -0,0 +1,105 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional +from pydantic import BaseModel +from pydantic import Field +from vcell_client.models.copasi_optimization_method_optimization_method_type import CopasiOptimizationMethodOptimizationMethodType +from vcell_client.models.copasi_optimization_parameter import CopasiOptimizationParameter +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class CopasiOptimizationMethod(BaseModel): + """ + CopasiOptimizationMethod + """ # noqa: E501 + optimization_method_type: Optional[CopasiOptimizationMethodOptimizationMethodType] = Field(default=None, alias="optimizationMethodType") + optimization_parameter: Optional[List[CopasiOptimizationParameter]] = Field(default=None, alias="optimizationParameter") + __properties: ClassVar[List[str]] = ["optimizationMethodType", "optimizationParameter"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of CopasiOptimizationMethod from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in optimization_parameter (list) + _items = [] + if self.optimization_parameter: + for _item in self.optimization_parameter: + if _item: + _items.append(_item.to_dict()) + _dict['optimizationParameter'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of CopasiOptimizationMethod from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in CopasiOptimizationMethod) in the input: " + _key) + + _obj = cls.model_validate({ + "optimizationMethodType": obj.get("optimizationMethodType"), + "optimizationParameter": [CopasiOptimizationParameter.from_dict(_item) for _item in obj.get("optimizationParameter")] if obj.get("optimizationParameter") is not None else None + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/copasi_optimization_method_optimization_method_type.py b/python-restclient/vcell_client/models/copasi_optimization_method_optimization_method_type.py new file mode 100644 index 0000000000..402a10e903 --- /dev/null +++ b/python-restclient/vcell_client/models/copasi_optimization_method_optimization_method_type.py @@ -0,0 +1,57 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +import re # noqa: F401 +from enum import Enum + + + +try: + from typing import Self +except ImportError: + from typing_extensions import Self + + +class CopasiOptimizationMethodOptimizationMethodType(str, Enum): + """ + CopasiOptimizationMethodOptimizationMethodType + """ + + """ + allowed enum values + """ + SRES = 'SRES' + EVOLUTIONARYPROGRAM = 'evolutionaryProgram' + GENETICALGORITHM = 'geneticAlgorithm' + GENETICALGORITHMSR = 'geneticAlgorithmSR' + HOOKEJEEVES = 'hookeJeeves' + LEVENBERGMARQUARDT = 'levenbergMarquardt' + NELDERMEAD = 'nelderMead' + PARTICLESWARM = 'particleSwarm' + PRAXIS = 'praxis' + RANDOMSEARCH = 'randomSearch' + SIMULATEDANNEALING = 'simulatedAnnealing' + STEEPESTDESCENT = 'steepestDescent' + TRUNCATEDNEWTON = 'truncatedNewton' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of CopasiOptimizationMethodOptimizationMethodType from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/python-restclient/vcell_client/models/copasi_optimization_parameter.py b/python-restclient/vcell_client/models/copasi_optimization_parameter.py new file mode 100644 index 0000000000..6147452607 --- /dev/null +++ b/python-restclient/vcell_client/models/copasi_optimization_parameter.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, StrictFloat, StrictInt +from pydantic import Field +from vcell_client.models.copasi_optimization_parameter_data_type import CopasiOptimizationParameterDataType +from vcell_client.models.copasi_optimization_parameter_param_type import CopasiOptimizationParameterParamType +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class CopasiOptimizationParameter(BaseModel): + """ + CopasiOptimizationParameter + """ # noqa: E501 + data_type: Optional[CopasiOptimizationParameterDataType] = Field(default=None, alias="dataType") + param_type: Optional[CopasiOptimizationParameterParamType] = Field(default=None, alias="paramType") + value: Optional[Union[StrictFloat, StrictInt]] = None + __properties: ClassVar[List[str]] = ["dataType", "paramType", "value"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of CopasiOptimizationParameter from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of CopasiOptimizationParameter from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in CopasiOptimizationParameter) in the input: " + _key) + + _obj = cls.model_validate({ + "dataType": obj.get("dataType"), + "paramType": obj.get("paramType"), + "value": obj.get("value") + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/copasi_optimization_parameter_data_type.py b/python-restclient/vcell_client/models/copasi_optimization_parameter_data_type.py new file mode 100644 index 0000000000..e2a0de252a --- /dev/null +++ b/python-restclient/vcell_client/models/copasi_optimization_parameter_data_type.py @@ -0,0 +1,46 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +import re # noqa: F401 +from enum import Enum + + + +try: + from typing import Self +except ImportError: + from typing_extensions import Self + + +class CopasiOptimizationParameterDataType(str, Enum): + """ + CopasiOptimizationParameterDataType + """ + + """ + allowed enum values + """ + DOUBLE = 'double' + INT = 'int' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of CopasiOptimizationParameterDataType from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/python-restclient/vcell_client/models/copasi_optimization_parameter_param_type.py b/python-restclient/vcell_client/models/copasi_optimization_parameter_param_type.py new file mode 100644 index 0000000000..8333d47eac --- /dev/null +++ b/python-restclient/vcell_client/models/copasi_optimization_parameter_param_type.py @@ -0,0 +1,58 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +import re # noqa: F401 +from enum import Enum + + + +try: + from typing import Self +except ImportError: + from typing_extensions import Self + + +class CopasiOptimizationParameterParamType(str, Enum): + """ + CopasiOptimizationParameterParamType + """ + + """ + allowed enum values + """ + COOLINGFACTOR = 'coolingFactor' + ITERATIONLIMIT = 'iterationLimit' + NUMBEROFGENERATIONS = 'numberOfGenerations' + NUMBEROFITERATIONS = 'numberOfIterations' + PF = 'pf' + POPULATIONSIZE = 'populationSize' + RANDOMNUMBERGENERATOR = 'randomNumberGenerator' + RHO = 'rho' + SCALE = 'scale' + SEED = 'seed' + STARTTEMPERATURE = 'startTemperature' + STDDEVIATION = 'stdDeviation' + SWARMSIZE = 'swarmSize' + TOLERANCE = 'tolerance' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of CopasiOptimizationParameterParamType from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/python-restclient/vcell_client/models/opt_job_status.py b/python-restclient/vcell_client/models/opt_job_status.py new file mode 100644 index 0000000000..91a16765fb --- /dev/null +++ b/python-restclient/vcell_client/models/opt_job_status.py @@ -0,0 +1,50 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +import re # noqa: F401 +from enum import Enum + + + +try: + from typing import Self +except ImportError: + from typing_extensions import Self + + +class OptJobStatus(str, Enum): + """ + OptJobStatus + """ + + """ + allowed enum values + """ + SUBMITTED = 'SUBMITTED' + QUEUED = 'QUEUED' + RUNNING = 'RUNNING' + COMPLETE = 'COMPLETE' + FAILED = 'FAILED' + STOPPED = 'STOPPED' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of OptJobStatus from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/python-restclient/vcell_client/models/opt_problem.py b/python-restclient/vcell_client/models/opt_problem.py new file mode 100644 index 0000000000..91908ba3ed --- /dev/null +++ b/python-restclient/vcell_client/models/opt_problem.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, StrictFloat, StrictInt, StrictStr +from pydantic import Field +from vcell_client.models.copasi_optimization_method import CopasiOptimizationMethod +from vcell_client.models.parameter_description import ParameterDescription +from vcell_client.models.reference_variable import ReferenceVariable +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class OptProblem(BaseModel): + """ + OptProblem + """ # noqa: E501 + copasi_optimization_method: Optional[CopasiOptimizationMethod] = Field(default=None, alias="copasiOptimizationMethod") + data_set: Optional[List[List[Union[StrictFloat, StrictInt]]]] = Field(default=None, alias="dataSet") + math_model_sbml_contents: Optional[StrictStr] = Field(default=None, alias="mathModelSbmlContents") + number_of_optimization_runs: Optional[StrictInt] = Field(default=None, alias="numberOfOptimizationRuns") + parameter_description_list: Optional[List[ParameterDescription]] = Field(default=None, alias="parameterDescriptionList") + reference_variable: Optional[List[ReferenceVariable]] = Field(default=None, alias="referenceVariable") + __properties: ClassVar[List[str]] = ["copasiOptimizationMethod", "dataSet", "mathModelSbmlContents", "numberOfOptimizationRuns", "parameterDescriptionList", "referenceVariable"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of OptProblem from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of copasi_optimization_method + if self.copasi_optimization_method: + _dict['copasiOptimizationMethod'] = self.copasi_optimization_method.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in parameter_description_list (list) + _items = [] + if self.parameter_description_list: + for _item in self.parameter_description_list: + if _item: + _items.append(_item.to_dict()) + _dict['parameterDescriptionList'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in reference_variable (list) + _items = [] + if self.reference_variable: + for _item in self.reference_variable: + if _item: + _items.append(_item.to_dict()) + _dict['referenceVariable'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of OptProblem from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in OptProblem) in the input: " + _key) + + _obj = cls.model_validate({ + "copasiOptimizationMethod": CopasiOptimizationMethod.from_dict(obj.get("copasiOptimizationMethod")) if obj.get("copasiOptimizationMethod") is not None else None, + "dataSet": obj.get("dataSet"), + "mathModelSbmlContents": obj.get("mathModelSbmlContents"), + "numberOfOptimizationRuns": obj.get("numberOfOptimizationRuns"), + "parameterDescriptionList": [ParameterDescription.from_dict(_item) for _item in obj.get("parameterDescriptionList")] if obj.get("parameterDescriptionList") is not None else None, + "referenceVariable": [ReferenceVariable.from_dict(_item) for _item in obj.get("referenceVariable")] if obj.get("referenceVariable") is not None else None + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/opt_progress_item.py b/python-restclient/vcell_client/models/opt_progress_item.py new file mode 100644 index 0000000000..a103b2ed4a --- /dev/null +++ b/python-restclient/vcell_client/models/opt_progress_item.py @@ -0,0 +1,96 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, StrictFloat, StrictInt +from pydantic import Field +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class OptProgressItem(BaseModel): + """ + OptProgressItem + """ # noqa: E501 + num_function_evaluations: Optional[StrictInt] = Field(default=None, alias="numFunctionEvaluations") + obj_func_value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, alias="objFuncValue") + __properties: ClassVar[List[str]] = ["numFunctionEvaluations", "objFuncValue"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of OptProgressItem from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of OptProgressItem from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in OptProgressItem) in the input: " + _key) + + _obj = cls.model_validate({ + "numFunctionEvaluations": obj.get("numFunctionEvaluations"), + "objFuncValue": obj.get("objFuncValue") + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/opt_progress_report.py b/python-restclient/vcell_client/models/opt_progress_report.py new file mode 100644 index 0000000000..1fb72da308 --- /dev/null +++ b/python-restclient/vcell_client/models/opt_progress_report.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, StrictFloat, StrictInt +from pydantic import Field +from vcell_client.models.opt_progress_item import OptProgressItem +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class OptProgressReport(BaseModel): + """ + OptProgressReport + """ # noqa: E501 + best_param_values: Optional[Dict[str, Union[StrictFloat, StrictInt]]] = Field(default=None, alias="bestParamValues") + progress_items: Optional[List[OptProgressItem]] = Field(default=None, alias="progressItems") + __properties: ClassVar[List[str]] = ["bestParamValues", "progressItems"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of OptProgressReport from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in progress_items (list) + _items = [] + if self.progress_items: + for _item in self.progress_items: + if _item: + _items.append(_item.to_dict()) + _dict['progressItems'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of OptProgressReport from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in OptProgressReport) in the input: " + _key) + + _obj = cls.model_validate({ + "bestParamValues": obj.get("bestParamValues"), + "progressItems": [OptProgressItem.from_dict(_item) for _item in obj.get("progressItems")] if obj.get("progressItems") is not None else None + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/opt_result_set.py b/python-restclient/vcell_client/models/opt_result_set.py new file mode 100644 index 0000000000..096b618e87 --- /dev/null +++ b/python-restclient/vcell_client/models/opt_result_set.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, StrictFloat, StrictInt +from pydantic import Field +from vcell_client.models.opt_progress_report import OptProgressReport +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class OptResultSet(BaseModel): + """ + OptResultSet + """ # noqa: E501 + num_function_evaluations: Optional[StrictInt] = Field(default=None, alias="numFunctionEvaluations") + objective_function: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, alias="objectiveFunction") + opt_parameter_values: Optional[Dict[str, Union[StrictFloat, StrictInt]]] = Field(default=None, alias="optParameterValues") + opt_progress_report: Optional[OptProgressReport] = Field(default=None, alias="optProgressReport") + __properties: ClassVar[List[str]] = ["numFunctionEvaluations", "objectiveFunction", "optParameterValues", "optProgressReport"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of OptResultSet from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of opt_progress_report + if self.opt_progress_report: + _dict['optProgressReport'] = self.opt_progress_report.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of OptResultSet from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in OptResultSet) in the input: " + _key) + + _obj = cls.model_validate({ + "numFunctionEvaluations": obj.get("numFunctionEvaluations"), + "objectiveFunction": obj.get("objectiveFunction"), + "optParameterValues": obj.get("optParameterValues"), + "optProgressReport": OptProgressReport.from_dict(obj.get("optProgressReport")) if obj.get("optProgressReport") is not None else None + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/optimization_job_status.py b/python-restclient/vcell_client/models/optimization_job_status.py new file mode 100644 index 0000000000..87388d8904 --- /dev/null +++ b/python-restclient/vcell_client/models/optimization_job_status.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional +from pydantic import BaseModel, StrictStr +from pydantic import Field +from vcell_client.models.opt_job_status import OptJobStatus +from vcell_client.models.opt_progress_report import OptProgressReport +from vcell_client.models.vcellopt import Vcellopt +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class OptimizationJobStatus(BaseModel): + """ + OptimizationJobStatus + """ # noqa: E501 + id: Optional[StrictStr] = None + status: Optional[OptJobStatus] = None + status_message: Optional[StrictStr] = Field(default=None, alias="statusMessage") + htc_job_id: Optional[StrictStr] = Field(default=None, alias="htcJobId") + progress_report: Optional[OptProgressReport] = Field(default=None, alias="progressReport") + results: Optional[Vcellopt] = None + __properties: ClassVar[List[str]] = ["id", "status", "statusMessage", "htcJobId", "progressReport", "results"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of OptimizationJobStatus from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of progress_report + if self.progress_report: + _dict['progressReport'] = self.progress_report.to_dict() + # override the default output from pydantic by calling `to_dict()` of results + if self.results: + _dict['results'] = self.results.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of OptimizationJobStatus from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in OptimizationJobStatus) in the input: " + _key) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "status": obj.get("status"), + "statusMessage": obj.get("statusMessage"), + "htcJobId": obj.get("htcJobId"), + "progressReport": OptProgressReport.from_dict(obj.get("progressReport")) if obj.get("progressReport") is not None else None, + "results": Vcellopt.from_dict(obj.get("results")) if obj.get("results") is not None else None + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/parameter_description.py b/python-restclient/vcell_client/models/parameter_description.py new file mode 100644 index 0000000000..7f9d4c7c84 --- /dev/null +++ b/python-restclient/vcell_client/models/parameter_description.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, StrictFloat, StrictInt, StrictStr +from pydantic import Field +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class ParameterDescription(BaseModel): + """ + ParameterDescription + """ # noqa: E501 + initial_value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, alias="initialValue") + max_value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, alias="maxValue") + min_value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, alias="minValue") + name: Optional[StrictStr] = None + scale: Optional[Union[StrictFloat, StrictInt]] = None + __properties: ClassVar[List[str]] = ["initialValue", "maxValue", "minValue", "name", "scale"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ParameterDescription from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of ParameterDescription from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in ParameterDescription) in the input: " + _key) + + _obj = cls.model_validate({ + "initialValue": obj.get("initialValue"), + "maxValue": obj.get("maxValue"), + "minValue": obj.get("minValue"), + "name": obj.get("name"), + "scale": obj.get("scale") + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/reference_variable.py b/python-restclient/vcell_client/models/reference_variable.py new file mode 100644 index 0000000000..7a29e40af3 --- /dev/null +++ b/python-restclient/vcell_client/models/reference_variable.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional +from pydantic import BaseModel, StrictStr +from pydantic import Field +from vcell_client.models.reference_variable_reference_variable_type import ReferenceVariableReferenceVariableType +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class ReferenceVariable(BaseModel): + """ + ReferenceVariable + """ # noqa: E501 + reference_variable_type: Optional[ReferenceVariableReferenceVariableType] = Field(default=None, alias="referenceVariableType") + var_name: Optional[StrictStr] = Field(default=None, alias="varName") + __properties: ClassVar[List[str]] = ["referenceVariableType", "varName"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ReferenceVariable from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of ReferenceVariable from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in ReferenceVariable) in the input: " + _key) + + _obj = cls.model_validate({ + "referenceVariableType": obj.get("referenceVariableType"), + "varName": obj.get("varName") + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/reference_variable_reference_variable_type.py b/python-restclient/vcell_client/models/reference_variable_reference_variable_type.py new file mode 100644 index 0000000000..d032702e1e --- /dev/null +++ b/python-restclient/vcell_client/models/reference_variable_reference_variable_type.py @@ -0,0 +1,46 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +import re # noqa: F401 +from enum import Enum + + + +try: + from typing import Self +except ImportError: + from typing_extensions import Self + + +class ReferenceVariableReferenceVariableType(str, Enum): + """ + ReferenceVariableReferenceVariableType + """ + + """ + allowed enum values + """ + DEPENDENT = 'dependent' + INDEPENDENT = 'independent' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ReferenceVariableReferenceVariableType from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/python-restclient/vcell_client/models/vcellopt.py b/python-restclient/vcell_client/models/vcellopt.py new file mode 100644 index 0000000000..db3d2b2cff --- /dev/null +++ b/python-restclient/vcell_client/models/vcellopt.py @@ -0,0 +1,109 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional +from pydantic import BaseModel, StrictStr +from pydantic import Field +from vcell_client.models.opt_problem import OptProblem +from vcell_client.models.opt_result_set import OptResultSet +from vcell_client.models.vcellopt_status import VcelloptStatus +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Vcellopt(BaseModel): + """ + Vcellopt + """ # noqa: E501 + opt_problem: Optional[OptProblem] = Field(default=None, alias="optProblem") + opt_result_set: Optional[OptResultSet] = Field(default=None, alias="optResultSet") + status: Optional[VcelloptStatus] = None + status_message: Optional[StrictStr] = Field(default=None, alias="statusMessage") + __properties: ClassVar[List[str]] = ["optProblem", "optResultSet", "status", "statusMessage"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Vcellopt from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of opt_problem + if self.opt_problem: + _dict['optProblem'] = self.opt_problem.to_dict() + # override the default output from pydantic by calling `to_dict()` of opt_result_set + if self.opt_result_set: + _dict['optResultSet'] = self.opt_result_set.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Vcellopt from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in Vcellopt) in the input: " + _key) + + _obj = cls.model_validate({ + "optProblem": OptProblem.from_dict(obj.get("optProblem")) if obj.get("optProblem") is not None else None, + "optResultSet": OptResultSet.from_dict(obj.get("optResultSet")) if obj.get("optResultSet") is not None else None, + "status": obj.get("status"), + "statusMessage": obj.get("statusMessage") + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/vcellopt_status.py b/python-restclient/vcell_client/models/vcellopt_status.py new file mode 100644 index 0000000000..2f4e5ff4af --- /dev/null +++ b/python-restclient/vcell_client/models/vcellopt_status.py @@ -0,0 +1,48 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +import re # noqa: F401 +from enum import Enum + + + +try: + from typing import Self +except ImportError: + from typing_extensions import Self + + +class VcelloptStatus(str, Enum): + """ + VcelloptStatus + """ + + """ + allowed enum values + """ + COMPLETE = 'complete' + FAILED = 'failed' + QUEUED = 'queued' + RUNNING = 'running' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of VcelloptStatus from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/pythonCopasiOpt/Dockerfile b/pythonCopasiOpt/Dockerfile index 78e5752f21..32dd8ed8a7 100644 --- a/pythonCopasiOpt/Dockerfile +++ b/pythonCopasiOpt/Dockerfile @@ -1,7 +1,8 @@ -FROM python:3.10-slim-bullseye +FROM python:3.10-slim-bookworm RUN apt -y update && apt -y upgrade && \ - apt install -y curl + apt install -y curl gcc python3-dev && \ + rm -rf /var/lib/apt/lists/* RUN mkdir -p /usr/local/app/vcell/installDir && \ mkdir -p /usr/local/app/vcell/installDir/python/vcell_opt diff --git a/pythonCopasiOpt/vcell-opt/poetry.lock b/pythonCopasiOpt/vcell-opt/poetry.lock index 557c4ee14f..c82400c594 100644 --- a/pythonCopasiOpt/vcell-opt/poetry.lock +++ b/pythonCopasiOpt/vcell-opt/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "anyio" @@ -6,6 +6,7 @@ version = "3.6.2" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.6.2" +groups = ["main"] files = [ {file = "anyio-3.6.2-py3-none-any.whl", hash = "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"}, {file = "anyio-3.6.2.tar.gz", hash = "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421"}, @@ -17,7 +18,7 @@ sniffio = ">=1.1" [package.extras] doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] +test = ["contextlib2 ; python_version < \"3.7\"", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4) ; python_version < \"3.8\"", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15) ; python_version < \"3.7\" and platform_python_implementation == \"CPython\" and platform_system != \"Windows\"", "uvloop (>=0.15) ; python_version >= \"3.7\" and platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] trio = ["trio (>=0.16,<0.22)"] [[package]] @@ -26,6 +27,8 @@ version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" optional = false python-versions = "*" +groups = ["main"] +markers = "platform_system == \"Darwin\" or sys_platform == \"darwin\"" files = [ {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, @@ -37,6 +40,7 @@ version = "21.3.0" description = "The secure Argon2 password hashing algorithm." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, {file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"}, @@ -56,6 +60,7 @@ version = "21.2.0" description = "Low-level CFFI bindings for Argon2" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, @@ -93,6 +98,7 @@ version = "1.3.0" description = "Better dates & times for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, @@ -112,6 +118,7 @@ version = "2.2.1" description = "Annotate AST trees with source code positions" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"}, {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"}, @@ -129,16 +136,17 @@ version = "22.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.5" +groups = ["main", "dev"] files = [ {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] +tests-no-zope = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] [[package]] name = "backcall" @@ -146,6 +154,7 @@ version = "0.2.0" description = "Specifications for callback functions passed in to an API" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, @@ -157,6 +166,7 @@ version = "4.11.1" description = "Screen-scraping library" optional = false python-versions = ">=3.6.0" +groups = ["main"] files = [ {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"}, {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, @@ -175,6 +185,7 @@ version = "5.0.1" description = "An easy safelist-based HTML-sanitizing tool." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "bleach-5.0.1-py3-none-any.whl", hash = "sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a"}, {file = "bleach-5.0.1.tar.gz", hash = "sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c"}, @@ -186,7 +197,7 @@ webencodings = "*" [package.extras] css = ["tinycss2 (>=1.1.0,<1.2)"] -dev = ["Sphinx (==4.3.2)", "black (==22.3.0)", "build (==0.8.0)", "flake8 (==4.0.1)", "hashin (==0.17.0)", "mypy (==0.961)", "pip-tools (==6.6.2)", "pytest (==7.1.2)", "tox (==3.25.0)", "twine (==4.0.1)", "wheel (==0.37.1)"] +dev = ["Sphinx (==4.3.2)", "black (==22.3.0) ; implementation_name == \"cpython\"", "build (==0.8.0)", "flake8 (==4.0.1)", "hashin (==0.17.0)", "mypy (==0.961) ; implementation_name == \"cpython\"", "pip-tools (==6.6.2)", "pytest (==7.1.2)", "tox (==3.25.0)", "twine (==4.0.1)", "wheel (==0.37.1)"] [[package]] name = "cffi" @@ -194,6 +205,7 @@ version = "1.15.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = "*" +groups = ["main"] files = [ {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, @@ -270,6 +282,7 @@ version = "8.1.3" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, @@ -284,10 +297,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {dev = "sys_platform == \"win32\""} [[package]] name = "commonmark" @@ -295,6 +310,7 @@ version = "0.9.1" description = "Python parser for the CommonMark Markdown spec" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, @@ -309,6 +325,7 @@ version = "1.0.6" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "contourpy-1.0.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:613c665529899b5d9fade7e5d1760111a0b011231277a0d36c49f0d3d6914bd6"}, {file = "contourpy-1.0.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78ced51807ccb2f45d4ea73aca339756d75d021069604c2fccd05390dc3c28eb"}, @@ -393,24 +410,30 @@ test-no-codebase = ["Pillow", "matplotlib", "pytest"] [[package]] name = "copasi-basico" -version = "0.40" +version = "0.86" description = "Simplified COPASI interface for python" optional = false python-versions = "*" +groups = ["main"] files = [ - {file = "copasi_basico-0.40-py3-none-any.whl", hash = "sha256:1a67220a1bb898b8eee29ac30b1c2498145c01036174b5dbc9bfc11b186a5292"}, - {file = "copasi_basico-0.40.tar.gz", hash = "sha256:72d836a461875cd4a83c4b15146b24d0bf83f0530ea67d413b32cdae2f1bc09e"}, + {file = "copasi_basico-0.86-py3-none-any.whl", hash = "sha256:d92b93ad28edcd84b83962913d1fc973906ca612c01e954007d23a9031167058"}, + {file = "copasi_basico-0.86.tar.gz", hash = "sha256:de3090ee3bb46a64953ab35b759023d20081a29d518eb3a5d0377fe23765f336"}, ] [package.dependencies] +lxml = "*" matplotlib = "*" numpy = "*" pandas = "*" python-copasi = "*" PyYAML = "*" +scipy = "*" [package.extras] +docs = ["sphinx", "sphinx_rtd_theme", "sphinxcontrib", "sphinxcontrib-bibtex", "sphinxcontrib-mermaid", "sphinxcontrib-plantuml", "sphinxcontrib-programoutput"] petab = ["copasi-petab-importer", "petab", "petab-select"] +ssr = ["libssr", "python-libsbml"] +tqdm = ["tqdm"] [[package]] name = "cycler" @@ -418,6 +441,7 @@ version = "0.11.0" description = "Composable style cycles" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, @@ -429,6 +453,7 @@ version = "1.6.4" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "debugpy-1.6.4-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:6ae238943482c78867ac707c09122688efb700372b617ffd364261e5e41f7a2f"}, {file = "debugpy-1.6.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a39e7da178e1f22f4bc04b57f085e785ed1bcf424aaf318835a1a7129eefe35"}, @@ -456,6 +481,7 @@ version = "5.1.1" description = "Decorators for Humans" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, @@ -467,6 +493,7 @@ version = "0.7.1" description = "XML bomb protection for Python stdlib modules" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] files = [ {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, @@ -478,6 +505,7 @@ version = "0.4" description = "Discover and load entry points from installed packages." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, @@ -489,6 +517,8 @@ version = "1.0.4" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, @@ -503,13 +533,14 @@ version = "1.2.0" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, ] [package.extras] -tests = ["asttokens", "littleutils", "pytest", "rich"] +tests = ["asttokens", "littleutils", "pytest", "rich ; python_version >= \"3.11\""] [[package]] name = "fastjsonschema" @@ -517,6 +548,7 @@ version = "2.16.2" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "fastjsonschema-2.16.2-py3-none-any.whl", hash = "sha256:21f918e8d9a1a4ba9c22e09574ba72267a6762d47822db9add95f6454e51cc1c"}, {file = "fastjsonschema-2.16.2.tar.gz", hash = "sha256:01e366f25d9047816fe3d288cbfc3e10541daf0af2044763f3d0ade42476da18"}, @@ -531,24 +563,25 @@ version = "4.38.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "fonttools-4.38.0-py3-none-any.whl", hash = "sha256:820466f43c8be8c3009aef8b87e785014133508f0de64ec469e4efb643ae54fb"}, {file = "fonttools-4.38.0.zip", hash = "sha256:2bb244009f9bf3fa100fc3ead6aeb99febe5985fa20afbfbaa2f8946c2fbdaf1"}, ] [package.extras] -all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=14.0.0)", "xattr", "zopfli (>=0.1.4)"] +all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=14.0.0) ; python_version < \"3.11\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres", "scipy"] +interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "scipy ; platform_python_implementation != \"PyPy\""] lxml = ["lxml (>=4.0,<5)"] pathops = ["skia-pathops (>=0.5.0)"] plot = ["matplotlib"] repacker = ["uharfbuzz (>=0.23.0)"] symfont = ["sympy"] -type1 = ["xattr"] +type1 = ["xattr ; sys_platform == \"darwin\""] ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=14.0.0)"] -woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] +unicode = ["unicodedata2 (>=14.0.0) ; python_version < \"3.11\""] +woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] [[package]] name = "fqdn" @@ -556,6 +589,7 @@ version = "1.5.1" description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" optional = false python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" +groups = ["main"] files = [ {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, @@ -567,36 +601,19 @@ version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] -[[package]] -name = "importlib-metadata" -version = "5.1.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "importlib_metadata-5.1.0-py3-none-any.whl", hash = "sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313"}, - {file = "importlib_metadata-5.1.0.tar.gz", hash = "sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] - [[package]] name = "iniconfig" version = "1.1.1" description = "iniconfig: brain-dead simple config-ini parsing" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, @@ -608,6 +625,7 @@ version = "6.17.1" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "ipykernel-6.17.1-py3-none-any.whl", hash = "sha256:3a9a1b2ad6dbbd5879855aabb4557f08e63fa2208bffed897f03070e2bb436f6"}, {file = "ipykernel-6.17.1.tar.gz", hash = "sha256:e178c1788399f93a459c241fe07c3b810771c607b1fb064a99d2c5d40c90c5d4"}, @@ -636,6 +654,7 @@ version = "8.10.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "ipython-8.10.0-py3-none-any.whl", hash = "sha256:b38c31e8fc7eff642fc7c597061fff462537cf2314e3225a19c906b7b0d8a345"}, {file = "ipython-8.10.0.tar.gz", hash = "sha256:b13a1d6c1f5818bd388db53b7107d17454129a70de2b87481d555daede5eb49e"}, @@ -674,6 +693,7 @@ version = "0.2.0" description = "Vestigial utilities from IPython" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, @@ -685,6 +705,7 @@ version = "8.0.2" description = "Jupyter interactive widgets" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "ipywidgets-8.0.2-py3-none-any.whl", hash = "sha256:1dc3dd4ee19ded045ea7c86eb273033d238d8e43f9e7872c52d092683f263891"}, {file = "ipywidgets-8.0.2.tar.gz", hash = "sha256:08cb75c6e0a96836147cbfdc55580ae04d13e05d26ffbc377b4e1c68baa28b1f"}, @@ -706,6 +727,7 @@ version = "20.11.0" description = "Operations with ISO 8601 durations" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, @@ -720,6 +742,7 @@ version = "0.18.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"}, {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"}, @@ -739,6 +762,7 @@ version = "3.1.2" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, @@ -756,6 +780,7 @@ version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +groups = ["main"] files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, @@ -767,6 +792,7 @@ version = "4.17.3" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, @@ -794,6 +820,7 @@ version = "1.0.0" description = "Jupyter metapackage. Install all the Jupyter components in one go." optional = false python-versions = "*" +groups = ["main"] files = [ {file = "jupyter-1.0.0-py2.py3-none-any.whl", hash = "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78"}, {file = "jupyter-1.0.0.tar.gz", hash = "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"}, @@ -814,6 +841,7 @@ version = "7.4.8" description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "jupyter_client-7.4.8-py3-none-any.whl", hash = "sha256:d4a67ae86ee014bcb96bd8190714f6af921f2b0f52f4208b086aa5acfd9f8d65"}, {file = "jupyter_client-7.4.8.tar.gz", hash = "sha256:109a3c33b62a9cf65aa8325850a0999a795fac155d9de4f7555aef5f310ee35a"}, @@ -838,6 +866,7 @@ version = "6.4.4" description = "Jupyter terminal console" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "jupyter_console-6.4.4-py3-none-any.whl", hash = "sha256:756df7f4f60c986e7bc0172e4493d3830a7e6e75c08750bbe59c0a5403ad6dee"}, {file = "jupyter_console-6.4.4.tar.gz", hash = "sha256:172f5335e31d600df61613a97b7f0352f2c8250bbd1092ef2d658f77249f89fb"}, @@ -851,7 +880,7 @@ prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" pygments = "*" [package.extras] -test = ["pexpect"] +test = ["pexpect ; sys_platform != \"win32\""] [[package]] name = "jupyter-core" @@ -859,6 +888,7 @@ version = "5.1.0" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jupyter_core-5.1.0-py3-none-any.whl", hash = "sha256:f5740d99606958544396914b08e67b668f45e7eff99ab47a7f4bcead419c02f4"}, {file = "jupyter_core-5.1.0.tar.gz", hash = "sha256:a5ae7c09c55c0b26f692ec69323ba2b62e8d7295354d20f6cd57b749de4a05bf"}, @@ -879,6 +909,7 @@ version = "0.6.3" description = "Jupyter Event System library" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "jupyter_events-0.6.3-py3-none-any.whl", hash = "sha256:57a2749f87ba387cd1bfd9b22a0875b889237dbf2edc2121ebb22bde47036c17"}, {file = "jupyter_events-0.6.3.tar.gz", hash = "sha256:9a6e9995f75d1b7146b436ea24d696ce3a35bfa8bfe45e0c33c334c79464d0b3"}, @@ -903,6 +934,7 @@ version = "2.7.2" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jupyter_server-2.7.2-py3-none-any.whl", hash = "sha256:98a375347b580e837e7016007c24680a4261ed8ad7cd35196ac087d229f48e5a"}, {file = "jupyter_server-2.7.2.tar.gz", hash = "sha256:d64fb4e593907290e5df916e3c9399c15ab2cd7bdb71cbcd1d36452dbfb30523"}, @@ -939,6 +971,7 @@ version = "0.4.4" description = "A Jupyter Server Extension Providing Terminals." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jupyter_server_terminals-0.4.4-py3-none-any.whl", hash = "sha256:75779164661cec02a8758a5311e18bb8eb70c4e86c6b699403100f1585a12a36"}, {file = "jupyter_server_terminals-0.4.4.tar.gz", hash = "sha256:57ab779797c25a7ba68e97bcfb5d7740f2b5e8a83b5e8102b10438041a7eac5d"}, @@ -958,6 +991,7 @@ version = "0.2.2" description = "Pygments theme using JupyterLab CSS variables" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, @@ -969,6 +1003,7 @@ version = "3.0.3" description = "Jupyter interactive widgets for JupyterLab" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "jupyterlab_widgets-3.0.3-py3-none-any.whl", hash = "sha256:6aa1bc0045470d54d76b9c0b7609a8f8f0087573bae25700a370c11f82cb38c8"}, {file = "jupyterlab_widgets-3.0.3.tar.gz", hash = "sha256:c767181399b4ca8b647befe2d913b1260f51bf9d8ef9b7a14632d4c1a7b536bd"}, @@ -980,6 +1015,7 @@ version = "1.4.4" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6"}, {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c"}, @@ -1051,12 +1087,163 @@ files = [ {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, ] +[[package]] +name = "lxml" +version = "6.0.3" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "lxml-6.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88c524cf8c3b8d71dfc3de6cfb225138a876862a92d88bfa22eb9ff020729d45"}, + {file = "lxml-6.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a10f9967859229cae38b1aa7a96eb655c96b8adc96989b52c5b1f77d963a77a4"}, + {file = "lxml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:edccf1157677db1da741d042601754b94af3926310c5763179200718ca738e70"}, + {file = "lxml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:20f8caa9beb61a688c4428631cb47fd6e0ba75ef30091cec5fee992138b2be77"}, + {file = "lxml-6.0.3-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0c88ca5fb307f7e817fc427681126e4712d3452258577bcb4ca86594c934852"}, + {file = "lxml-6.0.3-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:72d108ef9e39f45c6865ea8a5ba6736c0b1a33ddd6343653775349869e58c30b"}, + {file = "lxml-6.0.3-cp310-cp310-manylinux_2_28_i686.whl", hash = "sha256:b044fe3bdb8b68efa33cb5917ae9379f07ec2e416ecd18cf5d333650d6d2fcbb"}, + {file = "lxml-6.0.3-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:a4dc9f81707b9b56888fa7d3a889ac5219724cf0fbecab90ea5b197faf649534"}, + {file = "lxml-6.0.3-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:59ff244cee0270fc4cf5f2ee920d4493ee88d0bcbc6e8465e9ef01439f1785e7"}, + {file = "lxml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2a49123cc3209ccad7c4c5a4133bcfcfd4875f30461ea4d0aaa84e6608f712c5"}, + {file = "lxml-6.0.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:26cdd7c3f4c3b932b28859d0b70966c2ec8b67c106717d6320121002f8f99025"}, + {file = "lxml-6.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:6556b3197bd8a237a16fcd7278d09f094c5777ae36a1435b5e8e488826386d96"}, + {file = "lxml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:87bebd6836e88c0a007f66b89814daf5d7041430eb491c91d1851abc89aa6e93"}, + {file = "lxml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:0b012cf200736d90f828b3ab4206857772c61b710f0a98d3814c7994decb6652"}, + {file = "lxml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:794b42f0112adfa3f23670aba5bc0ac9c9adfcee699c0df129b0186c812ac3ff"}, + {file = "lxml-6.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:ecdded59dc50c0c28f652a98f69a7ada8bd2377248bf48c4a83c81204eb58b33"}, + {file = "lxml-6.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c8184fdb2259bda1db2db9d6e25f667769afc2531830b4fa29f83f66a7872dea"}, + {file = "lxml-6.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b0f01fb8bdcaf4aa69cf55b2b2f8ef722e4423e1c020e7250dcb89a1d5db38e"}, + {file = "lxml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fab00cef83d4f9d76c5e0722346e84bc174b071d68b4f725aeb0bf3877b9e6a6"}, + {file = "lxml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7f753db5785ce019d7b25bb75638ef5a42a0e208aa9f19933262134e668ca6af"}, + {file = "lxml-6.0.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27e317e554bc6086a082688ddf137437e5f7f20ffdd736a6f5b4e3ed1ecf1247"}, + {file = "lxml-6.0.3-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:feb5b9ed7d0510663a78b94f2b417a41c41b42a7bb157ef398ef9d78e6f0fd50"}, + {file = "lxml-6.0.3-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:51014ee2ab2091dcd9cdef92532f0a1addb7c2cc52a2bd70682e441363de5c0d"}, + {file = "lxml-6.0.3-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:abc39c4fb67f029400608f9a3a4a3f351ccb3c061b05fd3ad113e4cfbba8a8ee"}, + {file = "lxml-6.0.3-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:38652c280cf50cc5cf955e3d0b691fa6a97046d84407bbae340d8e353f9014ef"}, + {file = "lxml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c3de55b53f69ffa2fcfd897bd8a7e62f0f88a40a8a0c544e171e813f9d4ddbf5"}, + {file = "lxml-6.0.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:bd4f70e091f2df300396bc9ce36963f90b87611324c2ca750072a6e6375beba2"}, + {file = "lxml-6.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:c157bfef4e3b19688eb4da783c5bfabf5a3ac1ac8d317e0906f3feb18d4c89b7"}, + {file = "lxml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8d10a75e4d0a6a9ac2fec2f7ade682f468b51935102c70dab638fa4e94ffcb04"}, + {file = "lxml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:d573b81c29e20b1513afa386a544797a99cecde5497e6c77b6dfa4484112c819"}, + {file = "lxml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:ac63a1ef1899ccadace10ac937c41321672771378374c254e931d001448ae372"}, + {file = "lxml-6.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:10bc4f37c28b4e1b3e901dde66e3a096eb128acf388d5b2962dc2941284293bb"}, + {file = "lxml-6.0.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ad6952810349cbfb843fe15e8afc580b2712359ae42b1d2b05d097bd48c4aea4"}, + {file = "lxml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b81ec1ecac3be8c1ff1e00ca1c1baf8122e87db9000cd2549963847bd5e3b41"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:448e69211e59c39f398990753d15ba49f7218ec128f64ac8012ef16762e509a3"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6289cb9145fbbc5b0e159c9fcd7fc09446dadc6b60b72c4d1012e80c7c727970"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b68c29aac4788438b07d768057836de47589c7deaa3ad8dc4af488dfc27be388"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:50293e024afe5e2c25da2be68c8ceca8618912a0701a73f75b488317c8081aa6"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac65c08ba1bd90f662cb1d5c79f7ae4c53b1c100f0bb6ec5df1f40ac29028a7e"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:16fbcf06ae534b2fa5bcdc19fcf6abd9df2e74fe8563147d1c5a687a130efed4"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:3a0484bd1e84f82766befcbd71cccd7307dacfe08071e4dbc1d9a9b498d321e8"}, + {file = "lxml-6.0.3-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c137f8c8419c3de93e2998131d94628805f148e52b34da6d7533454e4d78bc2a"}, + {file = "lxml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:775266571f7027b1d77f5fce18a247b24f51a4404bdc1b90ec56be9b1e3801b9"}, + {file = "lxml-6.0.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:aa18653b795d2c273b8676f7ad2ca916d846d15864e335f746658e4c28eb5168"}, + {file = "lxml-6.0.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:cbffd22fc8e4d80454efa968b0c93440a00b8b8a817ce0c29d2c6cb5ad324362"}, + {file = "lxml-6.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7373ede7ccb89e6f6e39c1423b3a4d4ee48035d3b4619a6addced5c8b48d0ecc"}, + {file = "lxml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e759ff1b244725fef428c6b54f3dab4954c293b2d242a5f2e79db5cc3873de51"}, + {file = "lxml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:f179bae37ad673f57756b59f26833b7922230bef471fdb29492428f152bae8c6"}, + {file = "lxml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:8eeec925ad7f81886d413b3a1f8715551f75543519229a9b35e957771e1826d5"}, + {file = "lxml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:f96bba9a26a064ce9e11099bad12fb08384b64d3acc0acf94bf386ca5cf4f95f"}, + {file = "lxml-6.0.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:83c1d75e9d124ab82a4ddaf59135112f0dc49526b47355e5928ae6126a68e236"}, + {file = "lxml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b683665d0287308adafc90a5617a51a508d8af8c7040693693bb333b5f4474fe"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ed31e5852cd938704bc6c7a3822cbf84c7fa00ebfa914a1b4e2392d44f45bdfb"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8922a30704a4421d69a19e0499db5861da686c0bccc3a79cf3946e3155cf25f9"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a1adb0e220cb8691202ba9d97646a06292657a122df4b92733861d42f7cf4d2"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:821fd53699eb498990c915ba955a392d07246454c9405e6c1d0692362503013d"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04b7cedf52e125f86d0d426635e7fbe8e353d4cc272a1757888e3c072424381d"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:9d98063e6ae0da5084ec46952bb0a5ccb5e2cad168e32b4d65d1ec84e4b4ebd4"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:ce01ab3449015358f766a1950b3d818eedf9d4cdec3fa87e4eecaad10c0784db"}, + {file = "lxml-6.0.3-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d38c25bad123d6ce30bb37931d90a4e8a167cd796eeae9cd16c2bfce52718f8e"}, + {file = "lxml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9b8e0779780026979f217603385995202f364adc9807bd21210d81b9f562fc4e"}, + {file = "lxml-6.0.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8c082ad2398664213a4bb5d133e2eb8bf239220b7d6688f8c8ffa9050057501f"}, + {file = "lxml-6.0.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dfc80c74233fe01157ab550fb12b9d07a2f1fa7c5900cefb484e3bf02e856fbc"}, + {file = "lxml-6.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5c45bdcdc2ca6cf26fddff3faa5de7a2ed7c7f6016b3de80125313a37f972378"}, + {file = "lxml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99457524afd384c330dc51e527976653d543ccadfa815d9f2d92c5911626e536"}, + {file = "lxml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:c8e3b8a54e65393ce1d5c7d9753fe756f0d96089e7163b20ddec3e5bb56a963e"}, + {file = "lxml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:724b26a38cef98d6869d00a33cb66083bee967598e44f6a8e53f1dd283c851b0"}, + {file = "lxml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:f27373113fda6621e4201f529908a24c8a190c2af355aed4711dadca44db4673"}, + {file = "lxml-6.0.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8c08926678852a233bf1ef645c4d683d56107f814482f8f41b21ef2c7659790e"}, + {file = "lxml-6.0.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2ce76d113a7c3bf42761ec1de7ca615b0cbf9d8ae478eb1d6c20111d9c9fc098"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:83eca62141314d641ebe8089ffa532bbf572ea07dd6255b58c40130d06bb2509"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d8781d812bb8efd47c35651639da38980383ff0d0c1f3269ade23e3a90799079"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19b079e81aa3a31b523a224b0dd46da4f56e1b1e248eef9a599e5c885c788813"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6c055bafdcb53e7f9f75e22c009cd183dd410475e21c296d599531d7f03d1bf5"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f1594a183cee73f9a1dbfd35871c4e04b461f47eeb9bcf80f7d7856b1b136d"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:a6380c5035598e4665272ad3fc86c96ddb2a220d4059cce5ba4b660f78346ad9"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:143ac903fb6c9be6da613390825c8e8bb8c8d71517d43882031f6b9bc89770ef"}, + {file = "lxml-6.0.3-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4fff7d77f440378cd841e340398edf5dbefee334816efbf521bb6e31651e54e"}, + {file = "lxml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:631567ffc3ddb989ccdcd28f6b9fa5aab1ec7fc0e99fe65572b006a6aad347e2"}, + {file = "lxml-6.0.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:38acf7171535ffa7fff1fcec8b82ebd4e55cd02e581efe776928108421accaa1"}, + {file = "lxml-6.0.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:06b9f3ac459b4565bbaa97aa5512aa7f9a1188c662f0108364f288f6daf35773"}, + {file = "lxml-6.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2773dbe2cedee81f2769bd5d24ceb4037706cf032e1703513dd0e9476cd9375f"}, + {file = "lxml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:30c437d8bb9a9a9edff27e85b694342e47a26a6abc249abe00584a4824f9d80d"}, + {file = "lxml-6.0.3-cp314-cp314-win32.whl", hash = "sha256:1b60a3a1205f869bd47874787c792087174453b1a869db4837bf5b3ff92be017"}, + {file = "lxml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:5b6913a68d98c58c673667c864500ba31bc9b0f462effac98914e9a92ebacd2e"}, + {file = "lxml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:1b36a3c73f2a6d9c2bfae78089ca7aedae5c2ee5fd5214a15f00b2f89e558ba7"}, + {file = "lxml-6.0.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:239e9a6be3a79c03ec200d26f7bb17a4414704a208059e20050bf161e2d8848a"}, + {file = "lxml-6.0.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:16e5cbaa1a6351f2abefa4072e9aac1f09103b47fe7ab4496d54e5995b065162"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:89f8746c206d8cf2c167221831645d6cc2b24464afd9c428a5eb3fd34c584eb1"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5d559a84b2fd583e5bcf8ec4af1ec895f98811684d5fbd6524ea31a04f92d4ad"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7966fbce2d18fde579d5593933d36ad98cc7c8dc7f2b1916d127057ce0415062"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a1f258e6aa0e6eda2c1199f5582c062c96c7d4a28d96d0c4daa79e39b3f2a764"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:738aef404c862d2c3cd951364ee7175c9d50e8290f5726611c4208c0fba8d186"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:5c35e5c3ed300990a46a144d3514465713f812b35dacfa83e928c60db7c90af7"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:4ff774b43712b0cf40d9888a5494ca39aefe990c946511cc947b9fddcf74a29b"}, + {file = "lxml-6.0.3-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d20af2784c763928d0d0879cbc5a3739e4d81eefa0d68962d3478bff4c13e644"}, + {file = "lxml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fdb7786ebefaa0dad0d399dfeaf146b370a14591af2f3aea59e06f931a426678"}, + {file = "lxml-6.0.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c71a387ea133481e725079cff22de45593bf0b834824de22829365ab1d2386c9"}, + {file = "lxml-6.0.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:841b89fc3d910d61c7c267db6bb7dc3a8b3dac240edb66220fcdf96fe70a0552"}, + {file = "lxml-6.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:ac2d6cdafa29672d6a604c641bf67ace3fd0735ec6885501a94943379219ddbf"}, + {file = "lxml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:609bf136a7339aeca2bd4268c7cd190f33d13118975fe9964eda8e5138f42802"}, + {file = "lxml-6.0.3-cp314-cp314t-win32.whl", hash = "sha256:bf98f5f87f6484302e7cce4e2ca5af43562902852063d916c3e2f1c115fdce60"}, + {file = "lxml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d3d65e511e4e656ec67b472110f7a72cbf8547ca15f76fe74cffa4e97412a064"}, + {file = "lxml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:cbc7ce67f85b92db97c92219985432be84dc1ba9a028e68c6933e89551234df2"}, + {file = "lxml-6.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fc6eeeddcee4d985707b3fc29fd6993e256e55798ca600586da68d3f0e04ec5a"}, + {file = "lxml-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9e779a9c3167d2f158c41b6347fbc9e855f6d5561920a33123beb86463c3f46"}, + {file = "lxml-6.0.3-cp38-cp38-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:911dbd0e87729016402e03533117ffe94147bfbcd7902b76af5854c4b437e096"}, + {file = "lxml-6.0.3-cp38-cp38-manylinux_2_28_i686.whl", hash = "sha256:f297e9be3bbe59c31cfe5d0f38534510ed95856c480df3e8721b16d46ccaeeac"}, + {file = "lxml-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2d00902610dd91a970a06d5f1a6e4f2426e04a9fa07209d58e09b345e2269267"}, + {file = "lxml-6.0.3-cp38-cp38-win32.whl", hash = "sha256:46c80f7fd5dd7d8c269f6486b165c8f91c489e323f3a767221fb5b4b2b388d5f"}, + {file = "lxml-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:336925309af5ecd9616acbe1c28d68ee0088839b1d42ae7dcc40ffecff959537"}, + {file = "lxml-6.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:353161f166e76f0d8228f8f5216d110601d143a8b6d0fd869230e12c098a5842"}, + {file = "lxml-6.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e8ad05bb1fb4aa20ee201ab2f21c3c7571828e4fad525707437bb1c5f5ab6669"}, + {file = "lxml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:976b56bd0f4ca72280b4569eb227d012a541860f0d6fcc128ce26d22ef82c845"}, + {file = "lxml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:322c825054d02d35755b80dc5c39ba8a71c7c09c43453394a13b9bd8c0abc84c"}, + {file = "lxml-6.0.3-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c46a246df7fbab1f7b018c7eb361585b295ac95dec806158d9ed1e63b477f05"}, + {file = "lxml-6.0.3-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f8f004d5c601eb50ac29a110632595a4f4c50db81c715d46a43de64ef88246cb"}, + {file = "lxml-6.0.3-cp39-cp39-manylinux_2_28_i686.whl", hash = "sha256:33741ec3b4268efffae8ba40f9b64523f4489caf270bde175535e659f03af05a"}, + {file = "lxml-6.0.3-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:773c22d3de2dd5454b0f89b36d366fa0052f0e924656506c40462d8107acd00f"}, + {file = "lxml-6.0.3-cp39-cp39-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b29300eeaadf85df7f2df4bb29cadfb13b9600d1bb8053f35d82d96f9e6d088a"}, + {file = "lxml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:61399a5b01d74ec5f009762c74ab6ebf387e58393fc5d78368e12d4f577fea29"}, + {file = "lxml-6.0.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4723da3e8f4281853c2eaab161b69cc14bc9b0811be4cfa5a1de36df47e0c660"}, + {file = "lxml-6.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:8341c446fca7f6be003c60aededf2f23a53d4881cf7e0bafb9cef69c217ae26a"}, + {file = "lxml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:809726d4c72f1a902556df822c3acc5780053a12a05e16eac999392b30984c06"}, + {file = "lxml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:d1f14c1006722824c3f2158d147e520a82460b47ffdc2a84e444b3d244b65e4d"}, + {file = "lxml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:d8a8129bd502de138cdde22eac3990bde8a4efbafc72596baab67a495c48c974"}, + {file = "lxml-6.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:fddcf558bcb7a40993fb9e3ae3752d5d3a656479c71687799e43063563a2e68a"}, + {file = "lxml-6.0.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:093786037b934ef4747b0e8a0e1599fe7df7dd8246e7f07d43bba1c4c8bd7b84"}, + {file = "lxml-6.0.3-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6364aa77b13e04459df6a9d2b806465287e7540955527e75ebd5fda48532913d"}, + {file = "lxml-6.0.3-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:955550c78afb2be47755bd1b8153724292a5b539cf3f21665b310c145d08e6f8"}, + {file = "lxml-6.0.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a9a79144a8051bc5fbb223fac895b87eb67b361f27b00c2ed4a07ee34246b90"}, + {file = "lxml-6.0.3-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8243937d4673b46da90b4f5ea2627fd26842225e62e885828fdb8133aa1f7b32"}, + {file = "lxml-6.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:5892d2ef99449ebd8e30544af5bc61fd9c30e9e989093a10589766422f6c5e1a"}, + {file = "lxml-6.0.3.tar.gz", hash = "sha256:a1664c5139755df44cab3834f4400b331b02205d62d3fdcb1554f63439bf3372"}, +] + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml_html_clean"] +html5 = ["html5lib"] +htmlsoup = ["BeautifulSoup4"] + [[package]] name = "markupsafe" version = "2.1.1" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, @@ -1106,6 +1293,7 @@ version = "3.6.2" description = "Python plotting package" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "matplotlib-3.6.2-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:8d0068e40837c1d0df6e3abf1cdc9a34a6d2611d90e29610fa1d2455aeb4e2e5"}, {file = "matplotlib-3.6.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:252957e208c23db72ca9918cb33e160c7833faebf295aaedb43f5b083832a267"}, @@ -1167,6 +1355,7 @@ version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, @@ -1181,6 +1370,7 @@ version = "2.0.4" description = "A sane Markdown parser with useful plugins and renderers" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "mistune-2.0.4-py2.py3-none-any.whl", hash = "sha256:182cc5ee6f8ed1b807de6b7bb50155df7b66495412836b9a74c8fbdfc75fe36d"}, {file = "mistune-2.0.4.tar.gz", hash = "sha256:9ee0a66053e2267aba772c71e06891fa8f1af6d4b01d5e84e267b4570d4d9808"}, @@ -1192,6 +1382,7 @@ version = "0.991" description = "Optional static typing for Python" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "mypy-0.991-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab"}, {file = "mypy-0.991-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d"}, @@ -1242,6 +1433,7 @@ version = "0.4.3" description = "Experimental type system extensions for programs checked with the mypy typechecker." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, @@ -1253,6 +1445,7 @@ version = "0.4.8" description = "A web-based notebook environment for interactive computing" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "nbclassic-0.4.8-py3-none-any.whl", hash = "sha256:cbf05df5842b420d5cece0143462380ea9d308ff57c2dc0eb4d6e035b18fbfb3"}, {file = "nbclassic-0.4.8.tar.gz", hash = "sha256:c74d8a500f8e058d46b576a41e5bc640711e1032cf7541dde5f73ea49497e283"}, @@ -1280,7 +1473,7 @@ traitlets = ">=4.2.1" [package.extras] docs = ["myst-parser", "nbsphinx", "sphinx", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] json-logging = ["json-logging"] -test = ["coverage", "nbval", "pytest", "pytest-cov", "pytest-playwright", "pytest-tornasync", "requests", "requests-unixsocket", "testpath"] +test = ["coverage", "nbval", "pytest", "pytest-cov", "pytest-playwright", "pytest-tornasync", "requests", "requests-unixsocket ; sys_platform != \"win32\"", "testpath"] [[package]] name = "nbclient" @@ -1288,6 +1481,7 @@ version = "0.7.2" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false python-versions = ">=3.7.0" +groups = ["main"] files = [ {file = "nbclient-0.7.2-py3-none-any.whl", hash = "sha256:d97ac6257de2794f5397609df754fcbca1a603e94e924eb9b99787c031ae2e7c"}, {file = "nbclient-0.7.2.tar.gz", hash = "sha256:884a3f4a8c4fc24bb9302f263e0af47d97f0d01fe11ba714171b320c8ac09547"}, @@ -1310,6 +1504,7 @@ version = "7.2.6" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "nbconvert-7.2.6-py3-none-any.whl", hash = "sha256:f933e82fe48b9a421e4252249f6c0a9a9940dc555642b4729f3f1f526bb16779"}, {file = "nbconvert-7.2.6.tar.gz", hash = "sha256:c9c0e4b26326f7658ebf4cda0acc591b9727c4e3ee3ede962f70c11833b71b40"}, @@ -1319,7 +1514,6 @@ files = [ beautifulsoup4 = "*" bleach = "*" defusedxml = "*" -importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} jinja2 = ">=3.0" jupyter-core = ">=4.7" jupyterlab-pygments = "*" @@ -1348,6 +1542,7 @@ version = "5.7.0" description = "The Jupyter Notebook format" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "nbformat-5.7.0-py3-none-any.whl", hash = "sha256:1b05ec2c552c2f1adc745f4eddce1eac8ca9ffd59bb9fd859e827eaa031319f9"}, {file = "nbformat-5.7.0.tar.gz", hash = "sha256:1d4760c15c1a04269ef5caf375be8b98dd2f696e5eb9e603ec2bf091f9b0d3f3"}, @@ -1368,6 +1563,7 @@ version = "1.5.6" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"}, {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, @@ -1379,6 +1575,7 @@ version = "6.5.2" description = "A web-based notebook environment for interactive computing" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "notebook-6.5.2-py3-none-any.whl", hash = "sha256:e04f9018ceb86e4fa841e92ea8fb214f8d23c1cedfde530cc96f92446924f0e4"}, {file = "notebook-6.5.2.tar.gz", hash = "sha256:c1897e5317e225fc78b45549a6ab4b668e4c996fd03a04e938fe5e7af2bfffd0"}, @@ -1405,7 +1602,7 @@ traitlets = ">=4.2.1" [package.extras] docs = ["myst-parser", "nbsphinx", "sphinx", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] json-logging = ["json-logging"] -test = ["coverage", "nbval", "pytest", "pytest-cov", "requests", "requests-unixsocket", "selenium (==4.1.5)", "testpath"] +test = ["coverage", "nbval", "pytest", "pytest-cov", "requests", "requests-unixsocket ; sys_platform != \"win32\"", "selenium (==4.1.5)", "testpath"] [[package]] name = "notebook-shim" @@ -1413,6 +1610,7 @@ version = "0.2.2" description = "A shim layer for notebook traits and config" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "notebook_shim-0.2.2-py3-none-any.whl", hash = "sha256:9c6c30f74c4fbea6fce55c1be58e7fd0409b1c681b075dcedceb005db5026949"}, {file = "notebook_shim-0.2.2.tar.gz", hash = "sha256:090e0baf9a5582ff59b607af523ca2db68ff216da0c69956b62cab2ef4fc9c3f"}, @@ -1430,6 +1628,7 @@ version = "1.23.5" description = "NumPy is the fundamental package for array computing with Python." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "numpy-1.23.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9c88793f78fca17da0145455f0d7826bcb9f37da4764af27ac945488116efe63"}, {file = "numpy-1.23.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e9f4c4e51567b616be64e05d517c79a8a22f3606499941d97bb76f2ca59f982d"}, @@ -1467,6 +1666,7 @@ version = "7.4.0" description = "A decorator to automatically detect mismatch when overriding a method." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "overrides-7.4.0-py3-none-any.whl", hash = "sha256:3ad24583f86d6d7a49049695efe9933e67ba62f0c7625d53c59fa832ce4b8b7d"}, {file = "overrides-7.4.0.tar.gz", hash = "sha256:9502a3cca51f4fac40b5feca985b6703a5c1f6ad815588a7ca9e285b9dca6757"}, @@ -1478,6 +1678,7 @@ version = "21.3" description = "Core utilities for Python packages" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, @@ -1492,6 +1693,7 @@ version = "1.5.2" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pandas-1.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e9dbacd22555c2d47f262ef96bb4e30880e5956169741400af8b306bbb24a273"}, {file = "pandas-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e2b83abd292194f350bb04e188f9379d36b8dfac24dd445d5c87575f3beaf789"}, @@ -1524,9 +1726,8 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.20.3", markers = "python_version < \"3.10\""}, {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, - {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.21.0", markers = "python_version == \"3.10\""}, ] python-dateutil = ">=2.8.1" pytz = ">=2020.1" @@ -1540,6 +1741,7 @@ version = "1.5.0" description = "Utilities for writing pandoc filters in python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] files = [ {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, @@ -1551,6 +1753,7 @@ version = "0.8.3" description = "A Python Parser" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, @@ -1566,6 +1769,8 @@ version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform != \"win32\"" files = [ {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, @@ -1580,6 +1785,7 @@ version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, @@ -1591,6 +1797,7 @@ version = "10.0.1" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "Pillow-10.0.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a"}, {file = "Pillow-10.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d"}, @@ -1658,6 +1865,7 @@ version = "2.5.4" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, @@ -1673,6 +1881,7 @@ version = "1.0.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, @@ -1688,6 +1897,7 @@ version = "0.15.0" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "prometheus_client-0.15.0-py3-none-any.whl", hash = "sha256:db7c05cbd13a0f79975592d112320f2605a325969b270a94b71dcabc47b931d2"}, {file = "prometheus_client-0.15.0.tar.gz", hash = "sha256:be26aa452490cfcf6da953f9436e95a9f2b4d578ca80094b4458930e5f584ab1"}, @@ -1702,6 +1912,7 @@ version = "3.0.36" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.6.2" +groups = ["main"] files = [ {file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"}, {file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"}, @@ -1716,6 +1927,7 @@ version = "5.9.4" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] files = [ {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, @@ -1734,7 +1946,7 @@ files = [ ] [package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] +test = ["enum34 ; python_version <= \"3.4\"", "ipaddress ; python_version < \"3.0\"", "mock ; python_version < \"3.0\"", "pywin32 ; sys_platform == \"win32\"", "wmi ; sys_platform == \"win32\""] [[package]] name = "ptyprocess" @@ -1742,6 +1954,8 @@ version = "0.7.0" description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform != \"win32\" or os_name != \"nt\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -1753,6 +1967,7 @@ version = "0.2.2" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, @@ -1767,6 +1982,8 @@ version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] +markers = "implementation_name == \"pypy\"" files = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -1778,6 +1995,7 @@ version = "2.21" description = "C parser in Python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] files = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, @@ -1789,13 +2007,14 @@ version = "2.15.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "Pygments-2.15.0-py3-none-any.whl", hash = "sha256:77a3299119af881904cd5ecd1ac6a66214b6e9bed1f2db16993b54adede64094"}, {file = "Pygments-2.15.0.tar.gz", hash = "sha256:f7e36cffc4c517fbc252861b9a6e4644ca0e5abadf9a113c72d1358ad09b9500"}, ] [package.extras] -plugins = ["importlib-metadata"] +plugins = ["importlib-metadata ; python_version < \"3.8\""] [[package]] name = "pyparsing" @@ -1803,6 +2022,7 @@ version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.6.8" +groups = ["main", "dev"] files = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, @@ -1817,6 +2037,7 @@ version = "0.19.2" description = "Persistent/Functional/Immutable data structures" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "pyrsistent-0.19.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d6982b5a0237e1b7d876b60265564648a69b14017f3b5f908c5be2de3f9abb7a"}, {file = "pyrsistent-0.19.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:187d5730b0507d9285a96fca9716310d572e5464cadd19f22b63a6976254d77a"}, @@ -1848,6 +2069,7 @@ version = "7.2.0" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, @@ -1867,34 +2089,48 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. [[package]] name = "python-copasi" -version = "4.37.264" +version = "4.46.300" description = "COPASI Python API" optional = false python-versions = "*" -files = [ - {file = "python_copasi-4.37.264-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:feb5e6a08d1845167489f0dc046d2fea659985e61372cf1cea3801d427c74516"}, - {file = "python_copasi-4.37.264-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a3852b1654b030351a5a2f2f12b272dabc779a3effd6ee35bd3b5b8cf8f7cd5d"}, - {file = "python_copasi-4.37.264-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:643012aea17f5818ef8f481f36bda4a7d02fe942ceb7db14e6b0cefd4b776f2d"}, - {file = "python_copasi-4.37.264-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c60e08628037975e07561fb23b573233ea14b9a692ef796648fb24d6b155f660"}, - {file = "python_copasi-4.37.264-cp310-cp310-win32.whl", hash = "sha256:f5bbb453e0c8c1809f77cb27541c0b0be170ce5ace7721db97b76ca0f4993654"}, - {file = "python_copasi-4.37.264-cp310-cp310-win_amd64.whl", hash = "sha256:bf51cb2f515623731d3e4997a22596901fc84c0a94c72ab919223eded99eaac0"}, - {file = "python_copasi-4.37.264-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:17411ea3e3a1c2e807a387809d2bd2ae89759d489235e252f5a44e07e355333b"}, - {file = "python_copasi-4.37.264-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6db60217c9819cd9b91cd062a8e329c3cebacd5c0182032d9c244e50411f9f1"}, - {file = "python_copasi-4.37.264-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:145b952bccfc772846aae4e4817170b2c3b75939c404d6be1072c5a888fb375e"}, - {file = "python_copasi-4.37.264-cp37-cp37m-win32.whl", hash = "sha256:d6995873d25c5f4fe0434b2eaef908d1b2458b7e7536d053262024feb1b9df42"}, - {file = "python_copasi-4.37.264-cp37-cp37m-win_amd64.whl", hash = "sha256:97b18e21569745f0b9e06a84bd95624c959353f8fdc507a4403bee7a5635c317"}, - {file = "python_copasi-4.37.264-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:30c8bd90ab62405c2481d1498e2131bfd2c24fee8b5f21c4c5295cda889d5bc9"}, - {file = "python_copasi-4.37.264-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9b88d6368407e09c37c49bea16c2228b41310deeb326a874a379a27688dc8c4b"}, - {file = "python_copasi-4.37.264-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28ee9f80bb41ee02a0e713c9a672efbdbe141464a44190dcf69c4115393c3a10"}, - {file = "python_copasi-4.37.264-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:790ec25c0e1300002b5f4c2ef54f322e344687fe7886b1fe058b264da24414ba"}, - {file = "python_copasi-4.37.264-cp38-cp38-win32.whl", hash = "sha256:ccd81390bdd4fd6abc8045c42b4f35f08e8eb2154e3fd051d8c8a7ff94b4914d"}, - {file = "python_copasi-4.37.264-cp38-cp38-win_amd64.whl", hash = "sha256:8af99f7b8ceb27034121342b4bde313408b81f8e7213e451fd223d85de515ac9"}, - {file = "python_copasi-4.37.264-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0cc72e904a732d80d1935e38bbb94df762d7726fea9d8245f7d9cb9e6e3c9f0c"}, - {file = "python_copasi-4.37.264-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:03c969f2f44cb6d5be5fc533054dd8281ee805631edb07b4a825a2397dd1fef0"}, - {file = "python_copasi-4.37.264-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad524378a740bb0b49935f194db315045dfa9c457757b084b110a1fc4d475170"}, - {file = "python_copasi-4.37.264-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa4bebd9544903b11162acff4e5629816c0823b068bb1d362a455f411a251389"}, - {file = "python_copasi-4.37.264-cp39-cp39-win32.whl", hash = "sha256:69615d04a8fdd9659f83d73b2ff3145afe4cd878c804930052edab434300cb7c"}, - {file = "python_copasi-4.37.264-cp39-cp39-win_amd64.whl", hash = "sha256:3c6adbdbd4e8f585ce77fcefa952af074aa08ce3ccacf6e91457e09f0dcb837e"}, +groups = ["main"] +files = [ + {file = "python_copasi-4.46.300-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6fd5709ca1a78428a163d1a203fea7a0decc69fcd5f8438ddfa5bbaf2d31981"}, + {file = "python_copasi-4.46.300-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8940425b288cf5f52cd99deb69e848d6ffe99b8b02208cfcc486f19fa4918b1a"}, + {file = "python_copasi-4.46.300-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fa40e04006d540b6bca1e9cd59e16c15c96854c530c620676519b3edec12d36"}, + {file = "python_copasi-4.46.300-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f01ed153041a37b0c29d5a03c5244e0ff1874eacebe735c670ae140846dc6421"}, + {file = "python_copasi-4.46.300-cp310-cp310-win_amd64.whl", hash = "sha256:9e5d5995ea2ac11845b8e314984390a4cc38bc0ebec226b890fb173c39c64322"}, + {file = "python_copasi-4.46.300-cp310-cp310-win_arm64.whl", hash = "sha256:cb425ef95950f55ade364f7b3fad02df555e2fc061f5dd8b79c7c2e17e2e6307"}, + {file = "python_copasi-4.46.300-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:df42f6d83dfa376ef70ee53d58fb15a22f10aa1b61fd6f52892a9825d3b0044d"}, + {file = "python_copasi-4.46.300-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3109e67caea1fa1318778769ec985c1aa5878c19237e73189115cbd83b665f0e"}, + {file = "python_copasi-4.46.300-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1adaadcfd881f4dd160fdde41a03114c42c1d5205a28b4e4d66dff2f7361d66d"}, + {file = "python_copasi-4.46.300-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99d6561f0b150605d7b2782af121fbf2597786b48e0ca7139d02e2cf2f98cc89"}, + {file = "python_copasi-4.46.300-cp311-cp311-win_amd64.whl", hash = "sha256:bca6e68c47011745edaa06d4391fd102192c758540acc2fa5e5a2d2ff20d2986"}, + {file = "python_copasi-4.46.300-cp311-cp311-win_arm64.whl", hash = "sha256:5b68a8bee537e7b62d883341818cc56356cdaf64356dd50ef20bbc77845c6189"}, + {file = "python_copasi-4.46.300-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c288312bfd4841aa549df92fcf070581c2cd71d7ca1b3f6ffdb9c5c551b35bf"}, + {file = "python_copasi-4.46.300-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d5b3d6ab846e7f7ee1dd6d0bc8ae2df8b3272434ff6b30a4d38fa0745ffc45f5"}, + {file = "python_copasi-4.46.300-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29ba3be336f892c76df37c0311ce42beea6ff506db0acd1ff2ea93c357403e73"}, + {file = "python_copasi-4.46.300-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:033d21faecc6f981355e6307c1fdebc9029838cf942597caa145d870ff3f445a"}, + {file = "python_copasi-4.46.300-cp312-cp312-win_amd64.whl", hash = "sha256:1e057f94ad6bfe35bf457a7f8b6a3dbb776d44df0772e7e5dc2be54ede0fb072"}, + {file = "python_copasi-4.46.300-cp312-cp312-win_arm64.whl", hash = "sha256:d6fc0cc65a70ed6c23aad200d6501ddf13ea07515e7aab5ea376f354dabf30e1"}, + {file = "python_copasi-4.46.300-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:aba072a1ae075d04148cc37e9493ea79ac0c8474bca06b13c39521f802645a57"}, + {file = "python_copasi-4.46.300-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4355d1289de105bd51b86cd2ef64aeaa3c9921753de173eba37e5225e3268186"}, + {file = "python_copasi-4.46.300-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd98fa69c13c149b4fb86a387ef240615ee5f32b0395a38ad8efaf77eed00ee6"}, + {file = "python_copasi-4.46.300-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2a8a45ee9cf8404f950082425cb8f11a53cf70dccc5cb95082ab166d70fe5b"}, + {file = "python_copasi-4.46.300-cp313-cp313-win_amd64.whl", hash = "sha256:63cacffe4a651c42e14d1d3f5dc156602df0c150fde1bcf62f6652043c63efd2"}, + {file = "python_copasi-4.46.300-cp313-cp313-win_arm64.whl", hash = "sha256:c889b184290d6d7ef1cd09daa3b01656c567ef4781cd1c9e1a21b27534661c83"}, + {file = "python_copasi-4.46.300-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e25a9159f8958550a75546e8fe734d621cb616ac108761e98179d948c957bd05"}, + {file = "python_copasi-4.46.300-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1bd8bdfc6e4dc16202a8d867f87012a7861503df952989422cd013e3dc6e8062"}, + {file = "python_copasi-4.46.300-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44d691f5960b72c0265f2c360bb1b74e3ceaafdfe175c13f3f715d18684a6268"}, + {file = "python_copasi-4.46.300-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a08864ab379d893ea13efd4691b6dd924131dc98530180d9df86068cabe4ba1a"}, + {file = "python_copasi-4.46.300-cp314-cp314-win_amd64.whl", hash = "sha256:f79af84864bc12fd7d64050a0d84cf27f8d2a2f3bf7fe3dc36a652873ebe2f3d"}, + {file = "python_copasi-4.46.300-cp314-cp314-win_arm64.whl", hash = "sha256:b858704aa061c059d6a21a505c8657b65bfdbd412724bfe414a4cb83bfbfb595"}, + {file = "python_copasi-4.46.300-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2659dc1a983779e5c8d64bf360f4eb0ca169ad8a362d7639c800a5d6d7e4d529"}, + {file = "python_copasi-4.46.300-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18d878482d15f514be7a84131f576718a11c59869ff7569a7a86b9f8c2744bd5"}, + {file = "python_copasi-4.46.300-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:554f4fa303e1cf9742d084d7a33bdaf74ff0531ae4e3753624226e5c4d11234a"}, + {file = "python_copasi-4.46.300-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2f2a928bf697baed5579c8aa005bdb21078c8e6f2798685c0409242e7f8c656e"}, + {file = "python_copasi-4.46.300-cp39-cp39-win_amd64.whl", hash = "sha256:00ce8b8eb18833d4fee3edb4b1db3b18ae3d06569204c87d2a67bc3af61b123e"}, + {file = "python_copasi-4.46.300-cp39-cp39-win_arm64.whl", hash = "sha256:5fa56797ccfa4b2fd8ddd99bcbb353f7e70af3f2369c97cd291d6b7e2ebdc720"}, ] [[package]] @@ -1903,6 +2139,7 @@ version = "2.8.2" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, @@ -1917,6 +2154,7 @@ version = "2.0.7" description = "A python library adding a json log formatter" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"}, {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, @@ -1928,6 +2166,7 @@ version = "2022.6" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, @@ -1939,6 +2178,8 @@ version = "305" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\"" files = [ {file = "pywin32-305-cp310-cp310-win32.whl", hash = "sha256:421f6cd86e84bbb696d54563c48014b12a23ef95a14e0bdba526be756d89f116"}, {file = "pywin32-305-cp310-cp310-win_amd64.whl", hash = "sha256:73e819c6bed89f44ff1d690498c0a811948f73777e5f97c494c152b850fad478"}, @@ -1962,6 +2203,8 @@ version = "2.0.9" description = "Pseudo terminal support for Windows from Python." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "os_name == \"nt\"" files = [ {file = "pywinpty-2.0.9-cp310-none-win_amd64.whl", hash = "sha256:30a7b371446a694a6ce5ef906d70ac04e569de5308c42a2bdc9c3bc9275ec51f"}, {file = "pywinpty-2.0.9-cp311-none-win_amd64.whl", hash = "sha256:d78ef6f4bd7a6c6f94dc1a39ba8fb028540cc39f5cb593e756506db17843125f"}, @@ -1977,6 +2220,7 @@ version = "6.0" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, @@ -2026,6 +2270,7 @@ version = "24.0.1" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "pyzmq-24.0.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:28b119ba97129d3001673a697b7cce47fe6de1f7255d104c2f01108a5179a066"}, {file = "pyzmq-24.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bcbebd369493d68162cddb74a9c1fcebd139dfbb7ddb23d8f8e43e6c87bac3a6"}, @@ -2113,6 +2358,7 @@ version = "5.4.0" description = "Jupyter Qt console" optional = false python-versions = ">= 3.7" +groups = ["main"] files = [ {file = "qtconsole-5.4.0-py3-none-any.whl", hash = "sha256:be13560c19bdb3b54ed9741a915aa701a68d424519e8341ac479a91209e694b2"}, {file = "qtconsole-5.4.0.tar.gz", hash = "sha256:57748ea2fd26320a0b77adba20131cfbb13818c7c96d83fafcb110ff55f58b35"}, @@ -2138,6 +2384,7 @@ version = "2.3.0" description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "QtPy-2.3.0-py3-none-any.whl", hash = "sha256:8d6d544fc20facd27360ea189592e6135c614785f0dec0b4f083289de6beb408"}, {file = "QtPy-2.3.0.tar.gz", hash = "sha256:0603c9c83ccc035a4717a12908bf6bc6cb22509827ea2ec0e94c2da7c9ed57c5"}, @@ -2155,6 +2402,7 @@ version = "0.1.4" description = "A pure python RFC3339 validator" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] files = [ {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, @@ -2169,6 +2417,7 @@ version = "0.1.1" description = "Pure python rfc3986 validator" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] files = [ {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, @@ -2180,6 +2429,7 @@ version = "12.6.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.6.3,<4.0.0" +groups = ["main"] files = [ {file = "rich-12.6.0-py3-none-any.whl", hash = "sha256:a4eb26484f2c82589bd9a17c73d32a010b1e29d89f1604cd9bf3a2097b81bb5e"}, {file = "rich-12.6.0.tar.gz", hash = "sha256:ba3a3775974105c221d31141f2c116f4fd65c5ceb0698657a11e9f295ec93fd0"}, @@ -2192,21 +2442,86 @@ pygments = ">=2.6.0,<3.0.0" [package.extras] jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] +[[package]] +name = "scipy" +version = "1.15.3" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"}, + {file = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"}, + {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f"}, + {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92"}, + {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82"}, + {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40"}, + {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e"}, + {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c"}, + {file = "scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1"}, + {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889"}, + {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982"}, + {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9"}, + {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594"}, + {file = "scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c"}, + {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45"}, + {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49"}, + {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e"}, + {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539"}, + {file = "scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730"}, + {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825"}, + {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7"}, + {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11"}, + {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126"}, + {file = "scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb"}, + {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723"}, + {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb"}, + {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4"}, + {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5"}, + {file = "scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca"}, + {file = "scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf"}, +] + +[package.dependencies] +numpy = ">=1.23.5,<2.5" + +[package.extras] +dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"] +doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"] +test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + [[package]] name = "send2trash" version = "1.8.2" description = "Send file to trash natively under Mac OS X, Windows and Linux" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +groups = ["main"] files = [ {file = "Send2Trash-1.8.2-py3-none-any.whl", hash = "sha256:a384719d99c07ce1eefd6905d2decb6f8b7ed054025bb0e618919f945de4f679"}, {file = "Send2Trash-1.8.2.tar.gz", hash = "sha256:c132d59fa44b9ca2b1699af5c86f57ce9f4c5eb56629d5d55fbb7a35f84e2312"}, ] [package.extras] -nativelib = ["pyobjc-framework-Cocoa", "pywin32"] -objc = ["pyobjc-framework-Cocoa"] -win32 = ["pywin32"] +nativelib = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\"", "pywin32 ; sys_platform == \"win32\""] +objc = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\""] +win32 = ["pywin32 ; sys_platform == \"win32\""] [[package]] name = "shellingham" @@ -2214,6 +2529,7 @@ version = "1.5.4" description = "Tool to Detect Surrounding Shell" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, @@ -2225,6 +2541,7 @@ version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["main"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -2236,6 +2553,7 @@ version = "1.3.0" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, @@ -2247,6 +2565,7 @@ version = "2.3.2.post1" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, @@ -2258,6 +2577,7 @@ version = "0.6.2" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"}, {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"}, @@ -2277,6 +2597,7 @@ version = "0.17.1" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "terminado-0.17.1-py3-none-any.whl", hash = "sha256:8650d44334eba354dd591129ca3124a6ba42c3d5b70df5051b6921d506fdaeae"}, {file = "terminado-0.17.1.tar.gz", hash = "sha256:6ccbbcd3a4f8a25a5ec04991f39a0b8db52dfcd487ea0e578d977e6752380333"}, @@ -2297,6 +2618,7 @@ version = "1.2.1" description = "A tiny CSS parser" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, @@ -2315,6 +2637,8 @@ version = "2.0.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, @@ -2326,6 +2650,7 @@ version = "6.3.3" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">= 3.8" +groups = ["main"] files = [ {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, @@ -2346,6 +2671,7 @@ version = "5.6.0" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "traitlets-5.6.0-py3-none-any.whl", hash = "sha256:1410755385d778aed847d68deb99b3ba30fbbf489e17a1e8cbb753060d5cce73"}, {file = "traitlets-5.6.0.tar.gz", hash = "sha256:10b6ed1c9cedee83e795db70a8b9c2db157bb3778ec4587a349ecb7ef3b1033b"}, @@ -2361,6 +2687,7 @@ version = "0.7.0" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "typer-0.7.0-py3-none-any.whl", hash = "sha256:b5e704f4e48ec263de1c0b3a2387cd405a13767d2f907f44c1a08cbad96f606d"}, {file = "typer-0.7.0.tar.gz", hash = "sha256:ff797846578a9f2a201b53442aedeb543319466870fbe1c701eab66dd7681165"}, @@ -2384,6 +2711,7 @@ version = "2.8.19.14" description = "Typing stubs for python-dateutil" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "types-python-dateutil-2.8.19.14.tar.gz", hash = "sha256:1f4f10ac98bb8b16ade9dbee3518d9ace017821d94b057a425b069f834737f4b"}, {file = "types_python_dateutil-2.8.19.14-py3-none-any.whl", hash = "sha256:f977b8de27787639986b4e28963263fd0e5158942b3ecef91b9335c130cb1ce9"}, @@ -2395,6 +2723,7 @@ version = "4.4.0" description = "Backported and Experimental Type Hints for Python 3.7+" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, @@ -2406,6 +2735,7 @@ version = "1.3.0" description = "RFC 6570 URI Template Processor" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, @@ -2420,6 +2750,7 @@ version = "0.2.5" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, @@ -2431,6 +2762,7 @@ version = "1.13" description = "A library for working with the color formats defined by HTML and CSS." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "webcolors-1.13-py3-none-any.whl", hash = "sha256:29bc7e8752c0a1bd4a1f03c14d6e6a72e93d82193738fa860cbff59d0fcc11bf"}, {file = "webcolors-1.13.tar.gz", hash = "sha256:c225b674c83fa923be93d235330ce0300373d02885cef23238813b0d5668304a"}, @@ -2446,6 +2778,7 @@ version = "0.5.1" description = "Character encoding aliases for legacy web content" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, @@ -2457,6 +2790,7 @@ version = "1.4.2" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "websocket-client-1.4.2.tar.gz", hash = "sha256:d6e8f90ca8e2dd4e8027c4561adeb9456b54044312dba655e7cae652ceb9ae59"}, {file = "websocket_client-1.4.2-py3-none-any.whl", hash = "sha256:d6b06432f184438d99ac1f456eaf22fe1ade524c3dd16e661142dc54e9cba574"}, @@ -2473,27 +2807,13 @@ version = "4.0.3" description = "Jupyter interactive widgets for Jupyter Notebook" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "widgetsnbextension-4.0.3-py3-none-any.whl", hash = "sha256:7f3b0de8fda692d31ef03743b598620e31c2668b835edbd3962d080ccecf31eb"}, {file = "widgetsnbextension-4.0.3.tar.gz", hash = "sha256:34824864c062b0b3030ad78210db5ae6a3960dfb61d5b27562d6631774de0286"}, ] -[[package]] -name = "zipp" -version = "3.11.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.7" -files = [ - {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, - {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - [metadata] -lock-version = "2.0" -python-versions = "^3.9" -content-hash = "421aec668be9be404488993f689d6eb93084d4b5bd306130fd79656dd2660513" +lock-version = "2.1" +python-versions = "^3.10" +content-hash = "4458d473de4d9f8bc9302ae617aca7a8957d773130068de1c4eda1e971480122" diff --git a/pythonCopasiOpt/vcell-opt/pyproject.toml b/pythonCopasiOpt/vcell-opt/pyproject.toml index 8601fc6291..8aad7e030b 100644 --- a/pythonCopasiOpt/vcell-opt/pyproject.toml +++ b/pythonCopasiOpt/vcell-opt/pyproject.toml @@ -6,13 +6,13 @@ authors = ["Jim Schaff "] readme = "README.md" [tool.poetry.dependencies] -python = "^3.9" -copasi-basico = "0.40" -python-copasi = "4.37.264" +python = "^3.10" +copasi-basico = "^0.86" +python-copasi = "^4.45.298" jupyter = "^1.0.0" typer = {extras = ["all"], version = "^0.7.0"} -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] pytest = "^7.2.0" mypy = "^0.991" diff --git a/pythonCopasiOpt/vcell-opt/tests/vcellopt_test.py b/pythonCopasiOpt/vcell-opt/tests/vcellopt_test.py index e76aca9c03..205fb78af4 100644 --- a/pythonCopasiOpt/vcell-opt/tests/vcellopt_test.py +++ b/pythonCopasiOpt/vcell-opt/tests/vcellopt_test.py @@ -1,6 +1,8 @@ import json +import multiprocessing import os import tempfile +import time from pathlib import Path from typing import List @@ -42,10 +44,9 @@ def test_run() -> None: # define parameter estimation report format, note that header and footer are omitted to ease parsing # basico.add_report('parest report', task=basico.T.PARAMETER_ESTIMATION, + separator='\t', body=['CN=Root,Vector=TaskList[Parameter Estimation],Problem=Parameter Estimation,Reference=Function Evaluations', - '\\\t', 'CN=Root,Vector=TaskList[Parameter Estimation],Problem=Parameter Estimation,Reference=Best Value', - '\\\t', 'CN=Root,Vector=TaskList[Parameter Estimation],Problem=Parameter Estimation,Reference=Best Parameters' ], ) @@ -55,7 +56,8 @@ def test_run() -> None: param_names: List[str] = [param_desc.name for param_desc in vcell_opt_problem.parameter_description_list] f_report_file.write(json.dumps(param_names)+"\n") - basico.assign_report("parest report", task=basico.T.PARAMETER_ESTIMATION, filename=str(report_file), append=True) + basico.assign_report("parest report", task=basico.T.PARAMETER_ESTIMATION, filename=str(report_file), append=True, + confirm_overwrite=False) fit_items = get_fit_parameters(vcell_opt_problem) basico.set_fit_parameters(fit_items) @@ -201,3 +203,63 @@ def test_solver() -> None: if result_file.exists(): os.remove(result_file) + + +def _run_solver_in_subprocess(opt_file: str, report_file: str, result_file: str) -> None: + """Target function for multiprocessing — runs the solver in a separate process.""" + optService.run_command(opt_file=Path(opt_file), report_file=Path(report_file), result_file=Path(result_file)) + + +def test_incremental_report_writing() -> None: + """Verify that the report file is written incrementally during optimization, + not buffered until completion. This requires confirm_overwrite=False in + basico.assign_report() (the default True causes COPASI to buffer all output). + + Uses multiprocessing so the solver runs in a separate process (with its own GIL), + allowing the main process to monitor the report file size during execution. + """ + test_data_dir = Path(__file__).resolve().parent.parent / "test_data" + opt_file = test_data_dir / "optproblem.json" + report_file = test_data_dir / "incremental_test.report" + result_file = test_data_dir / "incremental_test.json" + + if report_file.exists(): + os.remove(report_file) + if result_file.exists(): + os.remove(result_file) + + # Run the solver in a separate process + proc = multiprocessing.Process( + target=_run_solver_in_subprocess, + args=(str(opt_file), str(report_file), str(result_file)) + ) + proc.start() + + # Monitor the report file size from the main process + file_sizes: List[int] = [] + while proc.is_alive(): + if report_file.exists(): + file_sizes.append(report_file.stat().st_size) + time.sleep(0.01) # 10ms polling + + proc.join(timeout=30) + assert proc.exitcode == 0, f"Solver process failed with exit code {proc.exitcode}" + + unique_sizes = sorted(set(file_sizes)) + print(f"Sampled {len(file_sizes)} times, unique file sizes: {unique_sizes}") + + # With confirm_overwrite=False, COPASI flushes progress incrementally. + # We expect at least 3 distinct sizes: header-only, intermediate progress, final. + # With confirm_overwrite=True (old behavior), we'd see only the header size + # until the solver finishes, then a single jump to the final size (2 unique sizes). + assert len(unique_sizes) >= 3, ( + f"Expected at least 3 distinct file sizes (header, intermediate, final) " + f"but got {len(unique_sizes)}: {unique_sizes}. " + f"COPASI may be buffering output — check confirm_overwrite setting." + ) + + # Cleanup + if report_file.exists(): + os.remove(report_file) + if result_file.exists(): + os.remove(result_file) diff --git a/pythonCopasiOpt/vcell-opt/vcell_opt/optService.py b/pythonCopasiOpt/vcell-opt/vcell_opt/optService.py index 0caabc7bb7..7ba8979064 100644 --- a/pythonCopasiOpt/vcell-opt/vcell_opt/optService.py +++ b/pythonCopasiOpt/vcell-opt/vcell_opt/optService.py @@ -43,11 +43,10 @@ def run_command(opt_file: Path = typer.Argument(..., file_okay=True, dir_okay=Fa # define parameter estimation report format, note that header and footer are omitted to ease parsing # basico.add_report('parest report', task=basico.T.PARAMETER_ESTIMATION, + separator='\t', body=[ 'CN=Root,Vector=TaskList[Parameter Estimation],Problem=Parameter Estimation,Reference=Function Evaluations', - '\\\t', 'CN=Root,Vector=TaskList[Parameter Estimation],Problem=Parameter Estimation,Reference=Best Value', - '\\\t', 'CN=Root,Vector=TaskList[Parameter Estimation],Problem=Parameter Estimation,Reference=Best Parameters' ], ) @@ -57,7 +56,8 @@ def run_command(opt_file: Path = typer.Argument(..., file_okay=True, dir_okay=Fa param_names: List[str] = [param_desc.name for param_desc in opt_problem.parameter_description_list] f_report_file.write(json.dumps(param_names)+"\n") - basico.assign_report("parest report", task=basico.T.PARAMETER_ESTIMATION, filename=str(report_file), append=True) + basico.assign_report("parest report", task=basico.T.PARAMETER_ESTIMATION, filename=str(report_file), append=True, + confirm_overwrite=False) fit_items = get_fit_parameters(opt_problem) basico.set_fit_parameters(fit_items) diff --git a/tools/openapi-clients.sh b/tools/openapi-clients.sh new file mode 100755 index 0000000000..afe02de664 --- /dev/null +++ b/tools/openapi-clients.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +set -e + +# +# Regenerate OpenAPI spec and/or generate API clients (Java, Python, TypeScript-Angular). +# +# Usage: +# ./tools/openapi-clients.sh # generate clients from existing tools/openapi.yaml +# ./tools/openapi-clients.sh --update-spec # rebuild vcell-rest, copy spec, then generate clients +# +# The --update-spec flag runs 'mvn clean install -DskipTests' to build vcell-rest, +# which produces the OpenAPI spec via SmallRye OpenAPI, then copies it to tools/openapi.yaml. +# Without the flag, it assumes tools/openapi.yaml is already up to date. +# +# After running, verify downstream compilation: +# mvn compile test-compile -pl vcell-rest -am +# + +generatorCliImage=openapitools/openapi-generator-cli:v7.1.0 + +scriptDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +parentDir="$(dirname "$scriptDir")" + +# Parse arguments +UPDATE_SPEC=false +for arg in "$@"; do + case $arg in + --update-spec) + UPDATE_SPEC=true + ;; + -h|--help) + echo "Usage: $0 [--update-spec]" + echo "" + echo " --update-spec Build vcell-rest and regenerate tools/openapi.yaml before generating clients" + echo " (default) Generate clients from existing tools/openapi.yaml" + exit 0 + ;; + *) + echo "Unknown argument: $arg" + echo "Usage: $0 [--update-spec]" + exit 1 + ;; + esac +done + +# Step 1: Optionally rebuild and update the OpenAPI spec +if [ "$UPDATE_SPEC" = true ]; then + echo "==> Building vcell-rest to generate OpenAPI spec..." + pushd "$parentDir" > /dev/null + mvn clean install dependency:copy-dependencies -DskipTests=true + popd > /dev/null + + echo "==> Copying generated spec to tools/openapi.yaml" + cp "$parentDir/vcell-rest/target/generated/openapi.yaml" "$scriptDir/openapi.yaml" +fi + +# Step 2: Validate the OpenAPI spec +echo "==> Validating openapi.yaml..." +docker run --rm -v "${scriptDir}:/local" ${generatorCliImage} validate -i /local/openapi.yaml --recommend +if [ $? -ne 0 ]; then + echo "openapi.yaml is not valid" + exit 1 +fi + +# Step 3: Generate Java client +echo "==> Generating Java client (vcell-restclient)..." +docker run --rm -v "${parentDir}:/vcell" \ + ${generatorCliImage} \ + generate \ + -g java \ + -i /vcell/tools/openapi.yaml \ + -o /vcell/vcell-restclient \ + -c /vcell/tools/java-config.yaml + +# Apply patch for FieldDataResourceApi +pushd "${parentDir}" > /dev/null || { echo "Failed to cd to ${parentDir}"; exit 1; } +if ! git apply "${scriptDir}/FieldDataResourceApi.patch"; then + echo "Failed to apply FieldDataResourceApi.patch" + exit 1 +fi +popd > /dev/null || { echo "Failed to return to previous directory"; exit 1; } + +# Step 4: Generate Python client +echo "==> Generating Python client (python-restclient)..." +docker run --rm -v "${parentDir}:/vcell" \ + ${generatorCliImage} generate \ + -g python \ + -i /vcell/tools/openapi.yaml \ + -o /vcell/python-restclient \ + -c /vcell/tools/python-config.yaml + +# Apply Python import fixes +"${scriptDir}/python-fix.sh" + +# Step 5: Generate TypeScript-Angular client +echo "==> Generating TypeScript-Angular client (webapp-ng)..." +docker run --rm -v "${parentDir}:/vcell" \ + ${generatorCliImage} generate \ + -g typescript-angular \ + -i /vcell/tools/openapi.yaml \ + -o /vcell/webapp-ng/src/app/core/modules/openapi \ + -c /vcell/tools/typescript-angular-config.yaml + +echo "==> Done. Verify downstream compilation with:" +echo " mvn compile test-compile -pl vcell-rest -am" diff --git a/tools/openapi.yaml b/tools/openapi.yaml index 10dd80a4d2..e70d579b38 100644 --- a/tools/openapi.yaml +++ b/tools/openapi.yaml @@ -1538,6 +1538,158 @@ paths: application/json: schema: $ref: '#/components/schemas/VCellHTTPError' + /api/v1/optimization: + get: + tags: + - Optimization Resource + summary: List optimization jobs for the authenticated user + operationId: listOptimizationJobs + responses: + "200": + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OptimizationJobStatus' + "401": + description: Not Authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + "403": + description: Not Allowed + "500": + description: Data Access Exception + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + security: + - openId: + - user + post: + tags: + - Optimization Resource + summary: Submit a new parameter estimation optimization job + operationId: submitOptimization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OptProblem' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/OptimizationJobStatus' + "401": + description: Not Authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + "403": + description: Not Allowed + "500": + description: Data Access Exception + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + security: + - openId: + - user + /api/v1/optimization/{optId}: + get: + tags: + - Optimization Resource + summary: "Get status, progress, or results of an optimization job" + operationId: getOptimizationStatus + parameters: + - name: optId + in: path + required: true + schema: + format: int64 + type: integer + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/OptimizationJobStatus' + "401": + description: Not Authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + "403": + description: Not Allowed + "404": + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + "500": + description: Data Access Exception + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + security: + - openId: + - user + /api/v1/optimization/{optId}/stop: + post: + tags: + - Optimization Resource + summary: Stop a running optimization job + operationId: stopOptimization + parameters: + - name: optId + in: path + required: true + schema: + format: int64 + type: integer + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/OptimizationJobStatus' + "401": + description: Not Authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + "403": + description: Not Allowed + "404": + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + "500": + description: Data Access Exception + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + security: + - openId: + - user /api/v1/publications: get: tags: @@ -2404,6 +2556,63 @@ components: z: format: double type: number + CopasiOptimizationMethod: + type: object + properties: + optimizationMethodType: + $ref: '#/components/schemas/CopasiOptimizationMethodOptimizationMethodType' + optimizationParameter: + type: array + items: + $ref: '#/components/schemas/CopasiOptimizationParameter' + CopasiOptimizationMethodOptimizationMethodType: + enum: + - SRES + - evolutionaryProgram + - geneticAlgorithm + - geneticAlgorithmSR + - hookeJeeves + - levenbergMarquardt + - nelderMead + - particleSwarm + - praxis + - randomSearch + - simulatedAnnealing + - steepestDescent + - truncatedNewton + type: string + CopasiOptimizationParameter: + type: object + properties: + dataType: + $ref: '#/components/schemas/CopasiOptimizationParameterDataType' + paramType: + $ref: '#/components/schemas/CopasiOptimizationParameterParamType' + value: + format: double + type: number + CopasiOptimizationParameterDataType: + enum: + - double + - int + type: string + CopasiOptimizationParameterParamType: + enum: + - coolingFactor + - iterationLimit + - numberOfGenerations + - numberOfIterations + - pf + - populationSize + - randomNumberGenerator + - rho + - scale + - seed + - startTemperature + - stdDeviation + - swarmSize + - tolerance + type: string Curve: required: - type @@ -2980,6 +3189,92 @@ components: $ref: '#/components/schemas/ExportableDataType' datasetName: type: string + OptJobStatus: + enum: + - SUBMITTED + - QUEUED + - RUNNING + - COMPLETE + - FAILED + - STOPPED + type: string + OptProblem: + type: object + properties: + copasiOptimizationMethod: + $ref: '#/components/schemas/CopasiOptimizationMethod' + dataSet: + type: array + items: + type: array + items: + format: double + type: number + mathModelSbmlContents: + type: string + numberOfOptimizationRuns: + format: int32 + type: integer + parameterDescriptionList: + type: array + items: + $ref: '#/components/schemas/ParameterDescription' + referenceVariable: + type: array + items: + $ref: '#/components/schemas/ReferenceVariable' + OptProgressItem: + type: object + properties: + numFunctionEvaluations: + format: int32 + type: integer + objFuncValue: + format: double + type: number + OptProgressReport: + type: object + properties: + bestParamValues: + type: object + additionalProperties: + format: double + type: number + progressItems: + type: array + items: + $ref: '#/components/schemas/OptProgressItem' + OptResultSet: + type: object + properties: + numFunctionEvaluations: + format: int32 + type: integer + objectiveFunction: + format: double + type: number + optParameterValues: + type: object + additionalProperties: + format: double + type: number + optProgressReport: + $ref: '#/components/schemas/OptProgressReport' + OptimizationJobStatus: + type: object + properties: + id: + $ref: '#/components/schemas/KeyValue' + status: + $ref: '#/components/schemas/OptJobStatus' + statusMessage: + type: string + htcJobId: + type: string + progressReport: + $ref: '#/components/schemas/OptProgressReport' + results: + $ref: '#/components/schemas/Vcellopt' Origin: type: object properties: @@ -2998,6 +3293,23 @@ components: type: number xml: attribute: true + ParameterDescription: + type: object + properties: + initialValue: + format: double + type: number + maxValue: + format: double + type: number + minValue: + format: double + type: number + name: + type: string + scale: + format: double + type: number Publication: type: object properties: @@ -3080,6 +3392,18 @@ components: items: format: int64 type: integer + ReferenceVariable: + type: object + properties: + referenceVariableType: + $ref: '#/components/schemas/ReferenceVariableReferenceVariableType' + varName: + type: string + ReferenceVariableReferenceVariableType: + enum: + - dependent + - independent + type: string SPECIAL_CLAIM: enum: - admins @@ -3538,6 +3862,24 @@ components: type: string typeName: type: string + Vcellopt: + type: object + properties: + optProblem: + $ref: '#/components/schemas/OptProblem' + optResultSet: + $ref: '#/components/schemas/OptResultSet' + status: + $ref: '#/components/schemas/VcelloptStatus' + statusMessage: + type: string + VcelloptStatus: + enum: + - complete + - failed + - queued + - running + type: string Version: type: object properties: diff --git a/vcell-api/src/main/java/org/vcell/rest/VCellApiApplication.java b/vcell-api/src/main/java/org/vcell/rest/VCellApiApplication.java index c086cfdaf8..428acb04fe 100644 --- a/vcell-api/src/main/java/org/vcell/rest/VCellApiApplication.java +++ b/vcell-api/src/main/java/org/vcell/rest/VCellApiApplication.java @@ -91,10 +91,6 @@ public enum AuthenticationPolicy { public static final String RPC = "rpc"; - public static final String OPTIMIZATION = "optimization"; - public static final String RUNOPTIMIZATION = "run"; - public static final String OPTIMIZATIONID = "optimizationid"; - public static final String PUBLICATION = "publication"; public static final String PUBLICATIONID = "publicationid"; @@ -288,8 +284,6 @@ public Restlet createInboundRoot() { rootRouter.attach(PATH_PREFIX+"/"+SCRIPTS, new Directory(getContext(), ROOT_URI)); rootRouter.attach(PATH_PREFIX+"/"+ACCESSTOKENRESOURCE, new AuthenticationTokenRestlet(getContext())); rootRouter.attach(PATH_PREFIX+"/"+WEBAPP, new Directory(getContext(), WEBAPP_URI)); - rootRouter.attach(PATH_PREFIX+"/"+OPTIMIZATION, OptimizationRunServerResource.class); - rootRouter.attach(PATH_PREFIX+"/"+OPTIMIZATION+"/{"+OPTIMIZATIONID+"}", OptimizationRunServerResource.class); rootRouter.attach(PATH_PREFIX+"/"+PUBLICATION, PublicationsServerResource.class); rootRouter.attach(PATH_PREFIX+"/"+PUBLICATION+"/{"+PUBLICATIONID+"}", PublicationServerResource.class); rootRouter.attach(PATH_PREFIX+"/"+BIOMODEL, BiomodelsServerResource.class); diff --git a/vcell-api/src/main/java/org/vcell/rest/common/OptimizationRunResource.java b/vcell-api/src/main/java/org/vcell/rest/common/OptimizationRunResource.java deleted file mode 100644 index 7629a352b0..0000000000 --- a/vcell-api/src/main/java/org/vcell/rest/common/OptimizationRunResource.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.vcell.rest.common; - -import org.json.JSONException; -import org.restlet.ext.json.JsonRepresentation; -import org.restlet.representation.Representation; -import org.restlet.resource.Get; -import org.restlet.resource.Post; - -public interface OptimizationRunResource { - - @Get("json") - public JsonRepresentation get_json(); - - /** - * runs the optimization problem and redirects to the solution. - */ - @Post - public Representation run(Representation OptRunJson) throws JSONException; - -} diff --git a/vcell-api/src/main/java/org/vcell/rest/server/OptimizationRunServerResource.java b/vcell-api/src/main/java/org/vcell/rest/server/OptimizationRunServerResource.java deleted file mode 100644 index 80774f2cdb..0000000000 --- a/vcell-api/src/main/java/org/vcell/rest/server/OptimizationRunServerResource.java +++ /dev/null @@ -1,274 +0,0 @@ -package org.vcell.rest.server; - -import cbit.vcell.resource.PropertyLoader; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.json.JSONObject; -import org.restlet.data.MediaType; -import org.restlet.data.Status; -import org.restlet.ext.json.JsonRepresentation; -import org.restlet.representation.Representation; -import org.restlet.representation.StringRepresentation; -import org.restlet.resource.Post; -import org.restlet.resource.ResourceException; -import org.restlet.resource.ServerResource; -import org.vcell.optimization.OptMessage; -import org.vcell.optimization.jtd.OptProblem; -import org.vcell.rest.VCellApiApplication; -import org.vcell.rest.common.OptimizationRunResource; - -import java.io.EOFException; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.net.Socket; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Hashtable; -import java.util.LinkedHashMap; -import java.util.Map.Entry; - -public class OptimizationRunServerResource extends AbstractServerResource implements OptimizationRunResource { - - private final static Logger lg = LogManager.getLogger(OptimizationRunServerResource.class); - - private static class OptSocketStreams{ - public Socket optSocket; - public ObjectInputStream ois; - public ObjectOutputStream oos; - public String optID; - public OptSocketStreams(Socket optSocket, ObjectInputStream ois, ObjectOutputStream oos) { - super(); - this.optSocket = optSocket; - this.ois = ois; - this.oos = oos; - } - public void closeAll(String optID) { - paramOptActiveSockets.remove(optID); - try{ois.close();}catch(Exception e2) { lg.error(e2.getMessage(), e2); } - try{oos.close();}catch(Exception e2) { lg.error(e2.getMessage(), e2); } - try{optSocket.close();}catch(Exception e2) { lg.error(e2.getMessage(), e2); } - } - public OptMessage.OptResponseMessage sendCommand(OptMessage.OptCommandMessage optCommandMessage) throws IOException,ClassNotFoundException{ - lg.info("sending command "+optCommandMessage+" with ID="+optCommandMessage.optID); - oos.writeObject(optCommandMessage); - lg.info("reading response for command "+optCommandMessage+" with ID="+optCommandMessage.optID); - try { - OptMessage.OptResponseMessage response = (OptMessage.OptResponseMessage) ois.readObject(); - lg.info("responded with "+response+" with ID="+response.optID); - return response; - } catch (EOFException | SocketException e){ - lg.error(e.getMessage(), e); - throw e; - } - } - public static OptSocketStreams create(String ipnum) throws UnknownHostException, IOException { - Socket optSocket = new Socket(ipnum, 8877); - lg.info("Client connected"); - ObjectOutputStream os = new ObjectOutputStream(optSocket.getOutputStream()); - ObjectInputStream objIS = new ObjectInputStream(optSocket.getInputStream()); - lg.info("got streams"); - return new OptSocketStreams(optSocket, objIS, os); - } - } - - private static Hashtable paramOptActiveSockets = new Hashtable<>(); - private static final int MAX_ENTRIES = 10; - private static LinkedHashMap paramOptResults = new LinkedHashMap() { - @Override - protected boolean removeEldestEntry(Entry eldest) { - return size() > MAX_ENTRIES; - } - }; - - private String submitOptProblem(Representation optProblemJsonRep,ServerResource serverResource) throws ResourceException { - synchronized (paramOptActiveSockets) { - if (paramOptActiveSockets.size() >= 100) { - String[] keys = paramOptActiveSockets.keySet().toArray(new String[0]); - for (int i = 0; i < keys.length; i++) { - OptSocketStreams optSocketStreams = paramOptActiveSockets.get(keys[i]); - String optID = keys[i]; - try { - // simple status query - so that we can close the connection and cache the results. - OptMessage.OptResponseMessage response = optSocketStreams.sendCommand(new OptMessage.OptJobQueryCommandMessage(optID)); - if (response instanceof OptMessage.OptErrorResponseMessage) { - OptMessage.OptErrorResponseMessage errorResponse = (OptMessage.OptErrorResponseMessage) response; - throw new RuntimeException("Failed to query optimization ID=" + optID + ": " + errorResponse.errorMessage); - } else if (response instanceof OptMessage.OptJobStatusResponseMessage) { - OptMessage.OptJobStatusResponseMessage statusResponse = (OptMessage.OptJobStatusResponseMessage) response; - if (statusResponse.status == OptMessage.OptJobMessageStatus.FAILED) { - throw new RuntimeException("job for optimization ID=" + optID + " failed: " + statusResponse.statusMessage); - } - } else if (response instanceof OptMessage.OptJobSolutionResponseMessage) { - OptMessage.OptJobSolutionResponseMessage solutionResponse = (OptMessage.OptJobSolutionResponseMessage) response; - paramOptResults.put(optID, new JsonRepresentation(solutionResponse.optRunJsonString)); - break; - } - } catch (Exception e) {//ioError socket closed - lg.error(e.getMessage(), e); - optSocketStreams.closeAll(optSocketStreams.optID); - } - } - if (paramOptActiveSockets.size() >= 100) { - throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Too many active optimization jobs, try again later"); - } - } - } - // VCellApiApplication application = ((VCellApiApplication)getApplication()); - // User vcellUser = application.getVCellUser(getChallengeResponse(),AuthenticationPolicy.ignoreInvalidCredentials); - if (optProblemJsonRep!=null && optProblemJsonRep.getMediaType().isCompatible(MediaType.APPLICATION_JSON)){ - try { - JsonRepresentation jsonRep = new JsonRepresentation(optProblemJsonRep); - JSONObject json = jsonRep.getJsonObject(); - ObjectMapper objectMapper = new ObjectMapper(); - - // round trip validation - OptProblem optProblem = objectMapper.readValue(json.toString(),OptProblem.class); - String optProblemJsonString = objectMapper.writeValueAsString(optProblem); - - // create new socket resources (remove on failure) - OptSocketStreams optSocketStreams = createOptSocketStreams(); - - OptMessage.OptJobRunCommandMessage runCommand = new OptMessage.OptJobRunCommandMessage(optProblemJsonString); - OptMessage.OptResponseMessage response = optSocketStreams.sendCommand(runCommand); - if (response instanceof OptMessage.OptErrorResponseMessage){ - OptMessage.OptErrorResponseMessage errorResponse = (OptMessage.OptErrorResponseMessage) response; - String errMsg = "opt job run command failed: " + errorResponse.errorMessage; - lg.error(errMsg); - optSocketStreams.closeAll(optSocketStreams.optID); - throw new RuntimeException(errMsg); - } else if (response instanceof OptMessage.OptJobRunResponseMessage){ - OptMessage.OptJobRunResponseMessage runResponse = (OptMessage.OptJobRunResponseMessage) response; - optSocketStreams.optID = runResponse.optID; - lg.info("optimizationJobID="+optSocketStreams.optID+" created socket connect to submit"); - synchronized (paramOptActiveSockets) { - paramOptActiveSockets.put(optSocketStreams.optID, optSocketStreams); - } - return optSocketStreams.optID; - } else { - throw new RuntimeException("unexpected response "+response+" from opt job submission"); - } - } catch (Exception e) { - lg.error(e.getMessage(), e); - throw new ResourceException(Status.SERVER_ERROR_INTERNAL,e.getMessage(), e); - } - }else{ - throw new RuntimeException("unexpected post representation "+optProblemJsonRep); - } - } - - private OptSocketStreams createOptSocketStreams() throws IOException, InterruptedException { - // Server: 127.0.0.11 -// justamq_api.1.16o695tgthpt@dockerbuild | Address: 127.0.0.11#53 -// justamq_api.1.16o695tgthpt@dockerbuild | -// justamq_api.1.16o695tgthpt@dockerbuild | Non-authoritative answer: -// justamq_api.1.16o695tgthpt@dockerbuild | Name: tasks.justamq_submit -// justamq_api.1.16o695tgthpt@dockerbuild | Address: 10.0.7.14 - - //VCELL_SITE defined manually during deploy - //stackname = {"vcell"} + {$VCELL_SITE (from swarm *.config)} - //see vcell/docker/swarm/README.md "CLIENT and SERVER deploy commands" and "To create deploy configuration file" - //tasks.{taskName}, taskName comes from combining stackname + {taskname defined by docker} - //Container gets vcell.server.id from vcell:docker:swarm:deploy.sh and *.config variable VCELL_SITE - //see vcell/docker/swarm/deploy.sh -> echo "env \$(cat $remote_config_file | xargs) docker stack deploy -c $remote_compose_file $stack_name" - //lookup swarm ip number for task - - // - // use optional vcell.submit.service.host property to connect to vcell-submit service (e.g. localhost during dev) - // - String swarmSubmitTaskName = PropertyLoader.getProperty(PropertyLoader.vcellsubmit_service_host, null); - if (swarmSubmitTaskName == null){ - // if not provided, then calculate the DNS name of the docker swarm service for vcell-submit - swarmSubmitTaskName = "tasks."+"vcell"+PropertyLoader.getRequiredProperty(PropertyLoader.vcellServerIDProperty).toLowerCase()+"_submit"; - } - ProcessBuilder pb =new ProcessBuilder("nslookup",swarmSubmitTaskName); - pb.redirectErrorStream(true); - Process process = pb.start(); - java.io.InputStream is = process.getInputStream(); - java.io.InputStreamReader isr = new java.io.InputStreamReader(is); - java.io.BufferedReader br = new java.io.BufferedReader(isr); - String line; - String ipnum = null; - boolean bFound = false; - while ((line = br.readLine()) != null) { - if(line.contains(swarmSubmitTaskName)) { - bFound = true; - }else if (bFound && line.trim().startsWith("Address:")) { - ipnum = line.trim().substring("Address:".length()).trim(); - break; - } - } - br.close(); - int errCode = process.waitFor(); - lg.debug("nslookup errcode="+errCode); - - OptSocketStreams optSocketStreams = OptSocketStreams.create(ipnum); - return optSocketStreams; - } - - private JsonRepresentation queryOptJobStatus(String optID, ServerResource serverResource) throws ResourceException { - synchronized (paramOptActiveSockets) { - if (paramOptResults.containsKey(optID)) {//return cached results, socket already closed - return paramOptResults.remove(optID); - } - boolean bStop = Boolean.parseBoolean(serverResource.getQueryValue("bStop")); - OptSocketStreams optSocketStreams = paramOptActiveSockets.get(optID); - if(optSocketStreams != null) { - try { - if (bStop){ - OptMessage.OptResponseMessage response = optSocketStreams.sendCommand(new OptMessage.OptJobStopCommandMessage(optID)); - if (response instanceof OptMessage.OptErrorResponseMessage){ - OptMessage.OptErrorResponseMessage errorResponse = (OptMessage.OptErrorResponseMessage) response; - throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Failed to stop optimization ID="+optID+": "+errorResponse.errorMessage); - }else{ - return new JsonRepresentation("stop requested for optimization ID="+optID); - } - } else { - // simple status query - OptMessage.OptResponseMessage response = optSocketStreams.sendCommand(new OptMessage.OptJobQueryCommandMessage(optID)); - if (response instanceof OptMessage.OptErrorResponseMessage){ - OptMessage.OptErrorResponseMessage errorResponse = (OptMessage.OptErrorResponseMessage) response; - throw new RuntimeException("status request failed for optID="+optID+": "+errorResponse.errorMessage); - }else if (response instanceof OptMessage.OptJobStatusResponseMessage){ - OptMessage.OptJobStatusResponseMessage statusResponse = (OptMessage.OptJobStatusResponseMessage) response; - if (statusResponse.progressReportJsonString==null) { - return new JsonRepresentation(statusResponse.status.name() + ":"); - }else{ - return new JsonRepresentation(statusResponse.progressReportJsonString); - } - }else if (response instanceof OptMessage.OptJobSolutionResponseMessage){ - OptMessage.OptJobSolutionResponseMessage solutionResponse = (OptMessage.OptJobSolutionResponseMessage) response; - return new JsonRepresentation(solutionResponse.optRunJsonString); - }else{ - throw new RuntimeException("unexpected response "+response+" from opt job query request - optID="+optID); - } - } - } catch (Exception e) { - lg.error(e.getMessage(), e); - optSocketStreams.closeAll(optID); - throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e.getMessage() + " optimization ID=" + optID, e); - } - }else { - throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Can't find connection for optimization ID="+optID); - } - } - } - - @Override - @Post - public Representation run(Representation optProblemJson) { - String optID = submitOptProblem(optProblemJson,this); - getResponse().setStatus(Status.SUCCESS_OK); - Representation representation = new StringRepresentation(optID,MediaType.TEXT_PLAIN); - return representation; - } - - @Override - public JsonRepresentation get_json() { - String optID = (String)getRequestAttributes().get(VCellApiApplication.OPTIMIZATIONID); - JsonRepresentation jsonRepresentation = queryOptJobStatus(optID,this); - getResponse().setStatus(Status.SUCCESS_OK); - return jsonRepresentation; - } -} diff --git a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java index ca8964a300..3d82e77ee2 100644 --- a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java +++ b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java @@ -216,67 +216,6 @@ public EventWrapper[] getEvents(long beginTimestamp) throws IOException { return eventWrappers; } - public String getOptRunJson(String optimizationId,boolean bStop) throws IOException { - - HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/optimization/"+optimizationId+"?bStop="+bStop); - httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - - if (lg.isInfoEnabled()) { - lg.info("Executing request to retrieve optimization run " + httpget.getRequestLine()); - } - - String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getOptRunJson()", httpget), httpClientContext); - if (lg.isInfoEnabled()) { - lg.info("returned: "+toStringTruncated(responseBody)); - } - return responseBody; - } - - public String submitOptimization(String optProblemJson) throws IOException, URISyntaxException { - - HttpPost httppost = new HttpPost(getApiUrlPrefix()+"/optimization"); - httppost.addHeader("Authorization", "Bearer "+httpClientContext.getUserToken(String.class)); - - StringEntity input = new StringEntity(optProblemJson); - input.setContentType("application/json"); - httppost.setEntity(input); - - if (lg.isInfoEnabled()) { - lg.info("Executing request to submit optProblem " + httppost.getRequestLine()); - } - - ResponseHandler handler = new ResponseHandler() { - - public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException { - int status = response.getStatusLine().getStatusCode(); - if (status == 200) { - HttpEntity entity = response.getEntity(); - String message = null; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));){ - message = reader.lines().collect(Collectors.joining()); - } - return message; - } else { - HttpEntity entity = response.getEntity(); - String message = null; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));){ - message = reader.lines().collect(Collectors.joining()); - } - final URI uri = httppost.getURI(); - lg.error("submitOptimization() ("+uri+") failed: response status: " + status + "\nreason: " + message); - throw new ClientProtocolException("submitOptimization() failed: response status: " + status + "\nreason: " + message); - } - } - - }; - String responseUri = httpclient.execute(httppost,handler,httpClientContext); - if (lg.isInfoEnabled()) { - lg.info("returned: "+toStringTruncated(responseUri)); - } - - return responseUri; - } - public void createDefaultQuarkusClient(boolean bIgnoreCertProblems){ apiClient = new ApiClient(){{ if (bIgnoreCertProblems){setHttpClientBuilder(CustomApiClientCode.createInsecureHttpClientBuilder());}; @@ -341,6 +280,8 @@ public MathModelResourceApi getMathModelApi(){ public ExportResourceApi getExportApi(){return new ExportResourceApi(apiClient);} + public OptimizationResourceApi getOptimizationApi(){return new OptimizationResourceApi(apiClient);} + public String getVCellUserNameFromAuth0Mapping() throws ApiException { try { UsersResourceApi usersResourceApi = new UsersResourceApi(apiClient); diff --git a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellOptClient.java b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellOptClient.java deleted file mode 100644 index d85feac336..0000000000 --- a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellOptClient.java +++ /dev/null @@ -1,219 +0,0 @@ -package org.vcell.api.client; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.util.Locale; -import java.util.stream.Collectors; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.ProtocolException; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpResponseException; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultRedirectStrategy; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.apache.http.util.TextUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * This example demonstrates the use of the {@link ResponseHandler} to simplify - * the process of processing the HTTP response and releasing associated - * resources. - */ -public class VCellOptClient { - - private static final Logger lg = LogManager.getLogger(VCellOptClient.class); - private HttpHost httpHost; - private CloseableHttpClient httpclient; - private HttpClientContext httpClientContext; - - // Create a custom response handler - public static class VCellStringResponseHandler implements ResponseHandler { - - private final String methodCallString; - private final HttpGet httpget; - private final HttpPost httppost; - - public VCellStringResponseHandler(String methodCallString, HttpGet httpget) { - this.methodCallString = methodCallString; - this.httpget = httpget; - this.httppost = null; - } - - public VCellStringResponseHandler(String methodCallString, HttpPost httppost) { - this.methodCallString = methodCallString; - this.httpget = null; - this.httppost = httppost; - } - - @Override - public String handleResponse(HttpResponse response) throws HttpResponseException, IOException { - int status = response.getStatusLine().getStatusCode(); - if (status >= 200 && status < 300) { - HttpEntity entity = response.getEntity(); - return entity != null ? EntityUtils.toString(entity) : null; - } else { - HttpEntity entity = response.getEntity(); - String message = null; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));){ - message = reader.lines().collect(Collectors.joining()); - } - final URI uri; - if (httpget!=null) { - uri = httpget.getURI(); - }else { - uri = httppost.getURI(); - } - lg.error(methodCallString+" ("+uri+") failed: response status: " + status + "\nreason: " + message); - throw new HttpResponseException(status, methodCallString+" failed: response status: " + status + "\nreason: " + message); - } - } - } - - public VCellOptClient(String host, int port) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException{ - this.httpHost = new HttpHost(host,port,"http"); - initClient(); - } - - private void initClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { - - HttpClientBuilder httpClientBuilder = HttpClients.custom(); - httpclient = httpClientBuilder.setRedirectStrategy(new DefaultRedirectStrategy()).build(); - httpClientContext = HttpClientContext.create(); - } - - public void close() throws IOException { - if (httpclient!=null){ - httpclient.close(); - } - } - - public String getOptRunJson(String optimizationId) throws IOException { - HttpGet httpget = new HttpGet("http://"+httpHost.getHostName()+":"+httpHost.getPort()+"/optimization/"+optimizationId); - - if (lg.isInfoEnabled()) { - lg.info("Executing request to retrieve optimization run " + httpget.getRequestLine()); - } - - String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getOptRunJson()", httpget), httpClientContext); - if (lg.isInfoEnabled()) { - lg.info("returned: "+toStringTruncated(responseBody)); - } - return responseBody; - } - - public String submitOptimization(String optProblemJson) throws IOException, URISyntaxException { - - HttpPost httppost = new HttpPost("http://"+httpHost.getHostName()+":"+httpHost.getPort()+"/optimization"); - StringEntity input = new StringEntity(optProblemJson); - input.setContentType("application/json"); - httppost.setEntity(input); - - if (lg.isInfoEnabled()) { - lg.info("Executing request to submit optProblem " + httppost.getRequestLine()); - } - - ResponseHandler handler = new ResponseHandler() { - - public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException { - int status = response.getStatusLine().getStatusCode(); - if (status == 202) { - HttpEntity entity = response.getEntity(); - if (lg.isInfoEnabled()) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));){ - lg.info("optimizationId = "+reader.readLine()); - } - } - final Header locationHeader = response.getFirstHeader("location"); - if (locationHeader == null) { - // got a redirect response, but no location header - throw new ClientProtocolException( - "Received redirect response " + response.getStatusLine() - + " but no location header"); - } - final String location = locationHeader.getValue(); - URI uri = createLocationURI(location); - return uri.toString(); - } else { - HttpEntity entity = response.getEntity(); - String message = null; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));){ - message = reader.lines().collect(Collectors.joining()); - } - final URI uri = httppost.getURI(); - lg.error("submitOptimization() ("+uri+") failed: response status: " + status + "\nreason: " + message); - throw new ClientProtocolException("submitOptimization() failed: response status: " + status + "\nreason: " + message); - } - } - - }; - String responseUri = httpclient.execute(httppost,handler,httpClientContext); - if (lg.isInfoEnabled()) { - lg.info("returned: "+toStringTruncated(responseUri)); - } - - String optimizationId = responseUri.substring(responseUri.lastIndexOf('/') + 1); - return optimizationId; - } - - /** - * from org.apache.http.impl.client.DefaultRedirectStrategy - * - * @param location - * @return - * @throws ProtocolException - */ - private URI createLocationURI(final String location) throws ClientProtocolException { - try { - final URIBuilder b = new URIBuilder(new URI(location).normalize()); - final String host = b.getHost(); - if (host != null) { - b.setHost(host.toLowerCase(Locale.US)); - } - final String path = b.getPath(); - if (TextUtils.isEmpty(path)) { - b.setPath("/"); - } - return b.build(); - } catch (final URISyntaxException ex) { - throw new ClientProtocolException("Invalid redirect URI: " + location, ex); - } - } - - - - private static String toStringTruncated(Object obj) { - return toStringTruncated(obj, 30); - } - - private static String toStringTruncated(Object obj, int maxlength) { - if (obj == null) { - return "null"; - } - String str = obj.toString(); - if (str.length() <= maxlength) { - return str; - }else { - return str.substring(0, maxlength-4)+"..."; - } - } - -} diff --git a/vcell-client/src/main/java/copasi/CopasiOptimizationSolverRemote.java b/vcell-client/src/main/java/copasi/CopasiOptimizationSolverRemote.java index aff33dd3a6..25d9bda226 100644 --- a/vcell-client/src/main/java/copasi/CopasiOptimizationSolverRemote.java +++ b/vcell-client/src/main/java/copasi/CopasiOptimizationSolverRemote.java @@ -1,14 +1,10 @@ package copasi; import cbit.vcell.client.ClientRequestManager; -import cbit.vcell.client.RequestManager; -import cbit.vcell.client.VCellClient; -import cbit.vcell.client.server.ClientServerInfo; import cbit.vcell.modelopt.ParameterEstimationTask; import cbit.vcell.opt.OptimizationException; import cbit.vcell.opt.OptimizationResultSet; import cbit.vcell.opt.OptimizationStatus; -import cbit.vcell.resource.PropertyLoader; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -16,198 +12,196 @@ import org.vcell.optimization.CopasiOptSolverCallbacks; import org.vcell.optimization.CopasiUtils; import org.vcell.optimization.jtd.*; +import org.vcell.restclient.api.OptimizationResourceApi; +import org.vcell.restclient.model.OptJobStatus; +import org.vcell.restclient.model.OptimizationJobStatus; import org.vcell.util.ClientTaskStatusSupport; import org.vcell.util.UserCancelException; -import javax.swing.*; +import java.util.function.Consumer; public class CopasiOptimizationSolverRemote { private final static Logger lg = LogManager.getLogger(CopasiOptimizationSolverRemote.class); + /** + * Entry point for the desktop client GUI. Gets the OptimizationResourceApi from the request manager + * and delegates to solveRemoteApi(OptimizationResourceApi, ...) with Swing-based progress updates. + */ public static OptimizationResultSet solveRemoteApi( ParameterEstimationTask parameterEstimationTask, CopasiOptSolverCallbacks optSolverCallbacks, ClientTaskStatusSupport clientTaskStatusSupport, ClientRequestManager requestManager) { - // return solveLocalPython(parameterEstimationTask); + VCellApiClient vcellApiClient = requestManager.getClientServerManager().getVCellApiClient(); + OptimizationResourceApi optApi = vcellApiClient.getOptimizationApi(); - try { - // e.g. vcell.serverhost=vcellapi.cam.uchc.edu:443 - VCellApiClient apiClient = requestManager.getClientServerManager().getVCellApiClient(); + // Use SwingUtilities.invokeLater for progress updates in the GUI + Consumer progressDispatcher = javax.swing.SwingUtilities::invokeLater; + + return solveRemoteApi(parameterEstimationTask, optSolverCallbacks, clientTaskStatusSupport, + optApi, progressDispatcher); + } - OptProblem optProblem = CopasiUtils.paramTaskToOptProblem(parameterEstimationTask); + /** + * Core optimization solver logic. Testable without Swing — accepts an OptimizationResourceApi + * directly and a pluggable progress dispatcher. + * + * @param parameterEstimationTask the parameter estimation task to solve + * @param optSolverCallbacks callbacks for progress reports and stop requests + * @param clientTaskStatusSupport status message and progress bar updates (nullable) + * @param optApi the generated REST client API for optimization endpoints + * @param progressDispatcher how to dispatch progress updates (SwingUtilities::invokeLater in GUI, Runnable::run in tests) + */ + public static OptimizationResultSet solveRemoteApi( + ParameterEstimationTask parameterEstimationTask, + CopasiOptSolverCallbacks optSolverCallbacks, + ClientTaskStatusSupport clientTaskStatusSupport, + OptimizationResourceApi optApi, + Consumer progressDispatcher) { + try { + // Convert parameter estimation task to OptProblem (vcell-core types) + OptProblem optProblemCore = CopasiUtils.paramTaskToOptProblem(parameterEstimationTask); + + // Convert to generated client model type for the API call ObjectMapper objectMapper = new ObjectMapper(); - String optProblemJson = objectMapper.writeValueAsString(optProblem); + String optProblemJson = objectMapper.writeValueAsString(optProblemCore); + org.vcell.restclient.model.OptProblem optProblem = objectMapper.readValue( + optProblemJson, org.vcell.restclient.model.OptProblem.class); if (clientTaskStatusSupport != null) { clientTaskStatusSupport.setMessage("Submitting opt problem..."); } - //Submit but allow user to get out from restlet blocking call - final String[] optIdHolder = new String[]{null}; - final Exception[] exceptHolder = new Exception[]{null}; - Thread submitThread = new Thread(() -> { - try { - optIdHolder[0] = apiClient.submitOptimization(optProblemJson); - lg.info("submitted optimization jobID="+optIdHolder[0]); - if (optSolverCallbacks.getStopRequested()) { - apiClient.getOptRunJson(optIdHolder[0], optSolverCallbacks.getStopRequested()); - lg.info("user cancelled optimization jobID="+optIdHolder[0]); - } - } catch (Exception e) { - lg.error(e.getMessage(), e); - exceptHolder[0] = e; - } - }); - submitThread.setDaemon(true); - submitThread.start(); - - // - // wait here until either failure to submit or submitted and retrieved Job ID - // - while (optIdHolder[0] == null && exceptHolder[0] == null && !optSolverCallbacks.getStopRequested()) { - try { - Thread.sleep(200); - }catch (InterruptedException e){} - } - - // - // failed to submit, throw the exception now - // - if (exceptHolder[0] != null) { - throw exceptHolder[0]; - } + // Submit optimization job + OptimizationJobStatus submitResult = optApi.submitOptimization(optProblem); + Long jobId = Long.parseLong(submitResult.getId()); + lg.info("submitted optimization jobID={}", jobId); - // - // loop to query status and collect results - // - final long TIMEOUT_MS = 1000 * 200; // 200 second timeout + // Poll for status and results + final long TIMEOUT_MS = 1000 * 600; // 10 minute timeout long startTime = System.currentTimeMillis(); if (clientTaskStatusSupport != null) { clientTaskStatusSupport.setMessage("Waiting for progress..."); } + Vcellopt optRun = null; OptProgressReport latestProgressReport = null; + while ((System.currentTimeMillis() - startTime) < TIMEOUT_MS) { - // - // check for user stop request - // - boolean bStopRequested = optSolverCallbacks.getStopRequested(); - if (bStopRequested) { - lg.info("user cancelled optimization jobID="+optIdHolder[0]); + // Check for user stop request + if (optSolverCallbacks.getStopRequested()) { + lg.info("user cancelled optimization jobID={}", jobId); try { - apiClient.getOptRunJson(optIdHolder[0], bStopRequested); - lg.info("requested job to be stopped jobID="+optIdHolder[0]); - }catch (Exception e){ + optApi.stopOptimization(jobId); + lg.info("requested job to be stopped jobID={}", jobId); + } catch (Exception e) { lg.error(e.getMessage(), e); - }finally{ - if (latestProgressReport!=null){ + } finally { + if (latestProgressReport != null) { if (clientTaskStatusSupport != null) { clientTaskStatusSupport.setProgress(100); } - OptimizationResultSet copasiOptimizationResultSet = CopasiUtils.getOptimizationResultSet(parameterEstimationTask, latestProgressReport); - return copasiOptimizationResultSet; + return CopasiUtils.getOptimizationResultSet(parameterEstimationTask, latestProgressReport); } } throw UserCancelException.CANCEL_GENERIC; } - String optRunServerMessage = apiClient.getOptRunJson(optIdHolder[0], false); + // Poll status + OptimizationJobStatus status = optApi.getOptimizationStatus(jobId); if (optSolverCallbacks.getStopRequested()) { throw UserCancelException.CANCEL_GENERIC; } - if (optRunServerMessage.startsWith(VcelloptStatus.QUEUED.name() + ":")) { - if (clientTaskStatusSupport != null) { - clientTaskStatusSupport.setMessage("Queued..."); - } - - } else if (optRunServerMessage.startsWith(VcelloptStatus.FAILED.name()+":") || optRunServerMessage.toLowerCase().startsWith("exception:")){ - if (clientTaskStatusSupport != null) { - clientTaskStatusSupport.setMessage(optRunServerMessage); - } - } else if (optRunServerMessage.startsWith(VcelloptStatus.RUNNING.name() + ":")) { - if (clientTaskStatusSupport != null) { - clientTaskStatusSupport.setMessage("Running (waiting for progress) ..."); - } - - } else { - // consider that optRunServerMessage is either a progress report (OptProgressReport) or a final solution (Vcellopt) - Object optObject = null; - try { - optObject = objectMapper.readValue(optRunServerMessage, Vcellopt.class); - }catch (Exception e){ - optObject = objectMapper.readValue(optRunServerMessage, OptProgressReport.class); - } - - if (optObject instanceof Vcellopt) { - // - // have final solution with progress report and analytics - // - optRun = (Vcellopt) optObject; - final OptProgressReport optProgressReport = optRun.getOptResultSet().getOptProgressReport(); - VcelloptStatus status = optRun.getStatus(); - if (optProgressReport != null){ - SwingUtilities.invokeLater(() -> optSolverCallbacks.setProgressReport(optProgressReport)); + lg.debug("job {}: poll status={}, hasProgressReport={}, hasResults={}", + jobId, status.getStatus(), + status.getProgressReport() != null, + status.getResults() != null); + + switch (status.getStatus()) { + case SUBMITTED: + case QUEUED: + case RUNNING: + if (status.getProgressReport() != null) { + String progressJson = objectMapper.writeValueAsString(status.getProgressReport()); + latestProgressReport = objectMapper.readValue(progressJson, OptProgressReport.class); + final OptProgressReport progressReport = latestProgressReport; + progressDispatcher.accept(() -> { + try { + optSolverCallbacks.setProgressReport(progressReport); + } catch (Exception e) { + lg.error("error updating progress", e); + } + if (clientTaskStatusSupport != null) { + clientTaskStatusSupport.setMessage("Running ..."); + } + }); + } else { + if (clientTaskStatusSupport != null) { + clientTaskStatusSupport.setMessage( + status.getStatus() == org.vcell.restclient.model.OptJobStatus.RUNNING + ? "Running (waiting for progress) ..." + : "Queued..."); + } } - if (status == VcelloptStatus.COMPLETE) { - lg.info("job " + optIdHolder[0] + ": status " + status + " " + optRun.getOptResultSet().toString()); + break; + + case COMPLETE: + if (status.getResults() != null) { + String resultsJson = objectMapper.writeValueAsString(status.getResults()); + optRun = objectMapper.readValue(resultsJson, Vcellopt.class); + lg.info("job {}: COMPLETE, optResultSet={}", jobId, optRun.getOptResultSet() != null); + if (optRun.getOptResultSet() != null && optRun.getOptResultSet().getOptProgressReport() != null) { + final OptProgressReport finalProgress = optRun.getOptResultSet().getOptProgressReport(); + progressDispatcher.accept(() -> optSolverCallbacks.setProgressReport(finalProgress)); + } if (clientTaskStatusSupport != null) { clientTaskStatusSupport.setProgress(100); } - break; - } - if (status == VcelloptStatus.FAILED) { - String msg = "optimization failed, message=" + optRun.getStatusMessage(); - lg.error(msg); - throw new RuntimeException(msg); + } else { + lg.warn("job {}: COMPLETE but results are null", jobId); } - lg.info("job " + optIdHolder[0] + ": status " + status); - }else if (optObject instanceof OptProgressReport){ - // - // have intermediate progress report - // - latestProgressReport = (OptProgressReport) optObject; - final OptProgressReport progressReport = latestProgressReport; - SwingUtilities.invokeLater(() -> { - try { - optSolverCallbacks.setProgressReport(progressReport); - } catch (Exception e) { - lg.error(optRunServerMessage, e); - } + break; + + case FAILED: + String failMsg = "optimization failed, message=" + status.getStatusMessage(); + lg.error(failMsg); + throw new RuntimeException(failMsg); + + case STOPPED: + if (latestProgressReport != null) { if (clientTaskStatusSupport != null) { - int numFunctionEvaluations = 0; - if (progressReport.getProgressItems()!=null && progressReport.getProgressItems().size()>0){ - OptProgressItem lastItem = progressReport.getProgressItems().get(progressReport.getProgressItems().size()-1); - numFunctionEvaluations = lastItem.getNumFunctionEvaluations(); - } - clientTaskStatusSupport.setMessage("Running ..."); + clientTaskStatusSupport.setProgress(100); } - }); - } + return CopasiUtils.getOptimizationResultSet(parameterEstimationTask, latestProgressReport); + } + throw UserCancelException.CANCEL_GENERIC; } + + if (optRun != null) { + break; // COMPLETE + } + try { Thread.sleep(2000); - }catch (InterruptedException e){} + } catch (InterruptedException e) { /* ignore */ } } - if((System.currentTimeMillis()-startTime) >= TIMEOUT_MS) { + + if ((System.currentTimeMillis() - startTime) >= TIMEOUT_MS) { lg.warn("optimization timed out."); throw new RuntimeException("optimization timed out."); } + OptResultSet optResultSet = optRun.getOptResultSet(); - if(optResultSet == null) { - String msg = "optResultSet is null, status is " + optRun.getStatusMessage(); - lg.error(msg); - throw new RuntimeException(msg); + if (optResultSet == null) { + throw new RuntimeException("optResultSet is null, status is " + optRun.getStatusMessage()); } - if(optResultSet != null && optResultSet.getOptParameterValues() == null) { - String msg = "getOptParameterValues is null, status is " + optRun.getStatusMessage(); - lg.error(msg); - throw new RuntimeException(msg); + if (optResultSet.getOptParameterValues() == null) { + throw new RuntimeException("getOptParameterValues is null, status is " + optRun.getStatusMessage()); } - if(clientTaskStatusSupport != null) { + if (clientTaskStatusSupport != null) { clientTaskStatusSupport.setMessage("Done, getting results..."); } @@ -216,12 +210,9 @@ public static OptimizationResultSet solveRemoteApi( optRun.getOptResultSet(), new OptimizationStatus(OptimizationStatus.NORMAL_TERMINATION, optRun.getStatusMessage())); lg.info("done with optimization"); - if (lg.isTraceEnabled()) { - lg.trace("-----------SOLUTION FROM VCellAPI---------------\n" + optResultSet.toString()); - } - return copasiOptimizationResultSet; - }catch(UserCancelException e) { + + } catch (UserCancelException e) { throw e; } catch (Exception e) { lg.error(e.getMessage(), e); diff --git a/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java b/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java index cabfc84230..56a97cea8d 100644 --- a/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java +++ b/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java @@ -224,6 +224,8 @@ public static void setConfigProvider(VCellConfigProvider configProvider) { public static final String jmsSimHostExternal = record("vcell.jms.sim.host.external",ValueType.GEN); public static final String jmsSimPortExternal = record("vcell.jms.sim.port.external",ValueType.GEN); public static final String jmsSimRestPortExternal = record("vcell.jms.sim.restport.external",ValueType.GEN); + public static final String jmsArtemisHostInternal = record("vcell.jms.artemis.host.internal",ValueType.GEN); + public static final String jmsArtemisPortInternal = record("vcell.jms.artemis.port.internal",ValueType.GEN); public static final String jmsUser = record("vcell.jms.user",ValueType.GEN); public static final String jmsPasswordValue = record("vcell.jms.password",ValueType.GEN); public static final String jmsPasswordFile = record("vcell.jms.pswdfile",ValueType.GEN); @@ -256,7 +258,6 @@ public static void setConfigProvider(VCellConfigProvider configProvider) { public static final String vcellSMTPPort = record("vcell.smtp.port",ValueType.GEN); public static final String vcellSMTPEmailAddress = record("vcell.smtp.emailAddress",ValueType.GEN); - public static final String vcellsubmit_service_host = record("vcell.submit.service.host",ValueType.GEN); public static final String javaSimulationExecutable = record("vcell.javaSimulation.executable",ValueType.GEN); public static final String simulationPreprocessor = record("vcell.simulation.preprocessor",ValueType.GEN); public static final String simulationPostprocessor = record("vcell.simulation.postprocessor",ValueType.GEN); diff --git a/vcell-core/src/main/java/org/vcell/optimization/OptJobRecord.java b/vcell-core/src/main/java/org/vcell/optimization/OptJobRecord.java new file mode 100644 index 0000000000..fcffed9230 --- /dev/null +++ b/vcell-core/src/main/java/org/vcell/optimization/OptJobRecord.java @@ -0,0 +1,22 @@ +package org.vcell.optimization; + +import org.vcell.util.document.KeyValue; + +import java.time.Instant; + +/** + * Database row record for the vc_optjob table. + * Shared between vcell-server (OptJobTable) and vcell-rest (OptimizationRestService). + */ +public record OptJobRecord( + KeyValue id, + KeyValue ownerKey, + OptJobStatus status, + String optProblemFile, + String optOutputFile, + String optReportFile, + String htcJobId, + String statusMessage, + Instant insertDate, + Instant updateDate +) {} diff --git a/vcell-core/src/main/java/org/vcell/optimization/OptJobStatus.java b/vcell-core/src/main/java/org/vcell/optimization/OptJobStatus.java new file mode 100644 index 0000000000..ee1dbcb4e4 --- /dev/null +++ b/vcell-core/src/main/java/org/vcell/optimization/OptJobStatus.java @@ -0,0 +1,10 @@ +package org.vcell.optimization; + +public enum OptJobStatus { + SUBMITTED, + QUEUED, + RUNNING, + COMPLETE, + FAILED, + STOPPED +} diff --git a/vcell-core/src/main/java/org/vcell/optimization/OptMessage.java b/vcell-core/src/main/java/org/vcell/optimization/OptMessage.java deleted file mode 100644 index 9277052646..0000000000 --- a/vcell-core/src/main/java/org/vcell/optimization/OptMessage.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.vcell.optimization; - -import java.io.Serializable; - -public class OptMessage implements Serializable { - public final String optID; - public OptMessage(String optID){ - this.optID = optID; - } - - public static class OptCommandMessage extends OptMessage { - public OptCommandMessage(String optID){ - super(optID); - } - } - - public static class OptResponseMessage extends OptMessage { - public final OptCommandMessage commandMessage; - public OptResponseMessage(OptCommandMessage commandMessage){ - super((commandMessage!=null)?commandMessage.optID:null); - this.commandMessage = commandMessage; - } - public OptResponseMessage(String optID, OptCommandMessage commandMessage){ - super(optID); - this.commandMessage = commandMessage; - } - } - - public static class OptErrorResponseMessage extends OptResponseMessage { - public final String errorMessage; - public OptErrorResponseMessage(OptCommandMessage optCommandMessage, String errorMessage){ - super(optCommandMessage); - this.errorMessage = errorMessage; - } - public String toString() { - return super.toString() + "(id="+optID+", errorMessage='"+errorMessage+"')"; - } - } - - // - // job submit command/response - // - public static class OptJobRunCommandMessage extends OptCommandMessage { - public final String optProblemJsonString; - public OptJobRunCommandMessage(String optProblemJsonString) { - super(null); - this.optProblemJsonString = optProblemJsonString; - } - public String toString() { - return super.toString() + "(id="+optID+"')"; - } - } - public static class OptJobRunResponseMessage extends OptResponseMessage { - public OptJobRunResponseMessage(String optID, OptJobRunCommandMessage optJobRunCommandMessage){ - super(optID, optJobRunCommandMessage); - } - public String toString() { - return super.toString() + "(id="+optID+")"; - } - } - - // - // job stop command/response - // - public static class OptJobStopCommandMessage extends OptCommandMessage { - public OptJobStopCommandMessage(String optID){ - super(optID); - } - public String toString() { - return super.toString() + "(id="+optID+"')"; - } - } - public static class OptJobStopResponseMessage extends OptResponseMessage { - public OptJobStopResponseMessage(OptJobStopCommandMessage optJobStopCommandMessage){ - super(optJobStopCommandMessage); - } - public String toString() { - return super.toString() + "(id="+optID+"')"; - } - } - - // - // job status command/response - // - public static class OptJobQueryCommandMessage extends OptCommandMessage { - public OptJobQueryCommandMessage(String optID){ - super(optID); - } - public String toString() { - return super.toString() + "(id="+optID+"')"; - } - } - public enum OptJobMessageStatus { - QUEUED, - FAILED, - COMPLETE, - RUNNING - } - public static class OptJobStatusResponseMessage extends OptResponseMessage { - public final OptJobMessageStatus status; - public final String statusMessage; - public final String progressReportJsonString; - - public OptJobStatusResponseMessage(OptJobQueryCommandMessage optJobQueryCommandMessage, - OptJobMessageStatus status, String statusMessage, - String progressReportJsonString) { - super(optJobQueryCommandMessage); - this.status = status; - this.statusMessage = statusMessage; - this.progressReportJsonString = progressReportJsonString; - } - public String toString() { - return super.toString() + "(id="+optID+", status='"+status+", statusMessage='"+statusMessage+"')"; - } - } - public static class OptJobSolutionResponseMessage extends OptResponseMessage { - public final String optRunJsonString; - public OptJobSolutionResponseMessage(OptJobQueryCommandMessage optJobQueryCommandMessage, - String optRunJsonString) { - super(optJobQueryCommandMessage); - this.optRunJsonString = optRunJsonString; - } - public String toString() { - return super.toString() + "(id="+optID+"')"; - } - } -} diff --git a/vcell-core/src/main/java/org/vcell/optimization/OptRequestMessage.java b/vcell-core/src/main/java/org/vcell/optimization/OptRequestMessage.java new file mode 100644 index 0000000000..33e974349b --- /dev/null +++ b/vcell-core/src/main/java/org/vcell/optimization/OptRequestMessage.java @@ -0,0 +1,26 @@ +package org.vcell.optimization; + +/** + * Internal message sent from vcell-rest to vcell-submit to request job submission or stop. + * Serialized as JSON over ActiveMQ (AMQP 1.0 on vcell-rest side, JMS/OpenWire on vcell-submit side). + */ +public class OptRequestMessage { + public String jobId; + public String command; // "submit" or "stop" + public String optProblemFilePath; // for submit + public String optOutputFilePath; // for submit + public String optReportFilePath; // for submit + public String htcJobId; // for stop (SLURM job to cancel) + + public OptRequestMessage() {} + + public OptRequestMessage(String jobId, String command, String optProblemFilePath, + String optOutputFilePath, String optReportFilePath, String htcJobId) { + this.jobId = jobId; + this.command = command; + this.optProblemFilePath = optProblemFilePath; + this.optOutputFilePath = optOutputFilePath; + this.optReportFilePath = optReportFilePath; + this.htcJobId = htcJobId; + } +} diff --git a/vcell-core/src/main/java/org/vcell/optimization/OptStatusMessage.java b/vcell-core/src/main/java/org/vcell/optimization/OptStatusMessage.java new file mode 100644 index 0000000000..d10e8e45b4 --- /dev/null +++ b/vcell-core/src/main/java/org/vcell/optimization/OptStatusMessage.java @@ -0,0 +1,21 @@ +package org.vcell.optimization; + +/** + * Internal message sent from vcell-submit back to vcell-rest with status updates. + * Serialized as JSON over ActiveMQ (JMS/OpenWire on vcell-submit side, AMQP 1.0 on vcell-rest side). + */ +public class OptStatusMessage { + public String jobId; + public OptJobStatus status; + public String statusMessage; + public String htcJobId; // set when SLURM job is submitted + + public OptStatusMessage() {} + + public OptStatusMessage(String jobId, OptJobStatus status, String statusMessage, String htcJobId) { + this.jobId = jobId; + this.status = status; + this.statusMessage = statusMessage; + this.htcJobId = htcJobId; + } +} diff --git a/vcell-rest/pom.xml b/vcell-rest/pom.xml index 56f0fd3c5e..dbfa8d9bbe 100644 --- a/vcell-rest/pom.xml +++ b/vcell-rest/pom.xml @@ -253,6 +253,18 @@ 2.7.0 test + + org.apache.activemq + activemq-client + ${activemq-client.version} + test + + + javax.jms + javax.jms-api + 2.0.1 + test + diff --git a/vcell-rest/src/main/java/org/vcell/restq/QuarkusStartUpTasks.java b/vcell-rest/src/main/java/org/vcell/restq/QuarkusStartUpTasks.java index 9216547889..3cfc1fe34c 100644 --- a/vcell-rest/src/main/java/org/vcell/restq/QuarkusStartUpTasks.java +++ b/vcell-rest/src/main/java/org/vcell/restq/QuarkusStartUpTasks.java @@ -8,7 +8,6 @@ import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; import jakarta.ws.rs.Produces; -import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.vcell.restq.db.AgroalConnectionFactory; diff --git a/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java b/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java index f8f2456367..434c9e6da4 100644 --- a/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java +++ b/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java @@ -31,7 +31,8 @@ import java.io.FileNotFoundException; import java.sql.SQLException; import java.util.Map; -import java.util.concurrent.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; @@ -59,10 +60,11 @@ public CompletableFuture startJob(Message exportJob) { @IfBuildProperty(name = "vcell.exporter", stringValue = "true") public class ExportRequestListenerMQ implements ExportMQInterface { private static final Logger logger = LogManager.getLogger(ExportRequestListenerMQ.class); - private final ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(10); private DataServerImpl dataServer; private TimeUnit waitUnit = TimeUnit.MINUTES; + @Inject + org.eclipse.microprofile.context.ManagedExecutor managedExecutor; @Inject ServerExportEventController exportStatusCreator; @Inject @@ -118,7 +120,7 @@ public CompletableFuture startJob(Message message, boolean handleF } catch (SQLException | DataAccessException e) { throw new RuntimeException(e); } - }, threadPoolExecutor) + }, managedExecutor) .orTimeout(15, waitUnit); if (handleFailure){ diff --git a/vcell-rest/src/main/java/org/vcell/restq/activemq/OptimizationMQ.java b/vcell-rest/src/main/java/org/vcell/restq/activemq/OptimizationMQ.java new file mode 100644 index 0000000000..610ff6c188 --- /dev/null +++ b/vcell-rest/src/main/java/org/vcell/restq/activemq/OptimizationMQ.java @@ -0,0 +1,86 @@ +package org.vcell.restq.activemq; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.smallrye.mutiny.Uni; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.microprofile.reactive.messaging.Channel; +import org.eclipse.microprofile.reactive.messaging.Emitter; +import org.eclipse.microprofile.reactive.messaging.Incoming; +import org.eclipse.microprofile.reactive.messaging.Message; +import org.vcell.optimization.OptRequestMessage; +import org.vcell.optimization.OptStatusMessage; +import org.vcell.restq.services.OptimizationRestService; +import org.vcell.util.document.KeyValue; + +/** + * ActiveMQ messaging for optimization job dispatch and status updates. + * + * vcell-rest produces messages on "opt-request" (submit/stop commands to vcell-submit) + * and consumes messages on "opt-status" (status updates from vcell-submit). + */ +@ApplicationScoped +public class OptimizationMQ { + private static final Logger lg = LogManager.getLogger(OptimizationMQ.class); + + @Inject + ObjectMapper mapper; + + @Inject + OptimizationRestService optimizationRestService; + + @Inject + @Channel("publisher-opt-request") + Emitter optRequestEmitter; + + /** + * Send a submit command to vcell-submit. + */ + public void sendSubmitRequest(OptRequestMessage request) { + try { + lg.info("Sending optimization submit request for job {}", request.jobId); + optRequestEmitter.send(mapper.writeValueAsString(request)); + } catch (Exception e) { + lg.error("Failed to send optimization submit request for job {}: {}", request.jobId, e.getMessage(), e); + } + } + + /** + * Send a stop command to vcell-submit. + */ + public void sendStopRequest(OptRequestMessage request) { + try { + lg.info("Sending optimization stop request for job {}", request.jobId); + optRequestEmitter.send(mapper.writeValueAsString(request)); + } catch (Exception e) { + lg.error("Failed to send optimization stop request for job {}: {}", request.jobId, e.getMessage(), e); + } + } + + /** + * Consume status updates from vcell-submit (e.g. QUEUED with htcJobId, FAILED with error). + */ + @Incoming("subscriber-opt-status") + public Uni consumeOptStatus(Message message) { + try { + OptStatusMessage statusMsg = mapper.readValue(message.getPayload(), OptStatusMessage.class); + lg.info("Received optimization status update: job={}, status={}", statusMsg.jobId, statusMsg.status); + + KeyValue jobKey = new KeyValue(statusMsg.jobId); + + if (statusMsg.htcJobId != null) { + optimizationRestService.updateHtcJobId(jobKey, statusMsg.htcJobId); + } + if (statusMsg.status != null) { + optimizationRestService.updateOptJobStatus(jobKey, statusMsg.status, statusMsg.statusMessage); + } + + return Uni.createFrom().completionStage(message.ack()); + } catch (Exception e) { + lg.error("Failed to process optimization status message: {}", e.getMessage(), e); + return Uni.createFrom().completionStage(message.nack(e)); + } + } +} diff --git a/vcell-rest/src/main/java/org/vcell/restq/handlers/OptimizationResource.java b/vcell-rest/src/main/java/org/vcell/restq/handlers/OptimizationResource.java new file mode 100644 index 0000000000..6136f92218 --- /dev/null +++ b/vcell-rest/src/main/java/org/vcell/restq/handlers/OptimizationResource.java @@ -0,0 +1,141 @@ +package org.vcell.restq.handlers; + +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.vcell.optimization.OptRequestMessage; +import org.vcell.optimization.jtd.OptProblem; +import org.vcell.restq.activemq.OptimizationMQ; +import org.vcell.restq.errors.exceptions.DataAccessWebException; +import org.vcell.restq.errors.exceptions.NotAuthenticatedWebException; +import org.vcell.restq.errors.exceptions.NotFoundWebException; +import org.vcell.restq.errors.exceptions.RuntimeWebException; +import org.vcell.optimization.OptJobStatus; +import org.vcell.restq.models.OptimizationJobStatus; +import org.vcell.restq.services.OptimizationRestService; +import org.vcell.restq.services.UserRestService; +import org.vcell.util.DataAccessException; +import org.vcell.util.document.KeyValue; +import org.vcell.util.document.User; + +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; + +@Path("/api/v1/optimization") +@Produces(MediaType.APPLICATION_JSON) +public class OptimizationResource { + + private final OptimizationRestService optimizationRestService; + + @Inject + SecurityIdentity securityIdentity; + + @Inject + UserRestService userRestService; + + @Inject + OptimizationMQ optimizationMQ; + + @org.eclipse.microprofile.config.inject.ConfigProperty(name = "vcell.optimization.parest-data-dir", defaultValue = "/simdata/parest_data") + String parestDataDir; + + @Inject + public OptimizationResource(OptimizationRestService optimizationRestService) { + this.optimizationRestService = optimizationRestService; + } + + @GET + @RolesAllowed("user") + @Operation(operationId = "listOptimizationJobs", summary = "List optimization jobs for the authenticated user") + public OptimizationJobStatus[] list() throws NotAuthenticatedWebException, DataAccessWebException { + try { + User vcellUser = userRestService.getUserFromIdentity(securityIdentity); + return optimizationRestService.listOptimizationJobs(vcellUser); + } catch (SQLException e) { + throw new RuntimeWebException("Failed to list optimization jobs: " + e.getMessage(), e); + } + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @RolesAllowed("user") + @Operation(operationId = "submitOptimization", summary = "Submit a new parameter estimation optimization job") + public OptimizationJobStatus submit(OptProblem optProblem) + throws NotAuthenticatedWebException, DataAccessWebException { + try { + User vcellUser = userRestService.getUserFromIdentity(securityIdentity); + OptimizationJobStatus status = optimizationRestService.submitOptimization( + optProblem, new File(parestDataDir), vcellUser); + + optimizationMQ.sendSubmitRequest(new OptRequestMessage( + status.id().toString(), + "submit", + new File(parestDataDir, "CopasiParest_" + status.id() + "_optProblem.json").getAbsolutePath(), + new File(parestDataDir, "CopasiParest_" + status.id() + "_optRun.json").getAbsolutePath(), + new File(parestDataDir, "CopasiParest_" + status.id() + "_optReport.txt").getAbsolutePath(), + null + )); + + return status; + } catch (SQLException e) { + throw new RuntimeWebException("Failed to submit optimization job: " + e.getMessage(), e); + } catch (IOException e) { + throw new RuntimeWebException("Failed to write optimization problem to filesystem: " + e.getMessage(), e); + } + } + + @GET + @Path("{optId}") + @RolesAllowed("user") + @Operation(operationId = "getOptimizationStatus", summary = "Get status, progress, or results of an optimization job") + public OptimizationJobStatus getStatus(@PathParam("optId") Long optId) + throws NotAuthenticatedWebException, NotFoundWebException, DataAccessWebException { + try { + User vcellUser = userRestService.getUserFromIdentity(securityIdentity); + return optimizationRestService.getOptimizationStatus(new KeyValue(optId.toString()), vcellUser); + } catch (DataAccessException e) { + throw new DataAccessWebException(e.getMessage(), e); + } catch (SQLException e) { + throw new RuntimeWebException("Failed to query optimization status: " + e.getMessage(), e); + } catch (IOException e) { + throw new RuntimeWebException("Failed to read optimization data: " + e.getMessage(), e); + } + } + + @POST + @Path("{optId}/stop") + @RolesAllowed("user") + @Operation(operationId = "stopOptimization", summary = "Stop a running optimization job") + public OptimizationJobStatus stop(@PathParam("optId") Long optId) + throws NotAuthenticatedWebException, NotFoundWebException, DataAccessWebException { + try { + User vcellUser = userRestService.getUserFromIdentity(securityIdentity); + KeyValue jobKey = new KeyValue(optId.toString()); + OptimizationJobStatus currentStatus = optimizationRestService.getOptimizationStatus(jobKey, vcellUser); + if (currentStatus.status() != OptJobStatus.RUNNING && currentStatus.status() != OptJobStatus.QUEUED) { + throw new DataAccessWebException("Cannot stop optimization job in state: " + currentStatus.status()); + } + + String htcJobId = optimizationRestService.getHtcJobId(jobKey); + optimizationMQ.sendStopRequest(new OptRequestMessage( + jobKey.toString(), + "stop", + null, null, null, + htcJobId + )); + + optimizationRestService.updateOptJobStatus(jobKey, OptJobStatus.STOPPED, "Stopped by user"); + return optimizationRestService.getOptimizationStatus(jobKey, vcellUser); + } catch (DataAccessException e) { + throw new DataAccessWebException(e.getMessage(), e); + } catch (SQLException e) { + throw new RuntimeWebException("Failed to stop optimization job: " + e.getMessage(), e); + } catch (IOException e) { + throw new RuntimeWebException("Failed to read optimization data: " + e.getMessage(), e); + } + } +} diff --git a/vcell-rest/src/main/java/org/vcell/restq/models/OptimizationJobStatus.java b/vcell-rest/src/main/java/org/vcell/restq/models/OptimizationJobStatus.java new file mode 100644 index 0000000000..943d107b05 --- /dev/null +++ b/vcell-rest/src/main/java/org/vcell/restq/models/OptimizationJobStatus.java @@ -0,0 +1,15 @@ +package org.vcell.restq.models; + +import org.vcell.optimization.OptJobStatus; +import org.vcell.optimization.jtd.OptProgressReport; +import org.vcell.optimization.jtd.Vcellopt; +import org.vcell.util.document.KeyValue; + +public record OptimizationJobStatus( + KeyValue id, + OptJobStatus status, + String statusMessage, + String htcJobId, + OptProgressReport progressReport, + Vcellopt results +) {} diff --git a/vcell-rest/src/main/java/org/vcell/restq/services/OptimizationRestService.java b/vcell-rest/src/main/java/org/vcell/restq/services/OptimizationRestService.java new file mode 100644 index 0000000000..34239cc4a9 --- /dev/null +++ b/vcell-rest/src/main/java/org/vcell/restq/services/OptimizationRestService.java @@ -0,0 +1,280 @@ +package org.vcell.restq.services; + +import cbit.vcell.modeldb.OptJobTable; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.enterprise.context.ApplicationScoped; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.vcell.db.KeyFactory; +import org.vcell.optimization.CopasiUtils; +import org.vcell.optimization.OptJobRecord; +import org.vcell.optimization.OptJobStatus; +import org.vcell.optimization.jtd.OptProblem; +import org.vcell.optimization.jtd.OptProgressReport; +import org.vcell.optimization.jtd.Vcellopt; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.restq.models.OptimizationJobStatus; +import org.vcell.util.DataAccessException; +import org.vcell.util.document.KeyValue; +import org.vcell.util.document.User; + +import java.io.File; +import java.io.IOException; +import java.sql.*; + +@ApplicationScoped +public class OptimizationRestService { + private static final Logger lg = LogManager.getLogger(OptimizationRestService.class); + + private static final OptJobTable optJobTable = OptJobTable.table; + + private final AgroalConnectionFactory connectionFactory; + private final KeyFactory keyFactory; + private final ObjectMapper objectMapper; + + public OptimizationRestService(AgroalConnectionFactory connectionFactory) { + this.connectionFactory = connectionFactory; + this.keyFactory = connectionFactory.getKeyFactory(); + this.objectMapper = new ObjectMapper(); + } + + /** + * Submit a new optimization job. Writes the OptProblem to the filesystem and creates a database record. + * + * @param optProblem the optimization problem to solve + * @param parestDataDir the directory for optimization data files (e.g. /simdata/parest_data) + * @param user the authenticated user submitting the job + * @return the initial job status with the assigned job ID + */ + public OptimizationJobStatus submitOptimization(OptProblem optProblem, File parestDataDir, User user) + throws SQLException, IOException { + Connection con = null; + try { + con = connectionFactory.getConnection(this); + KeyValue jobKey = keyFactory.getNewKey(con); + String filePrefix = "CopasiParest_" + jobKey; + + File optProblemFile = new File(parestDataDir, filePrefix + "_optProblem.json"); + File optOutputFile = new File(parestDataDir, filePrefix + "_optRun.json"); + File optReportFile = new File(parestDataDir, filePrefix + "_optReport.txt"); + + // Write the OptProblem to the filesystem + if (!parestDataDir.exists()) { + parestDataDir.mkdirs(); + } + CopasiUtils.writeOptProblem(optProblemFile, optProblem); + + // Insert the database record + String sql = "INSERT INTO " + optJobTable.getTableName() + + " " + optJobTable.getSQLColumnList() + + " VALUES " + optJobTable.getSQLValueList(jobKey, user.getID(), OptJobStatus.SUBMITTED, + optProblemFile.getAbsolutePath(), optOutputFile.getAbsolutePath(), optReportFile.getAbsolutePath(), + null, null); + executeUpdate(con, sql); + con.commit(); + + return new OptimizationJobStatus(jobKey, OptJobStatus.SUBMITTED, null, null, null, null); + } catch (SQLException | IOException e) { + if (con != null) con.rollback(); + throw e; + } finally { + if (con != null) connectionFactory.release(con, this); + } + } + + /** + * Get the current status of an optimization job, including progress or results if available. + */ + public OptimizationJobStatus getOptimizationStatus(KeyValue jobKey, User user) + throws SQLException, DataAccessException, IOException { + OptJobRecord record = getOptJobRecord(jobKey); + if (record == null) { + throw new DataAccessException("Optimization job not found: " + jobKey); + } + if (!record.ownerKey().equals(user.getID())) { + throw new DataAccessException("Not authorized to access optimization job: " + jobKey); + } + + OptProgressReport progressReport = null; + Vcellopt results = null; + + switch (record.status()) { + case SUBMITTED: + case RUNNING: + case QUEUED: + // Try to read progress from the report file. + // Even in SUBMITTED state, the SLURM job may already be running and writing progress + // (the QUEUED status message from vcell-submit arrives asynchronously). + progressReport = readProgressReport(record.optReportFile()); + // Check if the output file has appeared (solver completed) + results = readResults(record.optOutputFile()); + if (results != null) { + updateOptJobStatus(jobKey, OptJobStatus.COMPLETE, null); + return new OptimizationJobStatus(jobKey, OptJobStatus.COMPLETE, null, record.htcJobId(), progressReport, results); + } + // Auto-promote to RUNNING if progress report exists and we're still in SUBMITTED/QUEUED + if (progressReport != null && record.status() != OptJobStatus.RUNNING) { + updateOptJobStatus(jobKey, OptJobStatus.RUNNING, null); + return new OptimizationJobStatus(jobKey, OptJobStatus.RUNNING, null, record.htcJobId(), progressReport, null); + } + break; + case COMPLETE: + progressReport = readProgressReport(record.optReportFile()); + results = readResults(record.optOutputFile()); + break; + case STOPPED: + // After stop, the report file has progress up to the kill point + progressReport = readProgressReport(record.optReportFile()); + break; + case FAILED: + break; + } + + return new OptimizationJobStatus(jobKey, record.status(), record.statusMessage(), record.htcJobId(), progressReport, results); + } + + /** + * Update the status of an optimization job (e.g. when vcell-submit reports back). + */ + public void updateOptJobStatus(KeyValue jobKey, OptJobStatus status, String statusMessage) + throws SQLException { + Connection con = null; + try { + con = connectionFactory.getConnection(this); + String sql = "UPDATE " + optJobTable.getTableName() + + " SET " + optJobTable.getSQLUpdateList(status, statusMessage) + + " WHERE " + optJobTable.id + "=" + jobKey; + executeUpdate(con, sql); + con.commit(); + } catch (SQLException e) { + if (con != null) con.rollback(); + throw e; + } finally { + if (con != null) connectionFactory.release(con, this); + } + } + + /** + * Update the SLURM job ID after vcell-submit confirms submission. + */ + public void updateHtcJobId(KeyValue jobKey, String htcJobId) throws SQLException { + Connection con = null; + try { + con = connectionFactory.getConnection(this); + String sql = "UPDATE " + optJobTable.getTableName() + + " SET " + optJobTable.getSQLUpdateListHtcJobId(htcJobId, OptJobStatus.QUEUED) + + " WHERE " + optJobTable.id + "=" + jobKey; + executeUpdate(con, sql); + con.commit(); + } catch (SQLException e) { + if (con != null) con.rollback(); + throw e; + } finally { + if (con != null) connectionFactory.release(con, this); + } + } + + /** + * Get the SLURM job ID for a given optimization job (needed for stop). + */ + public String getHtcJobId(KeyValue jobKey) throws SQLException, DataAccessException { + OptJobRecord record = getOptJobRecord(jobKey); + if (record == null) { + throw new DataAccessException("Optimization job not found: " + jobKey); + } + return record.htcJobId(); + } + + /** + * List optimization jobs for a user, most recent first. Returns lightweight status (no progress/results). + */ + public OptimizationJobStatus[] listOptimizationJobs(User user) throws SQLException { + Connection con = null; + try { + con = connectionFactory.getConnection(this); + String sql = "SELECT " + optJobTable.id + "," + + optJobTable.status + "," + + optJobTable.htcJobId + "," + + optJobTable.statusMessage + "," + + optJobTable.insertDate + "," + + optJobTable.updateDate + + " FROM " + optJobTable.getTableName() + + " WHERE " + optJobTable.ownerRef + "=" + user.getID() + + " ORDER BY " + optJobTable.insertDate + " DESC"; + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(sql)) { + java.util.List jobs = new java.util.ArrayList<>(); + while (rs.next()) { + jobs.add(new OptimizationJobStatus( + new KeyValue(rs.getBigDecimal(optJobTable.id.toString())), + OptJobStatus.valueOf(rs.getString(optJobTable.status.toString())), + rs.getString(optJobTable.statusMessage.toString()), + rs.getString(optJobTable.htcJobId.toString()), + null, + null + )); + } + return jobs.toArray(new OptimizationJobStatus[0]); + } + } finally { + if (con != null) connectionFactory.release(con, this); + } + } + + // --- Private helpers --- + + private OptJobRecord getOptJobRecord(KeyValue jobKey) throws SQLException { + Connection con = null; + try { + con = connectionFactory.getConnection(this); + String sql = "SELECT * FROM " + optJobTable.getTableName() + + " WHERE " + optJobTable.id + "=" + jobKey; + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(sql)) { + if (rs.next()) { + return optJobTable.getOptJobRecord(rs); + } + return null; + } + } finally { + if (con != null) connectionFactory.release(con, this); + } + } + + private void executeUpdate(Connection con, String sql) throws SQLException { + if (lg.isDebugEnabled()) lg.debug(sql); + Statement stmt = con.createStatement(); + try { + int rowCount = stmt.executeUpdate(sql); + if (rowCount != 1) { + throw new SQLException("Expected 1 row, got " + rowCount); + } + } finally { + stmt.close(); + } + } + + private OptProgressReport readProgressReport(String reportFilePath) { + try { + File f = new File(reportFilePath); + if (f.exists()) { + return CopasiUtils.readProgressReportFromCSV(f); + } + } catch (IOException e) { + lg.warn("Failed to read progress report from {}: {}", reportFilePath, e.getMessage()); + } + return null; + } + + private Vcellopt readResults(String outputFilePath) { + try { + File f = new File(outputFilePath); + if (f.exists()) { + return objectMapper.readValue(f, Vcellopt.class); + } + } catch (IOException e) { + lg.warn("Failed to read optimization results from {}: {}", outputFilePath, e.getMessage()); + } + return null; + } +} diff --git a/vcell-rest/src/main/resources/application.properties b/vcell-rest/src/main/resources/application.properties index 932fd8285f..310703bd56 100644 --- a/vcell-rest/src/main/resources/application.properties +++ b/vcell-rest/src/main/resources/application.properties @@ -179,12 +179,33 @@ quarkus.swagger-ui.always-include=true %test.mp.messaging.outgoing.publisher-client-status.connect=smallrye-amqp %test.mp.messaging.outgoing.publisher-client-status.address=client-status +%test.mp.messaging.outgoing.publisher-opt-request.connector=smallrye-amqp +%test.mp.messaging.outgoing.publisher-opt-request.address=opt-request +%test.mp.messaging.outgoing.publisher-opt-request.capabilities=queue + +%test.mp.messaging.incoming.subscriber-opt-status.connector=smallrye-amqp +%test.mp.messaging.incoming.subscriber-opt-status.address=opt-status +%test.mp.messaging.incoming.subscriber-opt-status.capabilities=queue + quarkus.amqp.devservices.enabled=false +%prod.amqp-host=${jmshost_artemis_internal:localhost} +%prod.amqp-port=${jmsport_artemis_internal:5672} +%prod.amqp-username=${AMQP_USER:guest} +%prod.amqp-password=${AMQP_PASSWORD:guest} + +mp.messaging.outgoing.publisher-opt-request.connector=smallrye-amqp +mp.messaging.outgoing.publisher-opt-request.address=opt-request +mp.messaging.outgoing.publisher-opt-request.capabilities=queue + +mp.messaging.incoming.subscriber-opt-status.connector=smallrye-amqp +mp.messaging.incoming.subscriber-opt-status.address=opt-status +mp.messaging.incoming.subscriber-opt-status.capabilities=queue vcell.exporter=false ## VCell properties +%test.vcell.optimization.parest-data-dir=${java.io.tmpdir}/vcell-parest-test %dev,test.vcell.softwareVersion=8.0.0 quarkus.mailer.from=VCell_Support@uchc.edu quarkus.mailer.host=vdsmtp.cam.uchc.edu diff --git a/vcell-rest/src/main/resources/scripts/init.sql b/vcell-rest/src/main/resources/scripts/init.sql index f338f9d49a..d08f5d3033 100644 --- a/vcell-rest/src/main/resources/scripts/init.sql +++ b/vcell-rest/src/main/resources/scripts/init.sql @@ -76,6 +76,7 @@ CREATE TABLE vc_userlogininfo(id bigint PRIMARY KEY,userRef bigint NOT NULL REFE CREATE TABLE vc_metadata(id bigint PRIMARY KEY,bioModelRef bigint NOT NULL REFERENCES vc_biomodel(id) ON DELETE CASCADE,vcMetaDataLarge text ,vcMetaDataSmall varchar(4000) ); CREATE TABLE vc_simdelfromdisk(deldate varchar(20) ,userid varchar(255) NOT NULL,userkey bigint ,simid bigint ,simpref bigint ,simdate varchar(20) ,simname varchar(255) NOT NULL,status varchar(10) ,numfiles bigint ,totalsize bigint ); CREATE TABLE vc_useridentity(id bigint PRIMARY KEY,userRef bigint NOT NULL REFERENCES vc_userinfo(id),authSubject varchar(128) NOT NULL,authIssuer varchar(128) NOT NULL,insertDate timestamp NOT NULL); +CREATE TABLE vc_optjob(id bigint PRIMARY KEY,ownerRef bigint NOT NULL REFERENCES vc_userinfo(id),status varchar(32) NOT NULL,optProblemFile varchar(512) NOT NULL,optOutputFile varchar(512) NOT NULL,optReportFile varchar(512) NOT NULL,htcJobId varchar(128) ,statusMessage varchar(4000) ,insertDate timestamp NOT NULL,updateDate timestamp NOT NULL); CREATE VIEW public.dual AS SELECT CAST('X' as varchar) AS dummy; @@ -88,6 +89,7 @@ CREATE INDEX geom_imageref ON vc_geometry(imageRef); CREATE INDEX mathdesc_geomref ON vc_math(geometryRef); CREATE INDEX simcstat_simcref ON vc_simcontextstat(simContextRef); + INSERT INTO vc_userinfo VALUES ( 0,'void','1700596370242','void@example.com','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty',CURRENT_TIMESTAMP,'B9BDD75BC5382CA83D5AB82172A98D869555899C' ); INSERT INTO vc_userinfo VALUES ( 2,'Administrator','1700596370260','Administrator@example.com','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty',CURRENT_TIMESTAMP,'CD181552B879A2F29D10434D8ACF692B6C8126F9' ); INSERT INTO vc_userinfo VALUES ( 3,'vcellNagios','1700596370261','vcellNagios@example.com','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty',CURRENT_TIMESTAMP,'A93453F7962799355608EC89D33D3249474E538F' ); diff --git a/vcell-rest/src/test/java/org/vcell/restq/OptimizationCrossProtocolTest.java b/vcell-rest/src/test/java/org/vcell/restq/OptimizationCrossProtocolTest.java new file mode 100644 index 0000000000..a35017014b --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/OptimizationCrossProtocolTest.java @@ -0,0 +1,177 @@ +package org.vcell.restq; + +import cbit.vcell.resource.PropertyLoader; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.keycloak.client.KeycloakTestClient; +import jakarta.inject.Inject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.junit.jupiter.api.*; +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.api.OptimizationResourceApi; +import org.vcell.restclient.model.OptJobStatus; +import org.vcell.restclient.model.OptimizationJobStatus; +import org.vcell.restq.config.CDIVCellConfigProvider; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.restq.testresources.ArtemisTestResource; +import org.vcell.restq.testresources.OpenWireOptSubmitStub; +import org.vcell.util.DataAccessException; + +import java.io.File; +import java.sql.SQLException; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Cross-protocol integration test for the optimization messaging pipeline. + * + * Tests the full round-trip: + * REST submit → AMQP 1.0 publish (vcell-rest) → Artemis broker → OpenWire JMS consume (stub) + * → OpenWire JMS publish (stub) → Artemis broker → AMQP 1.0 consume (vcell-rest) → DB update + * → REST poll returns results + * + * The OpenWire stub mimics vcell-submit's OptimizationBatchServer using the same ActiveMQ + * OpenWire protocol. This catches cross-protocol issues like ANYCAST/MULTICAST routing mismatches + * and AMQP address mapping errors. + */ +@QuarkusTest +@Tag("Quarkus") +@QuarkusTestResource(ArtemisTestResource.class) +public class OptimizationCrossProtocolTest { + private static final Logger lg = LogManager.getLogger(OptimizationCrossProtocolTest.class); + + @Inject + AgroalConnectionFactory agroalConnectionFactory; + + @ConfigProperty(name = "quarkus.http.test-port") + Integer testPort; + + @ConfigProperty(name = "vcell.optimization.parest-data-dir") + String parestDataDir; + + @ConfigProperty(name = "artemis.openwire.host") + String openwireHost; + + @ConfigProperty(name = "artemis.openwire.port") + int openwirePort; + + KeycloakTestClient keycloakClient = new KeycloakTestClient(); + OpenWireOptSubmitStub stub; + + @BeforeAll + public static void setupConfig() { + PropertyLoader.setConfigProvider(new CDIVCellConfigProvider()); + } + + @BeforeEach + public void startStub() throws Exception { + stub = new OpenWireOptSubmitStub(openwireHost, openwirePort); + stub.start(); + } + + @AfterEach + public void cleanup() throws Exception { + if (stub != null) { + stub.stop(); + } + TestEndpointUtils.removeAllMappings(agroalConnectionFactory); + } + + /** + * Tests the full cross-protocol round-trip: submit via REST, messages flow through Artemis + * between AMQP 1.0 (vcell-rest) and OpenWire JMS (stub), results returned via REST polling. + */ + @Test + public void testCrossProtocol_submitPollComplete() throws Exception { + // Set up authenticated API client (same as desktop client) + ApiClient apiClient = TestEndpointUtils.createAuthenticatedAPIClient( + keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.alice); + TestEndpointUtils.mapApiClientToAdmin(apiClient); + OptimizationResourceApi optApi = new OptimizationResourceApi(apiClient); + + // Submit optimization via REST (triggers AMQP 1.0 publish to opt-request) + org.vcell.restclient.model.OptProblem optProblem = createClientOptProblem(); + OptimizationJobStatus submitResult = optApi.submitOptimization(optProblem); + assertNotNull(submitResult.getId()); + assertEquals(OptJobStatus.SUBMITTED, submitResult.getStatus()); + lg.info("Submitted optimization job: {}", submitResult.getId()); + + // Poll for completion — the OpenWire stub processes the request through Artemis + // and sends status back, which vcell-rest consumes via AMQP 1.0 + long jobId = Long.parseLong(submitResult.getId()); + OptimizationJobStatus finalStatus = null; + long startTime = System.currentTimeMillis(); + long timeoutMs = 30_000; + + while ((System.currentTimeMillis() - startTime) < timeoutMs) { + OptimizationJobStatus status = optApi.getOptimizationStatus(jobId); + lg.info("Poll: job={}, status={}", jobId, status.getStatus()); + + if (status.getStatus() == OptJobStatus.COMPLETE) { + finalStatus = status; + break; + } + if (status.getStatus() == OptJobStatus.FAILED) { + fail("Optimization job failed: " + status.getStatusMessage()); + } + + Thread.sleep(500); + } + + // Verify the full round-trip produced correct results + assertNotNull(finalStatus, "Should have received COMPLETE status before timeout"); + assertEquals(OptJobStatus.COMPLETE, finalStatus.getStatus()); + assertNotNull(finalStatus.getResults(), "COMPLETE status should include results"); + assertNotNull(finalStatus.getResults().getOptResultSet(), "Results should have optResultSet"); + assertEquals(0.001, finalStatus.getResults().getOptResultSet().getObjectiveFunction(), 0.0001); + + var params = finalStatus.getResults().getOptResultSet().getOptParameterValues(); + assertNotNull(params); + assertEquals(1.5, params.get("k1"), 0.001); + assertEquals(2.5, params.get("k2"), 0.001); + } + + private org.vcell.restclient.model.OptProblem createClientOptProblem() { + var optProblem = new org.vcell.restclient.model.OptProblem(); + optProblem.setMathModelSbmlContents("test"); + optProblem.setNumberOfOptimizationRuns(1); + + var p1 = new org.vcell.restclient.model.ParameterDescription(); + p1.setName("k1"); + p1.setMinValue(0.0); + p1.setMaxValue(10.0); + p1.setInitialValue(1.0); + p1.setScale(1.0); + + var p2 = new org.vcell.restclient.model.ParameterDescription(); + p2.setName("k2"); + p2.setMinValue(0.0); + p2.setMaxValue(10.0); + p2.setInitialValue(2.0); + p2.setScale(1.0); + + optProblem.setParameterDescriptionList(java.util.List.of(p1, p2)); + optProblem.setDataSet(java.util.List.of( + java.util.List.of(0.0, 1.0, 2.0), + java.util.List.of(1.0, 1.5, 2.5) + )); + + var rv1 = new org.vcell.restclient.model.ReferenceVariable(); + rv1.setVarName("t"); + rv1.setReferenceVariableType(org.vcell.restclient.model.ReferenceVariableReferenceVariableType.INDEPENDENT); + var rv2 = new org.vcell.restclient.model.ReferenceVariable(); + rv2.setVarName("x"); + rv2.setReferenceVariableType(org.vcell.restclient.model.ReferenceVariableReferenceVariableType.DEPENDENT); + + optProblem.setReferenceVariable(java.util.List.of(rv1, rv2)); + + var method = new org.vcell.restclient.model.CopasiOptimizationMethod(); + method.setOptimizationMethodType(org.vcell.restclient.model.CopasiOptimizationMethodOptimizationMethodType.EVOLUTIONARYPROGRAM); + method.setOptimizationParameter(java.util.List.of()); + optProblem.setCopasiOptimizationMethod(method); + + return optProblem; + } +} diff --git a/vcell-rest/src/test/java/org/vcell/restq/OptimizationE2ETest.java b/vcell-rest/src/test/java/org/vcell/restq/OptimizationE2ETest.java new file mode 100644 index 0000000000..1b175f807c --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/OptimizationE2ETest.java @@ -0,0 +1,274 @@ +package org.vcell.restq; + +import cbit.vcell.resource.PropertyLoader; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.keycloak.client.KeycloakTestClient; +import jakarta.inject.Inject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.junit.jupiter.api.*; +import org.vcell.optimization.OptJobStatus; +import org.vcell.optimization.jtd.*; +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.api.OptimizationResourceApi; +import org.vcell.restq.config.CDIVCellConfigProvider; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.util.DataAccessException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.sql.SQLException; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * End-to-end test exercising the same code path as the desktop client's parameter estimation. + * + * Calls CopasiOptimizationSolverRemote.solveRemoteApi() (the testable overload) against a live + * Quarkus instance with testcontainers. A mock vcell-submit consumer simulates the SLURM job + * lifecycle by updating database status and writing result files to the filesystem. + * + * This tests the full round-trip: client → REST → DB → filesystem → client, using the same + * generated OptimizationResourceApi that the desktop client uses. + */ +@QuarkusTest +@Tag("Quarkus") +public class OptimizationE2ETest { + private static final Logger lg = LogManager.getLogger(OptimizationE2ETest.class); + + @Inject + ObjectMapper objectMapper; + + @Inject + AgroalConnectionFactory agroalConnectionFactory; + + @Inject + org.vcell.restq.services.OptimizationRestService optimizationRestService; + + @ConfigProperty(name = "quarkus.http.test-port") + Integer testPort; + + @ConfigProperty(name = "vcell.optimization.parest-data-dir") + String parestDataDir; + + KeycloakTestClient keycloakClient = new KeycloakTestClient(); + + @BeforeAll + public static void setupConfig() { + PropertyLoader.setConfigProvider(new CDIVCellConfigProvider()); + } + + @AfterEach + public void removeOIDCMappings() throws SQLException, DataAccessException { + TestEndpointUtils.removeAllMappings(agroalConnectionFactory); + } + + /** + * E2E test: submit optimization via generated client, simulate vcell-submit processing, + * verify that the client receives results. + * + * This exercises the same code path as the desktop client's CopasiOptimizationSolverRemote, + * but with a mock vcell-submit consumer instead of real SLURM. + */ + @Test + public void testOptimizationE2E_submitPollComplete() throws Exception { + // Set up authenticated API client (same as desktop client would) + ApiClient apiClient = TestEndpointUtils.createAuthenticatedAPIClient( + keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.alice); + TestEndpointUtils.mapApiClientToAdmin(apiClient); + + OptimizationResourceApi optApi = new OptimizationResourceApi(apiClient); + + // Build OptProblem using the generated client model (same as desktop client) + org.vcell.restclient.model.OptProblem optProblem = createClientOptProblem(); + + // Submit the job + org.vcell.restclient.model.OptimizationJobStatus submitResult = optApi.submitOptimization(optProblem); + assertNotNull(submitResult.getId()); + assertEquals(org.vcell.restclient.model.OptJobStatus.SUBMITTED, submitResult.getStatus()); + lg.info("Submitted optimization job: {}", submitResult.getId()); + + // Simulate vcell-submit processing in a background thread (mock consumer) + String jobId = submitResult.getId(); + CompletableFuture mockSubmit = CompletableFuture.runAsync(() -> { + try { + simulateVcellSubmitProcessing(jobId); + } catch (Exception e) { + throw new RuntimeException("Mock vcell-submit failed", e); + } + }); + + // Poll for results (same loop as CopasiOptimizationSolverRemote) + org.vcell.restclient.model.OptimizationJobStatus finalStatus = null; + long startTime = System.currentTimeMillis(); + long timeoutMs = 30_000; // 30 seconds for test + + while ((System.currentTimeMillis() - startTime) < timeoutMs) { + org.vcell.restclient.model.OptimizationJobStatus status = optApi.getOptimizationStatus( + Long.parseLong(jobId)); + lg.info("Poll: job={}, status={}", jobId, status.getStatus()); + + if (status.getStatus() == org.vcell.restclient.model.OptJobStatus.COMPLETE) { + finalStatus = status; + break; + } + if (status.getStatus() == org.vcell.restclient.model.OptJobStatus.FAILED) { + fail("Optimization job failed: " + status.getStatusMessage()); + } + + Thread.sleep(500); // poll faster than real client for test speed + } + + // Verify the mock consumer completed without error + mockSubmit.get(5, TimeUnit.SECONDS); + + // Verify results + assertNotNull(finalStatus, "Should have received COMPLETE status before timeout"); + assertEquals(org.vcell.restclient.model.OptJobStatus.COMPLETE, finalStatus.getStatus()); + assertNotNull(finalStatus.getResults(), "COMPLETE status should include results"); + assertNotNull(finalStatus.getResults().getOptResultSet(), "Results should have optResultSet"); + assertEquals(0.001, finalStatus.getResults().getOptResultSet().getObjectiveFunction(), 0.0001); + + Map params = finalStatus.getResults().getOptResultSet().getOptParameterValues(); + assertNotNull(params); + assertEquals(1.5, params.get("k1"), 0.001); + assertEquals(2.5, params.get("k2"), 0.001); + } + + /** + * E2E test: submit optimization, then stop it mid-run. + * Verifies that stop returns the last progress report. + */ + @Test + public void testOptimizationE2E_submitAndStop() throws Exception { + ApiClient apiClient = TestEndpointUtils.createAuthenticatedAPIClient( + keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.alice); + TestEndpointUtils.mapApiClientToAdmin(apiClient); + + OptimizationResourceApi optApi = new OptimizationResourceApi(apiClient); + org.vcell.restclient.model.OptProblem optProblem = createClientOptProblem(); + + // Submit + org.vcell.restclient.model.OptimizationJobStatus submitResult = optApi.submitOptimization(optProblem); + String jobId = submitResult.getId(); + + // Simulate vcell-submit: transition to RUNNING with progress but don't complete + org.vcell.util.document.KeyValue jobKey = new org.vcell.util.document.KeyValue(jobId); + optimizationRestService.updateHtcJobId(jobKey, "SLURM:99999"); + optimizationRestService.updateOptJobStatus(jobKey, OptJobStatus.RUNNING, null); + + // Write a progress report + File reportFile = new File(parestDataDir, "CopasiParest_" + jobId + "_optReport.txt"); + reportFile.getParentFile().mkdirs(); + Files.writeString(reportFile.toPath(), + "[\"k1\",\"k2\"]\n" + + "10\t0.5\t1.0\t2.0\n" + + "20\t0.3\t1.2\t2.3\n"); + + // Verify RUNNING with progress + org.vcell.restclient.model.OptimizationJobStatus runningStatus = optApi.getOptimizationStatus( + Long.parseLong(jobId)); + assertEquals(org.vcell.restclient.model.OptJobStatus.RUNNING, runningStatus.getStatus()); + assertNotNull(runningStatus.getProgressReport(), "RUNNING should include progress"); + + // Stop the job + org.vcell.restclient.model.OptimizationJobStatus stopResult = optApi.stopOptimization( + Long.parseLong(jobId)); + assertEquals(org.vcell.restclient.model.OptJobStatus.STOPPED, stopResult.getStatus()); + assertEquals("Stopped by user", stopResult.getStatusMessage()); + + // Progress should still be available after stop + org.vcell.restclient.model.OptimizationJobStatus afterStop = optApi.getOptimizationStatus( + Long.parseLong(jobId)); + assertEquals(org.vcell.restclient.model.OptJobStatus.STOPPED, afterStop.getStatus()); + assertNotNull(afterStop.getProgressReport(), "Progress should survive stop"); + } + + /** + * Simulates what vcell-submit would do: transition the job through QUEUED → RUNNING → COMPLETE + * and write result files to the filesystem. + */ + private void simulateVcellSubmitProcessing(String jobId) throws Exception { + org.vcell.util.document.KeyValue jobKey = new org.vcell.util.document.KeyValue(jobId); + + // Phase 1: QUEUED (as if SLURM accepted the job) + Thread.sleep(500); + optimizationRestService.updateHtcJobId(jobKey, "SLURM:12345"); + lg.info("Mock vcell-submit: job {} → QUEUED", jobId); + + // Phase 2: RUNNING with progress report + Thread.sleep(500); + optimizationRestService.updateOptJobStatus(jobKey, OptJobStatus.RUNNING, null); + + File reportFile = new File(parestDataDir, "CopasiParest_" + jobId + "_optReport.txt"); + reportFile.getParentFile().mkdirs(); + Files.writeString(reportFile.toPath(), + "[\"k1\",\"k2\"]\n" + + "10\t0.5\t1.0\t2.0\n" + + "20\t0.1\t1.3\t2.4\n" + + "30\t0.01\t1.5\t2.5\n"); + lg.info("Mock vcell-submit: job {} → RUNNING with progress", jobId); + + // Phase 3: COMPLETE with results + Thread.sleep(500); + File outputFile = new File(parestDataDir, "CopasiParest_" + jobId + "_optRun.json"); + Vcellopt vcellopt = new Vcellopt(); + vcellopt.setStatus(VcelloptStatus.COMPLETE); + vcellopt.setStatusMessage("optimization complete"); + OptResultSet resultSet = new OptResultSet(); + resultSet.setNumFunctionEvaluations(30); + resultSet.setObjectiveFunction(0.001); + resultSet.setOptParameterValues(Map.of("k1", 1.5, "k2", 2.5)); + vcellopt.setOptResultSet(resultSet); + objectMapper.writeValue(outputFile, vcellopt); + lg.info("Mock vcell-submit: job {} → wrote results", jobId); + } + + private org.vcell.restclient.model.OptProblem createClientOptProblem() { + var optProblem = new org.vcell.restclient.model.OptProblem(); + optProblem.setMathModelSbmlContents("test"); + optProblem.setNumberOfOptimizationRuns(1); + + var p1 = new org.vcell.restclient.model.ParameterDescription(); + p1.setName("k1"); + p1.setMinValue(0.0); + p1.setMaxValue(10.0); + p1.setInitialValue(1.0); + p1.setScale(1.0); + + var p2 = new org.vcell.restclient.model.ParameterDescription(); + p2.setName("k2"); + p2.setMinValue(0.0); + p2.setMaxValue(10.0); + p2.setInitialValue(2.0); + p2.setScale(1.0); + + optProblem.setParameterDescriptionList(java.util.List.of(p1, p2)); + optProblem.setDataSet(java.util.List.of( + java.util.List.of(0.0, 1.0, 2.0), + java.util.List.of(1.0, 1.5, 2.5) + )); + + var rv1 = new org.vcell.restclient.model.ReferenceVariable(); + rv1.setVarName("t"); + rv1.setReferenceVariableType(org.vcell.restclient.model.ReferenceVariableReferenceVariableType.INDEPENDENT); + var rv2 = new org.vcell.restclient.model.ReferenceVariable(); + rv2.setVarName("x"); + rv2.setReferenceVariableType(org.vcell.restclient.model.ReferenceVariableReferenceVariableType.DEPENDENT); + + optProblem.setReferenceVariable(java.util.List.of(rv1, rv2)); + + var method = new org.vcell.restclient.model.CopasiOptimizationMethod(); + method.setOptimizationMethodType(org.vcell.restclient.model.CopasiOptimizationMethodOptimizationMethodType.EVOLUTIONARYPROGRAM); + method.setOptimizationParameter(java.util.List.of()); + optProblem.setCopasiOptimizationMethod(method); + + return optProblem; + } +} diff --git a/vcell-rest/src/test/java/org/vcell/restq/OptimizationResourceTest.java b/vcell-rest/src/test/java/org/vcell/restq/OptimizationResourceTest.java new file mode 100644 index 0000000000..1cbb5241d4 --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/OptimizationResourceTest.java @@ -0,0 +1,481 @@ +package org.vcell.restq; + +import cbit.vcell.resource.PropertyLoader; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.keycloak.client.KeycloakTestClient; +import jakarta.inject.Inject; +import org.junit.jupiter.api.*; +import org.vcell.optimization.CopasiUtils; +import org.vcell.optimization.OptJobStatus; +import org.vcell.optimization.jtd.*; +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.api.UsersResourceApi; +import org.vcell.restq.config.CDIVCellConfigProvider; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.restq.models.OptimizationJobStatus; +import org.vcell.restq.services.OptimizationRestService; +import org.vcell.util.DataAccessException; +import org.vcell.util.document.KeyValue; +import org.vcell.util.document.User; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +import static io.restassured.RestAssured.given; +import static org.junit.jupiter.api.Assertions.*; + +@QuarkusTest +@Tag("Quarkus") +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class OptimizationResourceTest { + + @Inject + ObjectMapper objectMapper; + + @Inject + AgroalConnectionFactory agroalConnectionFactory; + + @Inject + OptimizationRestService optimizationRestService; + + @Inject + @org.eclipse.microprofile.config.inject.ConfigProperty(name = "quarkus.http.test-port") + Integer testPort; + + KeycloakTestClient keycloakClient = new KeycloakTestClient(); + + private ApiClient aliceAPIClient; + + @BeforeAll + public static void setupConfig() { + PropertyLoader.setConfigProvider(new CDIVCellConfigProvider()); + } + + @BeforeEach + public void createClients() { + aliceAPIClient = TestEndpointUtils.createAuthenticatedAPIClient(keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.alice); + } + + @AfterEach + public void removeOIDCMappings() throws SQLException, DataAccessException { + TestEndpointUtils.removeAllMappings(agroalConnectionFactory); + } + + @Test + @Order(1) + public void testSubmitAndGetStatus() throws Exception { + // Map alice to admin user + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + String accessToken = keycloakClient.getAccessToken("alice"); + + // Create a minimal OptProblem + OptProblem optProblem = createTestOptProblem(); + + // Submit via REST + String responseJson = given() + .header("Authorization", "Bearer " + accessToken) + .contentType("application/json") + .body(objectMapper.writeValueAsString(optProblem)) + .when() + .post("/api/v1/optimization") + .then() + .statusCode(200) + .extract().body().asString(); + + OptimizationJobStatus submitStatus = objectMapper.readValue(responseJson, OptimizationJobStatus.class); + assertNotNull(submitStatus.id()); + assertEquals(OptJobStatus.SUBMITTED, submitStatus.status()); + assertNull(submitStatus.progressReport()); + assertNull(submitStatus.results()); + + // Query status + String statusJson = given() + .header("Authorization", "Bearer " + accessToken) + .when() + .get("/api/v1/optimization/" + submitStatus.id()) + .then() + .statusCode(200) + .extract().body().asString(); + + OptimizationJobStatus getStatus = objectMapper.readValue(statusJson, OptimizationJobStatus.class); + assertEquals(submitStatus.id(), getStatus.id()); + assertEquals(OptJobStatus.SUBMITTED, getStatus.status()); + } + + @Test + @Order(2) + public void testListJobs() throws Exception { + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + String accessToken = keycloakClient.getAccessToken("alice"); + User adminUser = TestEndpointUtils.administratorUser; + + File tempDir = Files.createTempDirectory("parest_test").toFile(); + try { + // Submit two jobs directly via service + OptProblem optProblem = createTestOptProblem(); + OptimizationJobStatus job1 = optimizationRestService.submitOptimization(optProblem, tempDir, adminUser); + OptimizationJobStatus job2 = optimizationRestService.submitOptimization(optProblem, tempDir, adminUser); + + // List via REST + String listJson = given() + .header("Authorization", "Bearer " + accessToken) + .when() + .get("/api/v1/optimization") + .then() + .statusCode(200) + .extract().body().asString(); + + OptimizationJobStatus[] jobs = objectMapper.readValue(listJson, OptimizationJobStatus[].class); + assertTrue(jobs.length >= 2, "Expected at least 2 jobs, got " + jobs.length); + + // Most recent first + for (OptimizationJobStatus job : jobs) { + assertNull(job.progressReport(), "List should not include progressReport"); + assertNull(job.results(), "List should not include results"); + } + } finally { + deleteRecursive(tempDir); + } + } + + @Test + @Order(3) + public void testStatusWithProgressReport() throws Exception { + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + String accessToken = keycloakClient.getAccessToken("alice"); + User adminUser = TestEndpointUtils.administratorUser; + + File tempDir = Files.createTempDirectory("parest_test").toFile(); + try { + OptProblem optProblem = createTestOptProblem(); + OptimizationJobStatus job = optimizationRestService.submitOptimization(optProblem, tempDir, adminUser); + + // Simulate vcell-submit reporting RUNNING + optimizationRestService.updateHtcJobId(job.id(), "SLURM:12345"); + optimizationRestService.updateOptJobStatus(job.id(), OptJobStatus.RUNNING, null); + + // Write a mock progress report file + File reportFile = new File(tempDir, "CopasiParest_" + job.id() + "_optReport.txt"); + // Header: JSON array of param names, then TSV rows: evaluations \t objective \t param values + Files.writeString(reportFile.toPath(), + "[\"k1\",\"k2\"]\n" + + "10\t0.5\t1.0\t2.0\n" + + "20\t0.1\t1.1\t2.1\n"); + + // Query status + String statusJson = given() + .header("Authorization", "Bearer " + accessToken) + .when() + .get("/api/v1/optimization/" + job.id()) + .then() + .statusCode(200) + .extract().body().asString(); + + OptimizationJobStatus status = objectMapper.readValue(statusJson, OptimizationJobStatus.class); + assertEquals(OptJobStatus.RUNNING, status.status()); + assertEquals("SLURM:12345", status.htcJobId()); + assertNotNull(status.progressReport(), "RUNNING status should include progress report"); + assertNull(status.results(), "RUNNING status should not include results"); + } finally { + deleteRecursive(tempDir); + } + } + + @Test + @Order(4) + public void testStatusWithResults() throws Exception { + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + String accessToken = keycloakClient.getAccessToken("alice"); + User adminUser = TestEndpointUtils.administratorUser; + + File tempDir = Files.createTempDirectory("parest_test").toFile(); + try { + OptProblem optProblem = createTestOptProblem(); + OptimizationJobStatus job = optimizationRestService.submitOptimization(optProblem, tempDir, adminUser); + optimizationRestService.updateOptJobStatus(job.id(), OptJobStatus.RUNNING, null); + + // Write a mock output file (simulates solver completion) + File outputFile = new File(tempDir, "CopasiParest_" + job.id() + "_optRun.json"); + Vcellopt vcellopt = new Vcellopt(); + vcellopt.setOptProblem(optProblem); + vcellopt.setStatus(VcelloptStatus.COMPLETE); + vcellopt.setStatusMessage("optimization complete"); + OptResultSet resultSet = new OptResultSet(); + resultSet.setNumFunctionEvaluations(50); + resultSet.setObjectiveFunction(0.001); + resultSet.setOptParameterValues(Map.of("k1", 1.5, "k2", 2.5)); + vcellopt.setOptResultSet(resultSet); + objectMapper.writeValue(outputFile, vcellopt); + + // Query status — should auto-transition to COMPLETE + String statusJson = given() + .header("Authorization", "Bearer " + accessToken) + .when() + .get("/api/v1/optimization/" + job.id()) + .then() + .statusCode(200) + .extract().body().asString(); + + OptimizationJobStatus status = objectMapper.readValue(statusJson, OptimizationJobStatus.class); + assertEquals(OptJobStatus.COMPLETE, status.status()); + assertNotNull(status.results(), "COMPLETE status should include results"); + assertEquals(VcelloptStatus.COMPLETE, status.results().getStatus()); + } finally { + deleteRecursive(tempDir); + } + } + + @Test + @Order(5) + public void testStopJob() throws Exception { + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + String accessToken = keycloakClient.getAccessToken("alice"); + User adminUser = TestEndpointUtils.administratorUser; + + File tempDir = Files.createTempDirectory("parest_test").toFile(); + try { + OptProblem optProblem = createTestOptProblem(); + OptimizationJobStatus job = optimizationRestService.submitOptimization(optProblem, tempDir, adminUser); + optimizationRestService.updateHtcJobId(job.id(), "SLURM:99999"); + optimizationRestService.updateOptJobStatus(job.id(), OptJobStatus.RUNNING, null); + + // Stop via REST + String stopJson = given() + .header("Authorization", "Bearer " + accessToken) + .contentType("application/json") + .when() + .post("/api/v1/optimization/" + job.id() + "/stop") + .then() + .statusCode(200) + .extract().body().asString(); + + OptimizationJobStatus stopStatus = objectMapper.readValue(stopJson, OptimizationJobStatus.class); + assertEquals(OptJobStatus.STOPPED, stopStatus.status()); + assertEquals("Stopped by user", stopStatus.statusMessage()); + } finally { + deleteRecursive(tempDir); + } + } + + @Test + @Order(6) + public void testUnauthorizedAccess() throws Exception { + // Submit as alice/admin + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + User adminUser = TestEndpointUtils.administratorUser; + + File tempDir = Files.createTempDirectory("parest_test").toFile(); + try { + OptProblem optProblem = createTestOptProblem(); + OptimizationJobStatus job = optimizationRestService.submitOptimization(optProblem, tempDir, adminUser); + + // Try to access as bob (different user) + ApiClient bobAPIClient = TestEndpointUtils.createAuthenticatedAPIClient(keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.bob); + TestEndpointUtils.mapApiClientToNagios(bobAPIClient); + String bobToken = keycloakClient.getAccessToken("bob"); + + given() + .header("Authorization", "Bearer " + bobToken) + .when() + .get("/api/v1/optimization/" + job.id()) + .then() + .statusCode(500); // DataAccessException mapped to 500 + } finally { + deleteRecursive(tempDir); + } + } + + @Test + @Order(7) + public void testUnauthenticatedAccess() { + // No auth token — should get 401 + given() + .when() + .get("/api/v1/optimization") + .then() + .statusCode(401); + } + + // ================================================================================== + // Tests using the auto-generated OptimizationResourceApi (vcell-restclient). + // These exercise the same client code path the desktop client will use. + // ================================================================================== + + @Test + @Order(10) + public void testGeneratedClient_submitAndGetStatus() throws Exception { + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + var optApi = new org.vcell.restclient.api.OptimizationResourceApi(aliceAPIClient); + + // Build OptProblem using the generated model types (org.vcell.restclient.model.*) + var optProblem = createGeneratedClientOptProblem(); + + // Submit + org.vcell.restclient.model.OptimizationJobStatus submitResult = optApi.submitOptimization(optProblem); + assertNotNull(submitResult.getId(), "Submit should return a job ID"); + assertEquals(org.vcell.restclient.model.OptJobStatus.SUBMITTED, submitResult.getStatus()); + assertNull(submitResult.getProgressReport()); + assertNull(submitResult.getResults()); + + // Get status by ID + Long jobId = Long.parseLong(submitResult.getId()); + org.vcell.restclient.model.OptimizationJobStatus getResult = optApi.getOptimizationStatus(jobId); + assertEquals(submitResult.getId(), getResult.getId()); + assertEquals(org.vcell.restclient.model.OptJobStatus.SUBMITTED, getResult.getStatus()); + } + + @Test + @Order(11) + public void testGeneratedClient_listJobs() throws Exception { + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + var optApi = new org.vcell.restclient.api.OptimizationResourceApi(aliceAPIClient); + + // Submit two jobs + var optProblem = createGeneratedClientOptProblem(); + optApi.submitOptimization(optProblem); + optApi.submitOptimization(optProblem); + + // List + java.util.List jobs = optApi.listOptimizationJobs(); + assertTrue(jobs.size() >= 2, "Expected at least 2 jobs, got " + jobs.size()); + for (var job : jobs) { + assertNotNull(job.getId()); + assertNotNull(job.getStatus()); + assertNull(job.getProgressReport(), "List should not include progressReport"); + assertNull(job.getResults(), "List should not include results"); + } + } + + @Test + @Order(12) + public void testGeneratedClient_stopJob() throws Exception { + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + var optApi = new org.vcell.restclient.api.OptimizationResourceApi(aliceAPIClient); + User adminUser = TestEndpointUtils.administratorUser; + + // Submit via generated client + var optProblem = createGeneratedClientOptProblem(); + org.vcell.restclient.model.OptimizationJobStatus submitResult = optApi.submitOptimization(optProblem); + Long jobId = Long.parseLong(submitResult.getId()); + + // Transition to RUNNING via the service (simulates vcell-submit status update) + KeyValue jobKey = new KeyValue(submitResult.getId()); + optimizationRestService.updateHtcJobId(jobKey, "SLURM:77777"); + optimizationRestService.updateOptJobStatus(jobKey, OptJobStatus.RUNNING, null); + + // Stop via generated client + org.vcell.restclient.model.OptimizationJobStatus stopResult = optApi.stopOptimization(jobId); + assertEquals(org.vcell.restclient.model.OptJobStatus.STOPPED, stopResult.getStatus()); + assertEquals("Stopped by user", stopResult.getStatusMessage()); + } + + /** + * Create an OptProblem using the generated client model types (org.vcell.restclient.model.*). + * This is the same pattern the desktop client will use. + */ + private org.vcell.restclient.model.OptProblem createGeneratedClientOptProblem() { + var optProblem = new org.vcell.restclient.model.OptProblem(); + optProblem.setMathModelSbmlContents("test"); + optProblem.setNumberOfOptimizationRuns(1); + + var p1 = new org.vcell.restclient.model.ParameterDescription(); + p1.setName("k1"); + p1.setMinValue(0.0); + p1.setMaxValue(10.0); + p1.setInitialValue(1.0); + p1.setScale(1.0); + + var p2 = new org.vcell.restclient.model.ParameterDescription(); + p2.setName("k2"); + p2.setMinValue(0.0); + p2.setMaxValue(10.0); + p2.setInitialValue(2.0); + p2.setScale(1.0); + + optProblem.setParameterDescriptionList(List.of(p1, p2)); + optProblem.setDataSet(List.of( + List.of(0.0, 1.0, 2.0), + List.of(1.0, 1.5, 2.5) + )); + + var rv1 = new org.vcell.restclient.model.ReferenceVariable(); + rv1.setVarName("t"); + rv1.setReferenceVariableType(org.vcell.restclient.model.ReferenceVariableReferenceVariableType.INDEPENDENT); + var rv2 = new org.vcell.restclient.model.ReferenceVariable(); + rv2.setVarName("x"); + rv2.setReferenceVariableType(org.vcell.restclient.model.ReferenceVariableReferenceVariableType.DEPENDENT); + + optProblem.setReferenceVariable(List.of(rv1, rv2)); + + var method = new org.vcell.restclient.model.CopasiOptimizationMethod(); + method.setOptimizationMethodType(org.vcell.restclient.model.CopasiOptimizationMethodOptimizationMethodType.EVOLUTIONARYPROGRAM); + method.setOptimizationParameter(List.of()); + optProblem.setCopasiOptimizationMethod(method); + + return optProblem; + } + + // ================================================================================== + // Helpers + // ================================================================================== + + private OptProblem createTestOptProblem() { + OptProblem optProblem = new OptProblem(); + optProblem.setMathModelSbmlContents("test"); + optProblem.setNumberOfOptimizationRuns(1); + + ParameterDescription p1 = new ParameterDescription(); + p1.setName("k1"); + p1.setMinValue(0.0); + p1.setMaxValue(10.0); + p1.setInitialValue(1.0); + p1.setScale(1.0); + + ParameterDescription p2 = new ParameterDescription(); + p2.setName("k2"); + p2.setMinValue(0.0); + p2.setMaxValue(10.0); + p2.setInitialValue(2.0); + p2.setScale(1.0); + + optProblem.setParameterDescriptionList(List.of(p1, p2)); + optProblem.setDataSet(List.of( + List.of(0.0, 1.0, 2.0), + List.of(1.0, 1.5, 2.5) + )); + + ReferenceVariable rv1 = new ReferenceVariable(); + rv1.setVarName("t"); + rv1.setReferenceVariableType(ReferenceVariableReferenceVariableType.INDEPENDENT); + ReferenceVariable rv2 = new ReferenceVariable(); + rv2.setVarName("x"); + rv2.setReferenceVariableType(ReferenceVariableReferenceVariableType.DEPENDENT); + + optProblem.setReferenceVariable(List.of(rv1, rv2)); + + CopasiOptimizationMethod method = new CopasiOptimizationMethod(); + method.setOptimizationMethodType(CopasiOptimizationMethodOptimizationMethodType.EVOLUTIONARY_PROGRAM); + method.setOptimizationParameter(List.of()); + optProblem.setCopasiOptimizationMethod(method); + + return optProblem; + } + + private static void deleteRecursive(File file) { + if (file.isDirectory()) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + deleteRecursive(child); + } + } + } + file.delete(); + } +} diff --git a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java index bb7f3d9378..d21b2daf5f 100644 --- a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java +++ b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java @@ -40,6 +40,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.eclipse.microprofile.context.ManagedExecutor; + @QuarkusTest public class ExportServerTest { @Inject @@ -53,6 +55,8 @@ public class ExportServerTest { ExportService exportService; @Inject ObjectMapper mapper; + @Inject + ManagedExecutor managedExecutor; private DataServerImpl dataServer; private final String simulationID = "597714292"; @@ -98,7 +102,7 @@ public void testExportStatus() throws Exception { // If an exception is thrown during the export process, the blocking iterable will hang because no finish statement has been sent throw new RuntimeException(e); } - }); + }, managedExecutor); int i = 0; for (ExportEvent exportEvent : blockingIterable) { switch (i){ diff --git a/vcell-rest/src/test/java/org/vcell/restq/testresources/ArtemisTestResource.java b/vcell-rest/src/test/java/org/vcell/restq/testresources/ArtemisTestResource.java new file mode 100644 index 0000000000..a223d80bd3 --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/testresources/ArtemisTestResource.java @@ -0,0 +1,48 @@ +package org.vcell.restq.testresources; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; + +import java.util.Map; + +/** + * Starts an Artemis broker testcontainer with both AMQP 1.0 (5672) and OpenWire (61616) ports exposed. + * Replaces Quarkus AMQP devservices so that cross-protocol tests can connect via OpenWire JMS + * (the same protocol vcell-submit uses in production). + */ +public class ArtemisTestResource implements QuarkusTestResourceLifecycleManager { + + private GenericContainer artemis; + + @Override + public Map start() { + artemis = new GenericContainer<>("quay.io/artemiscloud/activemq-artemis-broker:1.0.25") + .withExposedPorts(5672, 61616) + .withEnv("AMQ_USER", "guest") + .withEnv("AMQ_PASSWORD", "guest") + .waitingFor(Wait.forListeningPort()); + artemis.start(); + + String host = artemis.getHost(); + int amqpPort = artemis.getMappedPort(5672); + int openwirePort = artemis.getMappedPort(61616); + + return Map.of( + "amqp-host", host, + "amqp-port", String.valueOf(amqpPort), + "amqp-username", "guest", + "amqp-password", "guest", + "quarkus.amqp.devservices.enabled", "false", + "artemis.openwire.host", host, + "artemis.openwire.port", String.valueOf(openwirePort) + ); + } + + @Override + public void stop() { + if (artemis != null) { + artemis.stop(); + } + } +} diff --git a/vcell-rest/src/test/java/org/vcell/restq/testresources/OpenWireOptSubmitStub.java b/vcell-rest/src/test/java/org/vcell/restq/testresources/OpenWireOptSubmitStub.java new file mode 100644 index 0000000000..78cd2c3a87 --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/testresources/OpenWireOptSubmitStub.java @@ -0,0 +1,215 @@ +package org.vcell.restq.testresources; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.vcell.optimization.OptJobStatus; +import org.vcell.optimization.OptRequestMessage; +import org.vcell.optimization.OptStatusMessage; +import org.vcell.optimization.jtd.*; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Test stub that mimics vcell-submit's OptimizationBatchServer.initOptimizationQueue() + * using the same OpenWire JMS protocol (ActiveMQConnectionFactory). + * + * Mirrors the real handleSubmitRequest() flow: + * 1. Receive OptRequestMessage from opt-request queue + * 2. Validate jobId is numeric + * 3. Read the OptProblem file from the path in the message (validates filesystem handoff) + * 4. Write result files to the paths from the message + * 5. Send QUEUED status back on opt-status queue with htcJobId + * + * The only difference from production is that instead of submitting to SLURM, + * the stub writes result files directly (simulating what the SLURM job would produce). + */ +public class OpenWireOptSubmitStub { + private static final Logger lg = LogManager.getLogger(OpenWireOptSubmitStub.class); + + private final String host; + private final int port; + private final ObjectMapper objectMapper = new ObjectMapper(); + private Connection connection; + private final CountDownLatch ready = new CountDownLatch(1); + + public OpenWireOptSubmitStub(String host, int port) { + this.host = host; + this.port = port; + } + + public void start() throws Exception { + // Same connection setup as OptimizationBatchServer.initOptimizationQueue() + ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://" + host + ":" + port); + factory.setTrustAllPackages(true); + Connection conn = factory.createConnection(); + conn.start(); + this.connection = conn; + + Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination requestQueue = session.createQueue("opt-request"); + Destination statusQueue = session.createQueue("opt-status"); + MessageConsumer consumer = session.createConsumer(requestQueue); + MessageProducer producer = session.createProducer(statusQueue); + + Thread listenerThread = new Thread(() -> { + ready.countDown(); + while (!Thread.currentThread().isInterrupted()) { + try { + Message msg = consumer.receive(1000); + if (msg instanceof TextMessage textMsg) { + OptRequestMessage req = objectMapper.readValue(textMsg.getText(), OptRequestMessage.class); + lg.info("Stub received: command={}, jobId={}", req.command, req.jobId); + if ("submit".equals(req.command)) { + handleSubmitRequest(req, session, producer); + } else if ("stop".equals(req.command)) { + lg.info("Stub received stop for job {} (no-op in test)", req.jobId); + } else { + lg.warn("Stub: unknown command: {}", req.command); + } + } + } catch (JMSException e) { + if (!Thread.currentThread().isInterrupted()) { + lg.error("Stub listener error: {}", e.getMessage()); + } + break; + } catch (Exception e) { + lg.error("Stub processing error: {}", e.getMessage(), e); + } + } + }, "openwire-opt-stub"); + listenerThread.setDaemon(true); + listenerThread.start(); + + if (!ready.await(10, TimeUnit.SECONDS)) { + throw new RuntimeException("Stub listener did not start in time"); + } + } + + /** + * Mirrors OptimizationBatchServer.handleSubmitRequest() — same validation, same file I/O, + * same status message pattern. Only SLURM submission is replaced with direct file writes. + */ + /** + * Validate that a file path is under the expected parest_data directory to prevent path traversal. + * Same logic as OptimizationBatchServer.validateParestPath(). + */ + private static File validatePath(String filePath, String baseDir) throws java.io.IOException { + File file = new File(filePath).getCanonicalFile(); + java.nio.file.Path basePath = new File(baseDir).getCanonicalFile().toPath(); + if (!file.toPath().startsWith(basePath)) { + throw new java.io.IOException("Invalid file path (outside base dir): " + filePath); + } + return file; + } + + private void handleSubmitRequest(OptRequestMessage request, Session session, MessageProducer producer) { + try { + // Validate jobId is numeric (same as real handleSubmitRequest) + Long.parseLong(request.jobId); + + // Validate and read the OptProblem file from the path in the message + File optProblemFile = validatePath(request.optProblemFilePath, + new File(request.optProblemFilePath).getParentFile().getCanonicalPath()); + OptProblem optProblem = objectMapper.readValue(optProblemFile, OptProblem.class); + lg.info("Stub: read OptProblem from {}, params={}", + optProblemFile.getName(), optProblem.getParameterDescriptionList().size()); + + // Validate file paths from the message + String baseDir = optProblemFile.getParentFile().getCanonicalPath(); + File optOutputFile = validatePath(request.optOutputFilePath, baseDir); + File optReportFile = validatePath(request.optReportFilePath, baseDir); + + // Write progress report file (simulates what the SLURM CopasiParest job writes) + writeProgressReport(optReportFile); + + // Write result file (simulates SLURM job completion) + writeResults(optOutputFile); + + lg.info("Stub: wrote results for job {}", request.jobId); + + // Send QUEUED status back with htcJobId (same as real handleSubmitRequest) + sendStatusMessage(session, producer, request.jobId, OptJobStatus.QUEUED, null, "SLURM:99999"); + + } catch (Exception e) { + lg.error("Stub: failed to process job {}: {}", request.jobId, e.getMessage(), e); + try { + // Send FAILED status (same error handling as real handleSubmitRequest) + sendStatusMessage(session, producer, request.jobId, OptJobStatus.FAILED, e.getMessage(), null); + } catch (JMSException jmsEx) { + lg.error("Stub: failed to send FAILED status: {}", jmsEx.getMessage(), jmsEx); + } + } + } + + private void writeProgressReport(File reportFile) throws Exception { + reportFile.getCanonicalFile().getParentFile().mkdirs(); + java.nio.file.Files.writeString(reportFile.getCanonicalFile().toPath(), + "[\"k1\",\"k2\"]\n" + + "10\t0.5\t1.0\t2.0\n" + + "20\t0.1\t1.3\t2.4\n" + + "30\t0.01\t1.5\t2.5\n"); + } + + private void writeResults(File outputFile) throws Exception { + Vcellopt vcellopt = new Vcellopt(); + vcellopt.setStatus(VcelloptStatus.COMPLETE); + vcellopt.setStatusMessage("optimization complete"); + OptResultSet resultSet = new OptResultSet(); + resultSet.setNumFunctionEvaluations(30); + resultSet.setObjectiveFunction(0.001); + resultSet.setOptParameterValues(Map.of("k1", 1.5, "k2", 2.5)); + OptProgressReport progressReport = new OptProgressReport(); + progressReport.setBestParamValues(Map.of("k1", 1.5, "k2", 2.5)); + OptProgressItem item1 = new OptProgressItem(); + item1.setNumFunctionEvaluations(10); + item1.setObjFuncValue(0.5); + OptProgressItem item2 = new OptProgressItem(); + item2.setNumFunctionEvaluations(20); + item2.setObjFuncValue(0.1); + OptProgressItem item3 = new OptProgressItem(); + item3.setNumFunctionEvaluations(30); + item3.setObjFuncValue(0.01); + progressReport.setProgressItems(List.of(item1, item2, item3)); + resultSet.setOptProgressReport(progressReport); + vcellopt.setOptResultSet(resultSet); + objectMapper.writeValue(outputFile.getCanonicalFile(), vcellopt); + } + + /** + * Same signature and logic as OptimizationBatchServer.sendStatusMessage(). + */ + private void sendStatusMessage(Session session, MessageProducer producer, + String jobId, OptJobStatus status, String statusMessage, String htcJobId) + throws JMSException { + try { + OptStatusMessage statusMsg = new OptStatusMessage(jobId, status, statusMessage, htcJobId); + String json = objectMapper.writeValueAsString(statusMsg); + TextMessage textMessage = session.createTextMessage(json); + producer.send(textMessage); + lg.info("Stub sent status: jobId={}, status={}", jobId, status); + } catch (Exception e) { + lg.error("Stub: failed to send status for job {}: {}", jobId, e.getMessage(), e); + throw new JMSException("Failed to serialize status message: " + e.getMessage()); + } + } + + public void stop() throws Exception { + if (connection != null) { + connection.close(); + } + } +} diff --git a/vcell-restclient/.openapi-generator/FILES b/vcell-restclient/.openapi-generator/FILES index db63317f28..44964ca1cb 100644 --- a/vcell-restclient/.openapi-generator/FILES +++ b/vcell-restclient/.openapi-generator/FILES @@ -15,6 +15,11 @@ docs/BiomodelRef.md docs/CompositeCurve.md docs/ControlPointCurve.md docs/Coordinate.md +docs/CopasiOptimizationMethod.md +docs/CopasiOptimizationMethodOptimizationMethodType.md +docs/CopasiOptimizationParameter.md +docs/CopasiOptimizationParameterDataType.md +docs/CopasiOptimizationParameterParamType.md docs/Curve.md docs/CurveSelectionInfo.md docs/DataIdentifier.md @@ -54,11 +59,21 @@ docs/MathType.md docs/MathmodelRef.md docs/ModelType.md docs/N5ExportRequest.md +docs/OptJobStatus.md +docs/OptProblem.md +docs/OptProgressItem.md +docs/OptProgressReport.md +docs/OptResultSet.md +docs/OptimizationJobStatus.md +docs/OptimizationResourceApi.md docs/Origin.md +docs/ParameterDescription.md docs/Publication.md docs/PublicationInfo.md docs/PublicationResourceApi.md docs/PublishModelsRequest.md +docs/ReferenceVariable.md +docs/ReferenceVariableReferenceVariableType.md docs/SPECIALCLAIM.md docs/SampledCurve.md docs/SchedulerStatus.md @@ -97,6 +112,8 @@ docs/VariableMode.md docs/VariableSpecs.md docs/VariableType.md docs/VcImageResourceApi.md +docs/Vcellopt.md +docs/VcelloptStatus.md docs/Version.md docs/VersionFlag.md src/main/AndroidManifest.xml @@ -116,6 +133,7 @@ src/main/java/org/vcell/restclient/api/FieldDataResourceApi.java src/main/java/org/vcell/restclient/api/GeometryResourceApi.java src/main/java/org/vcell/restclient/api/HelloWorldApi.java src/main/java/org/vcell/restclient/api/MathModelResourceApi.java +src/main/java/org/vcell/restclient/api/OptimizationResourceApi.java src/main/java/org/vcell/restclient/api/PublicationResourceApi.java src/main/java/org/vcell/restclient/api/SimulationResourceApi.java src/main/java/org/vcell/restclient/api/SolverResourceApi.java @@ -134,6 +152,11 @@ src/main/java/org/vcell/restclient/model/BiomodelRef.java src/main/java/org/vcell/restclient/model/CompositeCurve.java src/main/java/org/vcell/restclient/model/ControlPointCurve.java src/main/java/org/vcell/restclient/model/Coordinate.java +src/main/java/org/vcell/restclient/model/CopasiOptimizationMethod.java +src/main/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodType.java +src/main/java/org/vcell/restclient/model/CopasiOptimizationParameter.java +src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterDataType.java +src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterParamType.java src/main/java/org/vcell/restclient/model/Curve.java src/main/java/org/vcell/restclient/model/CurveSelectionInfo.java src/main/java/org/vcell/restclient/model/DataIdentifier.java @@ -168,10 +191,19 @@ src/main/java/org/vcell/restclient/model/MathType.java src/main/java/org/vcell/restclient/model/MathmodelRef.java src/main/java/org/vcell/restclient/model/ModelType.java src/main/java/org/vcell/restclient/model/N5ExportRequest.java +src/main/java/org/vcell/restclient/model/OptJobStatus.java +src/main/java/org/vcell/restclient/model/OptProblem.java +src/main/java/org/vcell/restclient/model/OptProgressItem.java +src/main/java/org/vcell/restclient/model/OptProgressReport.java +src/main/java/org/vcell/restclient/model/OptResultSet.java +src/main/java/org/vcell/restclient/model/OptimizationJobStatus.java src/main/java/org/vcell/restclient/model/Origin.java +src/main/java/org/vcell/restclient/model/ParameterDescription.java src/main/java/org/vcell/restclient/model/Publication.java src/main/java/org/vcell/restclient/model/PublicationInfo.java src/main/java/org/vcell/restclient/model/PublishModelsRequest.java +src/main/java/org/vcell/restclient/model/ReferenceVariable.java +src/main/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableType.java src/main/java/org/vcell/restclient/model/SPECIALCLAIM.java src/main/java/org/vcell/restclient/model/SampledCurve.java src/main/java/org/vcell/restclient/model/SchedulerStatus.java @@ -206,5 +238,24 @@ src/main/java/org/vcell/restclient/model/VariableDomain.java src/main/java/org/vcell/restclient/model/VariableMode.java src/main/java/org/vcell/restclient/model/VariableSpecs.java src/main/java/org/vcell/restclient/model/VariableType.java +src/main/java/org/vcell/restclient/model/Vcellopt.java +src/main/java/org/vcell/restclient/model/VcelloptStatus.java src/main/java/org/vcell/restclient/model/Version.java src/main/java/org/vcell/restclient/model/VersionFlag.java +src/test/java/org/vcell/restclient/api/OptimizationResourceApiTest.java +src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodTypeTest.java +src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodTest.java +src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterDataTypeTest.java +src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterParamTypeTest.java +src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterTest.java +src/test/java/org/vcell/restclient/model/OptJobStatusTest.java +src/test/java/org/vcell/restclient/model/OptProblemTest.java +src/test/java/org/vcell/restclient/model/OptProgressItemTest.java +src/test/java/org/vcell/restclient/model/OptProgressReportTest.java +src/test/java/org/vcell/restclient/model/OptResultSetTest.java +src/test/java/org/vcell/restclient/model/OptimizationJobStatusTest.java +src/test/java/org/vcell/restclient/model/ParameterDescriptionTest.java +src/test/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableTypeTest.java +src/test/java/org/vcell/restclient/model/ReferenceVariableTest.java +src/test/java/org/vcell/restclient/model/VcelloptStatusTest.java +src/test/java/org/vcell/restclient/model/VcelloptTest.java diff --git a/vcell-restclient/README.md b/vcell-restclient/README.md index 598416b98b..3b7da6daca 100644 --- a/vcell-restclient/README.md +++ b/vcell-restclient/README.md @@ -163,6 +163,14 @@ Class | Method | HTTP request | Description *MathModelResourceApi* | [**getVCMLWithHttpInfo**](docs/MathModelResourceApi.md#getVCMLWithHttpInfo) | **GET** /api/v1/mathModel/{id} | *MathModelResourceApi* | [**saveMathModel**](docs/MathModelResourceApi.md#saveMathModel) | **POST** /api/v1/mathModel | *MathModelResourceApi* | [**saveMathModelWithHttpInfo**](docs/MathModelResourceApi.md#saveMathModelWithHttpInfo) | **POST** /api/v1/mathModel | +*OptimizationResourceApi* | [**getOptimizationStatus**](docs/OptimizationResourceApi.md#getOptimizationStatus) | **GET** /api/v1/optimization/{optId} | Get status, progress, or results of an optimization job +*OptimizationResourceApi* | [**getOptimizationStatusWithHttpInfo**](docs/OptimizationResourceApi.md#getOptimizationStatusWithHttpInfo) | **GET** /api/v1/optimization/{optId} | Get status, progress, or results of an optimization job +*OptimizationResourceApi* | [**listOptimizationJobs**](docs/OptimizationResourceApi.md#listOptimizationJobs) | **GET** /api/v1/optimization | List optimization jobs for the authenticated user +*OptimizationResourceApi* | [**listOptimizationJobsWithHttpInfo**](docs/OptimizationResourceApi.md#listOptimizationJobsWithHttpInfo) | **GET** /api/v1/optimization | List optimization jobs for the authenticated user +*OptimizationResourceApi* | [**stopOptimization**](docs/OptimizationResourceApi.md#stopOptimization) | **POST** /api/v1/optimization/{optId}/stop | Stop a running optimization job +*OptimizationResourceApi* | [**stopOptimizationWithHttpInfo**](docs/OptimizationResourceApi.md#stopOptimizationWithHttpInfo) | **POST** /api/v1/optimization/{optId}/stop | Stop a running optimization job +*OptimizationResourceApi* | [**submitOptimization**](docs/OptimizationResourceApi.md#submitOptimization) | **POST** /api/v1/optimization | Submit a new parameter estimation optimization job +*OptimizationResourceApi* | [**submitOptimizationWithHttpInfo**](docs/OptimizationResourceApi.md#submitOptimizationWithHttpInfo) | **POST** /api/v1/optimization | Submit a new parameter estimation optimization job *PublicationResourceApi* | [**createPublication**](docs/PublicationResourceApi.md#createPublication) | **POST** /api/v1/publications | Create publication *PublicationResourceApi* | [**createPublicationWithHttpInfo**](docs/PublicationResourceApi.md#createPublicationWithHttpInfo) | **POST** /api/v1/publications | Create publication *PublicationResourceApi* | [**deletePublication**](docs/PublicationResourceApi.md#deletePublication) | **DELETE** /api/v1/publications/{id} | Delete publication @@ -231,6 +239,11 @@ Class | Method | HTTP request | Description - [CompositeCurve](docs/CompositeCurve.md) - [ControlPointCurve](docs/ControlPointCurve.md) - [Coordinate](docs/Coordinate.md) + - [CopasiOptimizationMethod](docs/CopasiOptimizationMethod.md) + - [CopasiOptimizationMethodOptimizationMethodType](docs/CopasiOptimizationMethodOptimizationMethodType.md) + - [CopasiOptimizationParameter](docs/CopasiOptimizationParameter.md) + - [CopasiOptimizationParameterDataType](docs/CopasiOptimizationParameterDataType.md) + - [CopasiOptimizationParameterParamType](docs/CopasiOptimizationParameterParamType.md) - [Curve](docs/Curve.md) - [CurveSelectionInfo](docs/CurveSelectionInfo.md) - [DataIdentifier](docs/DataIdentifier.md) @@ -265,10 +278,19 @@ Class | Method | HTTP request | Description - [MathmodelRef](docs/MathmodelRef.md) - [ModelType](docs/ModelType.md) - [N5ExportRequest](docs/N5ExportRequest.md) + - [OptJobStatus](docs/OptJobStatus.md) + - [OptProblem](docs/OptProblem.md) + - [OptProgressItem](docs/OptProgressItem.md) + - [OptProgressReport](docs/OptProgressReport.md) + - [OptResultSet](docs/OptResultSet.md) + - [OptimizationJobStatus](docs/OptimizationJobStatus.md) - [Origin](docs/Origin.md) + - [ParameterDescription](docs/ParameterDescription.md) - [Publication](docs/Publication.md) - [PublicationInfo](docs/PublicationInfo.md) - [PublishModelsRequest](docs/PublishModelsRequest.md) + - [ReferenceVariable](docs/ReferenceVariable.md) + - [ReferenceVariableReferenceVariableType](docs/ReferenceVariableReferenceVariableType.md) - [SPECIALCLAIM](docs/SPECIALCLAIM.md) - [SampledCurve](docs/SampledCurve.md) - [SchedulerStatus](docs/SchedulerStatus.md) @@ -303,6 +325,8 @@ Class | Method | HTTP request | Description - [VariableMode](docs/VariableMode.md) - [VariableSpecs](docs/VariableSpecs.md) - [VariableType](docs/VariableType.md) + - [Vcellopt](docs/Vcellopt.md) + - [VcelloptStatus](docs/VcelloptStatus.md) - [Version](docs/Version.md) - [VersionFlag](docs/VersionFlag.md) diff --git a/vcell-restclient/api/openapi.yaml b/vcell-restclient/api/openapi.yaml index 16c828f0c3..edcf927ace 100644 --- a/vcell-restclient/api/openapi.yaml +++ b/vcell-restclient/api/openapi.yaml @@ -1616,6 +1616,167 @@ paths: tags: - Math Model Resource x-accepts: application/json + /api/v1/optimization: + get: + operationId: listOptimizationJobs + responses: + "200": + content: + application/json: + schema: + items: + $ref: '#/components/schemas/OptimizationJobStatus' + type: array + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Not Authenticated + "403": + description: Not Allowed + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Data Access Exception + security: + - openId: + - user + summary: List optimization jobs for the authenticated user + tags: + - Optimization Resource + x-accepts: application/json + post: + operationId: submitOptimization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OptProblem' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/OptimizationJobStatus' + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Not Authenticated + "403": + description: Not Allowed + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Data Access Exception + security: + - openId: + - user + summary: Submit a new parameter estimation optimization job + tags: + - Optimization Resource + x-content-type: application/json + x-accepts: application/json + /api/v1/optimization/{optId}: + get: + operationId: getOptimizationStatus + parameters: + - explode: false + in: path + name: optId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/OptimizationJobStatus' + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Not Authenticated + "403": + description: Not Allowed + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Not found + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Data Access Exception + security: + - openId: + - user + summary: "Get status, progress, or results of an optimization job" + tags: + - Optimization Resource + x-accepts: application/json + /api/v1/optimization/{optId}/stop: + post: + operationId: stopOptimization + parameters: + - explode: false + in: path + name: optId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/OptimizationJobStatus' + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Not Authenticated + "403": + description: Not Allowed + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Not found + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Data Access Exception + security: + - openId: + - user + summary: Stop a running optimization job + tags: + - Optimization Resource + x-accepts: application/json /api/v1/publications: get: operationId: getPublications @@ -2734,6 +2895,76 @@ components: format: double type: number type: object + CopasiOptimizationMethod: + example: + optimizationMethodType: null + optimizationParameter: + - paramType: null + dataType: null + value: 5.962133916683182 + - paramType: null + dataType: null + value: 5.962133916683182 + properties: + optimizationMethodType: + $ref: '#/components/schemas/CopasiOptimizationMethodOptimizationMethodType' + optimizationParameter: + items: + $ref: '#/components/schemas/CopasiOptimizationParameter' + type: array + type: object + CopasiOptimizationMethodOptimizationMethodType: + enum: + - SRES + - evolutionaryProgram + - geneticAlgorithm + - geneticAlgorithmSR + - hookeJeeves + - levenbergMarquardt + - nelderMead + - particleSwarm + - praxis + - randomSearch + - simulatedAnnealing + - steepestDescent + - truncatedNewton + type: string + CopasiOptimizationParameter: + example: + paramType: null + dataType: null + value: 5.962133916683182 + properties: + dataType: + $ref: '#/components/schemas/CopasiOptimizationParameterDataType' + paramType: + $ref: '#/components/schemas/CopasiOptimizationParameterParamType' + value: + format: double + type: number + type: object + CopasiOptimizationParameterDataType: + enum: + - double + - int + type: string + CopasiOptimizationParameterParamType: + enum: + - coolingFactor + - iterationLimit + - numberOfGenerations + - numberOfIterations + - pf + - populationSize + - randomNumberGenerator + - rho + - scale + - seed + - startTemperature + - stdDeviation + - swarmSize + - tolerance + type: string Curve: discriminator: mapping: @@ -3994,6 +4225,211 @@ components: datasetName: type: string type: object + OptJobStatus: + enum: + - SUBMITTED + - QUEUED + - RUNNING + - COMPLETE + - FAILED + - STOPPED + type: string + OptProblem: + example: + referenceVariable: + - varName: varName + referenceVariableType: null + - varName: varName + referenceVariableType: null + numberOfOptimizationRuns: 2 + parameterDescriptionList: + - minValue: 3.616076749251911 + maxValue: 9.301444243932576 + name: name + scale: 2.027123023002322 + initialValue: 7.061401241503109 + - minValue: 3.616076749251911 + maxValue: 9.301444243932576 + name: name + scale: 2.027123023002322 + initialValue: 7.061401241503109 + copasiOptimizationMethod: + optimizationMethodType: null + optimizationParameter: + - paramType: null + dataType: null + value: 5.962133916683182 + - paramType: null + dataType: null + value: 5.962133916683182 + mathModelSbmlContents: mathModelSbmlContents + dataSet: + - - 5.637376656633329 + - 5.637376656633329 + - - 5.637376656633329 + - 5.637376656633329 + properties: + copasiOptimizationMethod: + $ref: '#/components/schemas/CopasiOptimizationMethod' + dataSet: + items: + items: + format: double + type: number + type: array + type: array + mathModelSbmlContents: + type: string + numberOfOptimizationRuns: + format: int32 + type: integer + parameterDescriptionList: + items: + $ref: '#/components/schemas/ParameterDescription' + type: array + referenceVariable: + items: + $ref: '#/components/schemas/ReferenceVariable' + type: array + type: object + OptProgressItem: + example: + objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + properties: + numFunctionEvaluations: + format: int32 + type: integer + objFuncValue: + format: double + type: number + type: object + OptProgressReport: + example: + bestParamValues: + key: 0.8008281904610115 + progressItems: + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + properties: + bestParamValues: + additionalProperties: + format: double + type: number + type: object + progressItems: + items: + $ref: '#/components/schemas/OptProgressItem' + type: array + type: object + OptResultSet: + example: + optProgressReport: + bestParamValues: + key: 0.8008281904610115 + progressItems: + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + objectiveFunction: 7.386281948385884 + optParameterValues: + key: 1.2315135367772556 + numFunctionEvaluations: 4 + properties: + numFunctionEvaluations: + format: int32 + type: integer + objectiveFunction: + format: double + type: number + optParameterValues: + additionalProperties: + format: double + type: number + type: object + optProgressReport: + $ref: '#/components/schemas/OptProgressReport' + type: object + OptimizationJobStatus: + example: + htcJobId: htcJobId + progressReport: + bestParamValues: + key: 0.8008281904610115 + progressItems: + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + id: id + results: + optProblem: + referenceVariable: + - varName: varName + referenceVariableType: null + - varName: varName + referenceVariableType: null + numberOfOptimizationRuns: 2 + parameterDescriptionList: + - minValue: 3.616076749251911 + maxValue: 9.301444243932576 + name: name + scale: 2.027123023002322 + initialValue: 7.061401241503109 + - minValue: 3.616076749251911 + maxValue: 9.301444243932576 + name: name + scale: 2.027123023002322 + initialValue: 7.061401241503109 + copasiOptimizationMethod: + optimizationMethodType: null + optimizationParameter: + - paramType: null + dataType: null + value: 5.962133916683182 + - paramType: null + dataType: null + value: 5.962133916683182 + mathModelSbmlContents: mathModelSbmlContents + dataSet: + - - 5.637376656633329 + - 5.637376656633329 + - - 5.637376656633329 + - 5.637376656633329 + optResultSet: + optProgressReport: + bestParamValues: + key: 0.8008281904610115 + progressItems: + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + objectiveFunction: 7.386281948385884 + optParameterValues: + key: 1.2315135367772556 + numFunctionEvaluations: 4 + statusMessage: statusMessage + status: null + statusMessage: statusMessage + status: null + properties: + id: + type: string + status: + $ref: '#/components/schemas/OptJobStatus' + statusMessage: + type: string + htcJobId: + type: string + progressReport: + $ref: '#/components/schemas/OptProgressReport' + results: + $ref: '#/components/schemas/Vcellopt' + type: object Origin: example: x: 5.962133916683182 @@ -4016,6 +4452,29 @@ components: xml: attribute: true type: object + ParameterDescription: + example: + minValue: 3.616076749251911 + maxValue: 9.301444243932576 + name: name + scale: 2.027123023002322 + initialValue: 7.061401241503109 + properties: + initialValue: + format: double + type: number + maxValue: + format: double + type: number + minValue: + format: double + type: number + name: + type: string + scale: + format: double + type: number + type: object Publication: example: date: 2022-03-10T00:00:00.000+00:00 @@ -4167,6 +4626,21 @@ components: type: integer type: array type: object + ReferenceVariable: + example: + varName: varName + referenceVariableType: null + properties: + referenceVariableType: + $ref: '#/components/schemas/ReferenceVariableReferenceVariableType' + varName: + type: string + type: object + ReferenceVariableReferenceVariableType: + enum: + - dependent + - independent + type: string SPECIAL_CLAIM: enum: - admins @@ -5067,6 +5541,73 @@ components: typeName: type: string type: object + Vcellopt: + example: + optProblem: + referenceVariable: + - varName: varName + referenceVariableType: null + - varName: varName + referenceVariableType: null + numberOfOptimizationRuns: 2 + parameterDescriptionList: + - minValue: 3.616076749251911 + maxValue: 9.301444243932576 + name: name + scale: 2.027123023002322 + initialValue: 7.061401241503109 + - minValue: 3.616076749251911 + maxValue: 9.301444243932576 + name: name + scale: 2.027123023002322 + initialValue: 7.061401241503109 + copasiOptimizationMethod: + optimizationMethodType: null + optimizationParameter: + - paramType: null + dataType: null + value: 5.962133916683182 + - paramType: null + dataType: null + value: 5.962133916683182 + mathModelSbmlContents: mathModelSbmlContents + dataSet: + - - 5.637376656633329 + - 5.637376656633329 + - - 5.637376656633329 + - 5.637376656633329 + optResultSet: + optProgressReport: + bestParamValues: + key: 0.8008281904610115 + progressItems: + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + - objFuncValue: 1.4658129805029452 + numFunctionEvaluations: 6 + objectiveFunction: 7.386281948385884 + optParameterValues: + key: 1.2315135367772556 + numFunctionEvaluations: 4 + statusMessage: statusMessage + status: null + properties: + optProblem: + $ref: '#/components/schemas/OptProblem' + optResultSet: + $ref: '#/components/schemas/OptResultSet' + status: + $ref: '#/components/schemas/VcelloptStatus' + statusMessage: + type: string + type: object + VcelloptStatus: + enum: + - complete + - failed + - queued + - running + type: string Version: example: date: 2000-01-23T04:56:07.000+00:00 diff --git a/vcell-restclient/docs/CopasiOptimizationMethod.md b/vcell-restclient/docs/CopasiOptimizationMethod.md new file mode 100644 index 0000000000..23272c2259 --- /dev/null +++ b/vcell-restclient/docs/CopasiOptimizationMethod.md @@ -0,0 +1,14 @@ + + +# CopasiOptimizationMethod + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**optimizationMethodType** | **CopasiOptimizationMethodOptimizationMethodType** | | [optional] | +|**optimizationParameter** | [**List<CopasiOptimizationParameter>**](CopasiOptimizationParameter.md) | | [optional] | + + + diff --git a/vcell-restclient/docs/CopasiOptimizationMethodOptimizationMethodType.md b/vcell-restclient/docs/CopasiOptimizationMethodOptimizationMethodType.md new file mode 100644 index 0000000000..56605ef3d4 --- /dev/null +++ b/vcell-restclient/docs/CopasiOptimizationMethodOptimizationMethodType.md @@ -0,0 +1,35 @@ + + +# CopasiOptimizationMethodOptimizationMethodType + +## Enum + + +* `SRES` (value: `"SRES"`) + +* `EVOLUTIONARYPROGRAM` (value: `"evolutionaryProgram"`) + +* `GENETICALGORITHM` (value: `"geneticAlgorithm"`) + +* `GENETICALGORITHMSR` (value: `"geneticAlgorithmSR"`) + +* `HOOKEJEEVES` (value: `"hookeJeeves"`) + +* `LEVENBERGMARQUARDT` (value: `"levenbergMarquardt"`) + +* `NELDERMEAD` (value: `"nelderMead"`) + +* `PARTICLESWARM` (value: `"particleSwarm"`) + +* `PRAXIS` (value: `"praxis"`) + +* `RANDOMSEARCH` (value: `"randomSearch"`) + +* `SIMULATEDANNEALING` (value: `"simulatedAnnealing"`) + +* `STEEPESTDESCENT` (value: `"steepestDescent"`) + +* `TRUNCATEDNEWTON` (value: `"truncatedNewton"`) + + + diff --git a/vcell-restclient/docs/CopasiOptimizationParameter.md b/vcell-restclient/docs/CopasiOptimizationParameter.md new file mode 100644 index 0000000000..ae157fc1a5 --- /dev/null +++ b/vcell-restclient/docs/CopasiOptimizationParameter.md @@ -0,0 +1,15 @@ + + +# CopasiOptimizationParameter + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**dataType** | **CopasiOptimizationParameterDataType** | | [optional] | +|**paramType** | **CopasiOptimizationParameterParamType** | | [optional] | +|**value** | **Double** | | [optional] | + + + diff --git a/vcell-restclient/docs/CopasiOptimizationParameterDataType.md b/vcell-restclient/docs/CopasiOptimizationParameterDataType.md new file mode 100644 index 0000000000..1d404da75f --- /dev/null +++ b/vcell-restclient/docs/CopasiOptimizationParameterDataType.md @@ -0,0 +1,13 @@ + + +# CopasiOptimizationParameterDataType + +## Enum + + +* `DOUBLE` (value: `"double"`) + +* `INT` (value: `"int"`) + + + diff --git a/vcell-restclient/docs/CopasiOptimizationParameterParamType.md b/vcell-restclient/docs/CopasiOptimizationParameterParamType.md new file mode 100644 index 0000000000..c7e1b0a6ae --- /dev/null +++ b/vcell-restclient/docs/CopasiOptimizationParameterParamType.md @@ -0,0 +1,37 @@ + + +# CopasiOptimizationParameterParamType + +## Enum + + +* `COOLINGFACTOR` (value: `"coolingFactor"`) + +* `ITERATIONLIMIT` (value: `"iterationLimit"`) + +* `NUMBEROFGENERATIONS` (value: `"numberOfGenerations"`) + +* `NUMBEROFITERATIONS` (value: `"numberOfIterations"`) + +* `PF` (value: `"pf"`) + +* `POPULATIONSIZE` (value: `"populationSize"`) + +* `RANDOMNUMBERGENERATOR` (value: `"randomNumberGenerator"`) + +* `RHO` (value: `"rho"`) + +* `SCALE` (value: `"scale"`) + +* `SEED` (value: `"seed"`) + +* `STARTTEMPERATURE` (value: `"startTemperature"`) + +* `STDDEVIATION` (value: `"stdDeviation"`) + +* `SWARMSIZE` (value: `"swarmSize"`) + +* `TOLERANCE` (value: `"tolerance"`) + + + diff --git a/vcell-restclient/docs/OptJobStatus.md b/vcell-restclient/docs/OptJobStatus.md new file mode 100644 index 0000000000..d25a16cd76 --- /dev/null +++ b/vcell-restclient/docs/OptJobStatus.md @@ -0,0 +1,21 @@ + + +# OptJobStatus + +## Enum + + +* `SUBMITTED` (value: `"SUBMITTED"`) + +* `QUEUED` (value: `"QUEUED"`) + +* `RUNNING` (value: `"RUNNING"`) + +* `COMPLETE` (value: `"COMPLETE"`) + +* `FAILED` (value: `"FAILED"`) + +* `STOPPED` (value: `"STOPPED"`) + + + diff --git a/vcell-restclient/docs/OptProblem.md b/vcell-restclient/docs/OptProblem.md new file mode 100644 index 0000000000..898859e5f2 --- /dev/null +++ b/vcell-restclient/docs/OptProblem.md @@ -0,0 +1,18 @@ + + +# OptProblem + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**copasiOptimizationMethod** | [**CopasiOptimizationMethod**](CopasiOptimizationMethod.md) | | [optional] | +|**dataSet** | **List<List<Double>>** | | [optional] | +|**mathModelSbmlContents** | **String** | | [optional] | +|**numberOfOptimizationRuns** | **Integer** | | [optional] | +|**parameterDescriptionList** | [**List<ParameterDescription>**](ParameterDescription.md) | | [optional] | +|**referenceVariable** | [**List<ReferenceVariable>**](ReferenceVariable.md) | | [optional] | + + + diff --git a/vcell-restclient/docs/OptProgressItem.md b/vcell-restclient/docs/OptProgressItem.md new file mode 100644 index 0000000000..6f1b822114 --- /dev/null +++ b/vcell-restclient/docs/OptProgressItem.md @@ -0,0 +1,14 @@ + + +# OptProgressItem + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**numFunctionEvaluations** | **Integer** | | [optional] | +|**objFuncValue** | **Double** | | [optional] | + + + diff --git a/vcell-restclient/docs/OptProgressReport.md b/vcell-restclient/docs/OptProgressReport.md new file mode 100644 index 0000000000..e7f00fa2b9 --- /dev/null +++ b/vcell-restclient/docs/OptProgressReport.md @@ -0,0 +1,14 @@ + + +# OptProgressReport + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**bestParamValues** | **Map<String, Double>** | | [optional] | +|**progressItems** | [**List<OptProgressItem>**](OptProgressItem.md) | | [optional] | + + + diff --git a/vcell-restclient/docs/OptResultSet.md b/vcell-restclient/docs/OptResultSet.md new file mode 100644 index 0000000000..19ea55c46a --- /dev/null +++ b/vcell-restclient/docs/OptResultSet.md @@ -0,0 +1,16 @@ + + +# OptResultSet + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**numFunctionEvaluations** | **Integer** | | [optional] | +|**objectiveFunction** | **Double** | | [optional] | +|**optParameterValues** | **Map<String, Double>** | | [optional] | +|**optProgressReport** | [**OptProgressReport**](OptProgressReport.md) | | [optional] | + + + diff --git a/vcell-restclient/docs/OptimizationJobStatus.md b/vcell-restclient/docs/OptimizationJobStatus.md new file mode 100644 index 0000000000..0a8653d200 --- /dev/null +++ b/vcell-restclient/docs/OptimizationJobStatus.md @@ -0,0 +1,18 @@ + + +# OptimizationJobStatus + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**id** | **String** | | [optional] | +|**status** | **OptJobStatus** | | [optional] | +|**statusMessage** | **String** | | [optional] | +|**htcJobId** | **String** | | [optional] | +|**progressReport** | [**OptProgressReport**](OptProgressReport.md) | | [optional] | +|**results** | [**Vcellopt**](Vcellopt.md) | | [optional] | + + + diff --git a/vcell-restclient/docs/OptimizationResourceApi.md b/vcell-restclient/docs/OptimizationResourceApi.md new file mode 100644 index 0000000000..aaf8b4143f --- /dev/null +++ b/vcell-restclient/docs/OptimizationResourceApi.md @@ -0,0 +1,572 @@ +# OptimizationResourceApi + +All URIs are relative to *https://vcell.cam.uchc.edu* + +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +| [**getOptimizationStatus**](OptimizationResourceApi.md#getOptimizationStatus) | **GET** /api/v1/optimization/{optId} | Get status, progress, or results of an optimization job | +| [**getOptimizationStatusWithHttpInfo**](OptimizationResourceApi.md#getOptimizationStatusWithHttpInfo) | **GET** /api/v1/optimization/{optId} | Get status, progress, or results of an optimization job | +| [**listOptimizationJobs**](OptimizationResourceApi.md#listOptimizationJobs) | **GET** /api/v1/optimization | List optimization jobs for the authenticated user | +| [**listOptimizationJobsWithHttpInfo**](OptimizationResourceApi.md#listOptimizationJobsWithHttpInfo) | **GET** /api/v1/optimization | List optimization jobs for the authenticated user | +| [**stopOptimization**](OptimizationResourceApi.md#stopOptimization) | **POST** /api/v1/optimization/{optId}/stop | Stop a running optimization job | +| [**stopOptimizationWithHttpInfo**](OptimizationResourceApi.md#stopOptimizationWithHttpInfo) | **POST** /api/v1/optimization/{optId}/stop | Stop a running optimization job | +| [**submitOptimization**](OptimizationResourceApi.md#submitOptimization) | **POST** /api/v1/optimization | Submit a new parameter estimation optimization job | +| [**submitOptimizationWithHttpInfo**](OptimizationResourceApi.md#submitOptimizationWithHttpInfo) | **POST** /api/v1/optimization | Submit a new parameter estimation optimization job | + + + +## getOptimizationStatus + +> OptimizationJobStatus getOptimizationStatus(optId) + +Get status, progress, or results of an optimization job + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + Long optId = 56L; // Long | + try { + OptimizationJobStatus result = apiInstance.getOptimizationStatus(optId); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#getOptimizationStatus"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **optId** | **Long**| | | + +### Return type + +[**OptimizationJobStatus**](OptimizationJobStatus.md) + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **404** | Not found | - | +| **500** | Data Access Exception | - | + +## getOptimizationStatusWithHttpInfo + +> ApiResponse getOptimizationStatus getOptimizationStatusWithHttpInfo(optId) + +Get status, progress, or results of an optimization job + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.ApiResponse; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + Long optId = 56L; // Long | + try { + ApiResponse response = apiInstance.getOptimizationStatusWithHttpInfo(optId); + System.out.println("Status code: " + response.getStatusCode()); + System.out.println("Response headers: " + response.getHeaders()); + System.out.println("Response body: " + response.getData()); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#getOptimizationStatus"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **optId** | **Long**| | | + +### Return type + +ApiResponse<[**OptimizationJobStatus**](OptimizationJobStatus.md)> + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **404** | Not found | - | +| **500** | Data Access Exception | - | + + +## listOptimizationJobs + +> List listOptimizationJobs() + +List optimization jobs for the authenticated user + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + try { + List result = apiInstance.listOptimizationJobs(); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#listOptimizationJobs"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +This endpoint does not need any parameter. + +### Return type + +[**List<OptimizationJobStatus>**](OptimizationJobStatus.md) + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **500** | Data Access Exception | - | + +## listOptimizationJobsWithHttpInfo + +> ApiResponse> listOptimizationJobs listOptimizationJobsWithHttpInfo() + +List optimization jobs for the authenticated user + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.ApiResponse; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + try { + ApiResponse> response = apiInstance.listOptimizationJobsWithHttpInfo(); + System.out.println("Status code: " + response.getStatusCode()); + System.out.println("Response headers: " + response.getHeaders()); + System.out.println("Response body: " + response.getData()); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#listOptimizationJobs"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +This endpoint does not need any parameter. + +### Return type + +ApiResponse<[**List<OptimizationJobStatus>**](OptimizationJobStatus.md)> + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **500** | Data Access Exception | - | + + +## stopOptimization + +> OptimizationJobStatus stopOptimization(optId) + +Stop a running optimization job + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + Long optId = 56L; // Long | + try { + OptimizationJobStatus result = apiInstance.stopOptimization(optId); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#stopOptimization"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **optId** | **Long**| | | + +### Return type + +[**OptimizationJobStatus**](OptimizationJobStatus.md) + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **404** | Not found | - | +| **500** | Data Access Exception | - | + +## stopOptimizationWithHttpInfo + +> ApiResponse stopOptimization stopOptimizationWithHttpInfo(optId) + +Stop a running optimization job + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.ApiResponse; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + Long optId = 56L; // Long | + try { + ApiResponse response = apiInstance.stopOptimizationWithHttpInfo(optId); + System.out.println("Status code: " + response.getStatusCode()); + System.out.println("Response headers: " + response.getHeaders()); + System.out.println("Response body: " + response.getData()); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#stopOptimization"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **optId** | **Long**| | | + +### Return type + +ApiResponse<[**OptimizationJobStatus**](OptimizationJobStatus.md)> + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **404** | Not found | - | +| **500** | Data Access Exception | - | + + +## submitOptimization + +> OptimizationJobStatus submitOptimization(optProblem) + +Submit a new parameter estimation optimization job + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + OptProblem optProblem = new OptProblem(); // OptProblem | + try { + OptimizationJobStatus result = apiInstance.submitOptimization(optProblem); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#submitOptimization"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **optProblem** | [**OptProblem**](OptProblem.md)| | [optional] | + +### Return type + +[**OptimizationJobStatus**](OptimizationJobStatus.md) + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **500** | Data Access Exception | - | + +## submitOptimizationWithHttpInfo + +> ApiResponse submitOptimization submitOptimizationWithHttpInfo(optProblem) + +Submit a new parameter estimation optimization job + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.ApiResponse; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.OptimizationResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + OptimizationResourceApi apiInstance = new OptimizationResourceApi(defaultClient); + OptProblem optProblem = new OptProblem(); // OptProblem | + try { + ApiResponse response = apiInstance.submitOptimizationWithHttpInfo(optProblem); + System.out.println("Status code: " + response.getStatusCode()); + System.out.println("Response headers: " + response.getHeaders()); + System.out.println("Response body: " + response.getData()); + } catch (ApiException e) { + System.err.println("Exception when calling OptimizationResourceApi#submitOptimization"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **optProblem** | [**OptProblem**](OptProblem.md)| | [optional] | + +### Return type + +ApiResponse<[**OptimizationJobStatus**](OptimizationJobStatus.md)> + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **500** | Data Access Exception | - | + diff --git a/vcell-restclient/docs/ParameterDescription.md b/vcell-restclient/docs/ParameterDescription.md new file mode 100644 index 0000000000..3d733d5d26 --- /dev/null +++ b/vcell-restclient/docs/ParameterDescription.md @@ -0,0 +1,17 @@ + + +# ParameterDescription + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**initialValue** | **Double** | | [optional] | +|**maxValue** | **Double** | | [optional] | +|**minValue** | **Double** | | [optional] | +|**name** | **String** | | [optional] | +|**scale** | **Double** | | [optional] | + + + diff --git a/vcell-restclient/docs/ReferenceVariable.md b/vcell-restclient/docs/ReferenceVariable.md new file mode 100644 index 0000000000..307bffdf17 --- /dev/null +++ b/vcell-restclient/docs/ReferenceVariable.md @@ -0,0 +1,14 @@ + + +# ReferenceVariable + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**referenceVariableType** | **ReferenceVariableReferenceVariableType** | | [optional] | +|**varName** | **String** | | [optional] | + + + diff --git a/vcell-restclient/docs/ReferenceVariableReferenceVariableType.md b/vcell-restclient/docs/ReferenceVariableReferenceVariableType.md new file mode 100644 index 0000000000..6285edaa68 --- /dev/null +++ b/vcell-restclient/docs/ReferenceVariableReferenceVariableType.md @@ -0,0 +1,13 @@ + + +# ReferenceVariableReferenceVariableType + +## Enum + + +* `DEPENDENT` (value: `"dependent"`) + +* `INDEPENDENT` (value: `"independent"`) + + + diff --git a/vcell-restclient/docs/Vcellopt.md b/vcell-restclient/docs/Vcellopt.md new file mode 100644 index 0000000000..24a062acb1 --- /dev/null +++ b/vcell-restclient/docs/Vcellopt.md @@ -0,0 +1,16 @@ + + +# Vcellopt + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**optProblem** | [**OptProblem**](OptProblem.md) | | [optional] | +|**optResultSet** | [**OptResultSet**](OptResultSet.md) | | [optional] | +|**status** | **VcelloptStatus** | | [optional] | +|**statusMessage** | **String** | | [optional] | + + + diff --git a/vcell-restclient/docs/VcelloptStatus.md b/vcell-restclient/docs/VcelloptStatus.md new file mode 100644 index 0000000000..36e597f713 --- /dev/null +++ b/vcell-restclient/docs/VcelloptStatus.md @@ -0,0 +1,17 @@ + + +# VcelloptStatus + +## Enum + + +* `COMPLETE` (value: `"complete"`) + +* `FAILED` (value: `"failed"`) + +* `QUEUED` (value: `"queued"`) + +* `RUNNING` (value: `"running"`) + + + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/api/OptimizationResourceApi.java b/vcell-restclient/src/main/java/org/vcell/restclient/api/OptimizationResourceApi.java new file mode 100644 index 0000000000..cf98184e1c --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/api/OptimizationResourceApi.java @@ -0,0 +1,374 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package org.vcell.restclient.api; + +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.ApiResponse; +import org.vcell.restclient.Pair; + +import org.vcell.restclient.model.OptProblem; +import org.vcell.restclient.model.OptimizationJobStatus; +import org.vcell.restclient.model.VCellHTTPError; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; + +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.http.HttpRequest; +import java.nio.channels.Channels; +import java.nio.channels.Pipe; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import java.util.ArrayList; +import java.util.StringJoiner; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OptimizationResourceApi { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public OptimizationResourceApi() { + this(new ApiClient()); + } + + public OptimizationResourceApi(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + + protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; + } + return operationId + " call failed with: " + statusCode + " - " + body; + } + + /** + * Get status, progress, or results of an optimization job + * + * @param optId (required) + * @return OptimizationJobStatus + * @throws ApiException if fails to make API call + */ + public OptimizationJobStatus getOptimizationStatus(Long optId) throws ApiException { + ApiResponse localVarResponse = getOptimizationStatusWithHttpInfo(optId); + return localVarResponse.getData(); + } + + /** + * Get status, progress, or results of an optimization job + * + * @param optId (required) + * @return ApiResponse<OptimizationJobStatus> + * @throws ApiException if fails to make API call + */ + public ApiResponse getOptimizationStatusWithHttpInfo(Long optId) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = getOptimizationStatusRequestBuilder(optId); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("getOptimizationStatus", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder getOptimizationStatusRequestBuilder(Long optId) throws ApiException { + // verify the required parameter 'optId' is set + if (optId == null) { + throw new ApiException(400, "Missing the required parameter 'optId' when calling getOptimizationStatus"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/api/v1/optimization/{optId}" + .replace("{optId}", ApiClient.urlEncode(optId.toString())); + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * List optimization jobs for the authenticated user + * + * @return List<OptimizationJobStatus> + * @throws ApiException if fails to make API call + */ + public List listOptimizationJobs() throws ApiException { + ApiResponse> localVarResponse = listOptimizationJobsWithHttpInfo(); + return localVarResponse.getData(); + } + + /** + * List optimization jobs for the authenticated user + * + * @return ApiResponse<List<OptimizationJobStatus>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> listOptimizationJobsWithHttpInfo() throws ApiException { + HttpRequest.Builder localVarRequestBuilder = listOptimizationJobsRequestBuilder(); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("listOptimizationJobs", localVarResponse); + } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder listOptimizationJobsRequestBuilder() throws ApiException { + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/api/v1/optimization"; + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * Stop a running optimization job + * + * @param optId (required) + * @return OptimizationJobStatus + * @throws ApiException if fails to make API call + */ + public OptimizationJobStatus stopOptimization(Long optId) throws ApiException { + ApiResponse localVarResponse = stopOptimizationWithHttpInfo(optId); + return localVarResponse.getData(); + } + + /** + * Stop a running optimization job + * + * @param optId (required) + * @return ApiResponse<OptimizationJobStatus> + * @throws ApiException if fails to make API call + */ + public ApiResponse stopOptimizationWithHttpInfo(Long optId) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = stopOptimizationRequestBuilder(optId); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("stopOptimization", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder stopOptimizationRequestBuilder(Long optId) throws ApiException { + // verify the required parameter 'optId' is set + if (optId == null) { + throw new ApiException(400, "Missing the required parameter 'optId' when calling stopOptimization"); + } + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/api/v1/optimization/{optId}/stop" + .replace("{optId}", ApiClient.urlEncode(optId.toString())); + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Accept", "application/json"); + + localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * Submit a new parameter estimation optimization job + * + * @param optProblem (optional) + * @return OptimizationJobStatus + * @throws ApiException if fails to make API call + */ + public OptimizationJobStatus submitOptimization(OptProblem optProblem) throws ApiException { + ApiResponse localVarResponse = submitOptimizationWithHttpInfo(optProblem); + return localVarResponse.getData(); + } + + /** + * Submit a new parameter estimation optimization job + * + * @param optProblem (optional) + * @return ApiResponse<OptimizationJobStatus> + * @throws ApiException if fails to make API call + */ + public ApiResponse submitOptimizationWithHttpInfo(OptProblem optProblem) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = submitOptimizationRequestBuilder(optProblem); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("submitOptimization", localVarResponse); + } + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder submitOptimizationRequestBuilder(OptProblem optProblem) throws ApiException { + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/api/v1/optimization"; + + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + + localVarRequestBuilder.header("Content-Type", "application/json"); + localVarRequestBuilder.header("Accept", "application/json"); + + try { + byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(optProblem); + localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); + } catch (IOException e) { + throw new ApiException(e); + } + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } +} diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationMethod.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationMethod.java new file mode 100644 index 0000000000..fa04816add --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationMethod.java @@ -0,0 +1,203 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.vcell.restclient.model.CopasiOptimizationMethodOptimizationMethodType; +import org.vcell.restclient.model.CopasiOptimizationParameter; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * CopasiOptimizationMethod + */ +@JsonPropertyOrder({ + CopasiOptimizationMethod.JSON_PROPERTY_OPTIMIZATION_METHOD_TYPE, + CopasiOptimizationMethod.JSON_PROPERTY_OPTIMIZATION_PARAMETER +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class CopasiOptimizationMethod { + public static final String JSON_PROPERTY_OPTIMIZATION_METHOD_TYPE = "optimizationMethodType"; + private CopasiOptimizationMethodOptimizationMethodType optimizationMethodType; + + public static final String JSON_PROPERTY_OPTIMIZATION_PARAMETER = "optimizationParameter"; + private List optimizationParameter; + + public CopasiOptimizationMethod() { + } + + public CopasiOptimizationMethod optimizationMethodType(CopasiOptimizationMethodOptimizationMethodType optimizationMethodType) { + this.optimizationMethodType = optimizationMethodType; + return this; + } + + /** + * Get optimizationMethodType + * @return optimizationMethodType + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OPTIMIZATION_METHOD_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public CopasiOptimizationMethodOptimizationMethodType getOptimizationMethodType() { + return optimizationMethodType; + } + + + @JsonProperty(JSON_PROPERTY_OPTIMIZATION_METHOD_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setOptimizationMethodType(CopasiOptimizationMethodOptimizationMethodType optimizationMethodType) { + this.optimizationMethodType = optimizationMethodType; + } + + + public CopasiOptimizationMethod optimizationParameter(List optimizationParameter) { + this.optimizationParameter = optimizationParameter; + return this; + } + + public CopasiOptimizationMethod addOptimizationParameterItem(CopasiOptimizationParameter optimizationParameterItem) { + if (this.optimizationParameter == null) { + this.optimizationParameter = new ArrayList<>(); + } + this.optimizationParameter.add(optimizationParameterItem); + return this; + } + + /** + * Get optimizationParameter + * @return optimizationParameter + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OPTIMIZATION_PARAMETER) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getOptimizationParameter() { + return optimizationParameter; + } + + + @JsonProperty(JSON_PROPERTY_OPTIMIZATION_PARAMETER) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setOptimizationParameter(List optimizationParameter) { + this.optimizationParameter = optimizationParameter; + } + + + /** + * Return true if this CopasiOptimizationMethod object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CopasiOptimizationMethod copasiOptimizationMethod = (CopasiOptimizationMethod) o; + return Objects.equals(this.optimizationMethodType, copasiOptimizationMethod.optimizationMethodType) && + Objects.equals(this.optimizationParameter, copasiOptimizationMethod.optimizationParameter); + } + + @Override + public int hashCode() { + return Objects.hash(optimizationMethodType, optimizationParameter); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CopasiOptimizationMethod {\n"); + sb.append(" optimizationMethodType: ").append(toIndentedString(optimizationMethodType)).append("\n"); + sb.append(" optimizationParameter: ").append(toIndentedString(optimizationParameter)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `optimizationMethodType` to the URL query string + if (getOptimizationMethodType() != null) { + joiner.add(String.format("%soptimizationMethodType%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getOptimizationMethodType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `optimizationParameter` to the URL query string + if (getOptimizationParameter() != null) { + for (int i = 0; i < getOptimizationParameter().size(); i++) { + if (getOptimizationParameter().get(i) != null) { + joiner.add(getOptimizationParameter().get(i).toUrlQueryString(String.format("%soptimizationParameter%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodType.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodType.java new file mode 100644 index 0000000000..09b8edc5cc --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodType.java @@ -0,0 +1,100 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets CopasiOptimizationMethodOptimizationMethodType + */ +public enum CopasiOptimizationMethodOptimizationMethodType { + + SRES("SRES"), + + EVOLUTIONARYPROGRAM("evolutionaryProgram"), + + GENETICALGORITHM("geneticAlgorithm"), + + GENETICALGORITHMSR("geneticAlgorithmSR"), + + HOOKEJEEVES("hookeJeeves"), + + LEVENBERGMARQUARDT("levenbergMarquardt"), + + NELDERMEAD("nelderMead"), + + PARTICLESWARM("particleSwarm"), + + PRAXIS("praxis"), + + RANDOMSEARCH("randomSearch"), + + SIMULATEDANNEALING("simulatedAnnealing"), + + STEEPESTDESCENT("steepestDescent"), + + TRUNCATEDNEWTON("truncatedNewton"); + + private String value; + + CopasiOptimizationMethodOptimizationMethodType(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static CopasiOptimizationMethodOptimizationMethodType fromValue(String value) { + for (CopasiOptimizationMethodOptimizationMethodType b : CopasiOptimizationMethodOptimizationMethodType.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameter.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameter.java new file mode 100644 index 0000000000..eba8c8c8f5 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameter.java @@ -0,0 +1,224 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.CopasiOptimizationParameterDataType; +import org.vcell.restclient.model.CopasiOptimizationParameterParamType; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * CopasiOptimizationParameter + */ +@JsonPropertyOrder({ + CopasiOptimizationParameter.JSON_PROPERTY_DATA_TYPE, + CopasiOptimizationParameter.JSON_PROPERTY_PARAM_TYPE, + CopasiOptimizationParameter.JSON_PROPERTY_VALUE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class CopasiOptimizationParameter { + public static final String JSON_PROPERTY_DATA_TYPE = "dataType"; + private CopasiOptimizationParameterDataType dataType; + + public static final String JSON_PROPERTY_PARAM_TYPE = "paramType"; + private CopasiOptimizationParameterParamType paramType; + + public static final String JSON_PROPERTY_VALUE = "value"; + private Double value; + + public CopasiOptimizationParameter() { + } + + public CopasiOptimizationParameter dataType(CopasiOptimizationParameterDataType dataType) { + this.dataType = dataType; + return this; + } + + /** + * Get dataType + * @return dataType + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_DATA_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public CopasiOptimizationParameterDataType getDataType() { + return dataType; + } + + + @JsonProperty(JSON_PROPERTY_DATA_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDataType(CopasiOptimizationParameterDataType dataType) { + this.dataType = dataType; + } + + + public CopasiOptimizationParameter paramType(CopasiOptimizationParameterParamType paramType) { + this.paramType = paramType; + return this; + } + + /** + * Get paramType + * @return paramType + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_PARAM_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public CopasiOptimizationParameterParamType getParamType() { + return paramType; + } + + + @JsonProperty(JSON_PROPERTY_PARAM_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setParamType(CopasiOptimizationParameterParamType paramType) { + this.paramType = paramType; + } + + + public CopasiOptimizationParameter value(Double value) { + this.value = value; + return this; + } + + /** + * Get value + * @return value + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getValue() { + return value; + } + + + @JsonProperty(JSON_PROPERTY_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setValue(Double value) { + this.value = value; + } + + + /** + * Return true if this CopasiOptimizationParameter object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CopasiOptimizationParameter copasiOptimizationParameter = (CopasiOptimizationParameter) o; + return Objects.equals(this.dataType, copasiOptimizationParameter.dataType) && + Objects.equals(this.paramType, copasiOptimizationParameter.paramType) && + Objects.equals(this.value, copasiOptimizationParameter.value); + } + + @Override + public int hashCode() { + return Objects.hash(dataType, paramType, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CopasiOptimizationParameter {\n"); + sb.append(" dataType: ").append(toIndentedString(dataType)).append("\n"); + sb.append(" paramType: ").append(toIndentedString(paramType)).append("\n"); + sb.append(" value: ").append(toIndentedString(value)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `dataType` to the URL query string + if (getDataType() != null) { + joiner.add(String.format("%sdataType%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getDataType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `paramType` to the URL query string + if (getParamType() != null) { + joiner.add(String.format("%sparamType%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getParamType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `value` to the URL query string + if (getValue() != null) { + joiner.add(String.format("%svalue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterDataType.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterDataType.java new file mode 100644 index 0000000000..7f385c42a1 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterDataType.java @@ -0,0 +1,78 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets CopasiOptimizationParameterDataType + */ +public enum CopasiOptimizationParameterDataType { + + DOUBLE("double"), + + INT("int"); + + private String value; + + CopasiOptimizationParameterDataType(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static CopasiOptimizationParameterDataType fromValue(String value) { + for (CopasiOptimizationParameterDataType b : CopasiOptimizationParameterDataType.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterParamType.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterParamType.java new file mode 100644 index 0000000000..c103846a52 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/CopasiOptimizationParameterParamType.java @@ -0,0 +1,102 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets CopasiOptimizationParameterParamType + */ +public enum CopasiOptimizationParameterParamType { + + COOLINGFACTOR("coolingFactor"), + + ITERATIONLIMIT("iterationLimit"), + + NUMBEROFGENERATIONS("numberOfGenerations"), + + NUMBEROFITERATIONS("numberOfIterations"), + + PF("pf"), + + POPULATIONSIZE("populationSize"), + + RANDOMNUMBERGENERATOR("randomNumberGenerator"), + + RHO("rho"), + + SCALE("scale"), + + SEED("seed"), + + STARTTEMPERATURE("startTemperature"), + + STDDEVIATION("stdDeviation"), + + SWARMSIZE("swarmSize"), + + TOLERANCE("tolerance"); + + private String value; + + CopasiOptimizationParameterParamType(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static CopasiOptimizationParameterParamType fromValue(String value) { + for (CopasiOptimizationParameterParamType b : CopasiOptimizationParameterParamType.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/OptJobStatus.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptJobStatus.java new file mode 100644 index 0000000000..dbb0777d05 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptJobStatus.java @@ -0,0 +1,86 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets OptJobStatus + */ +public enum OptJobStatus { + + SUBMITTED("SUBMITTED"), + + QUEUED("QUEUED"), + + RUNNING("RUNNING"), + + COMPLETE("COMPLETE"), + + FAILED("FAILED"), + + STOPPED("STOPPED"); + + private String value; + + OptJobStatus(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static OptJobStatus fromValue(String value) { + for (OptJobStatus b : OptJobStatus.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProblem.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProblem.java new file mode 100644 index 0000000000..4a2f9d1f83 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProblem.java @@ -0,0 +1,373 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.vcell.restclient.model.CopasiOptimizationMethod; +import org.vcell.restclient.model.ParameterDescription; +import org.vcell.restclient.model.ReferenceVariable; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * OptProblem + */ +@JsonPropertyOrder({ + OptProblem.JSON_PROPERTY_COPASI_OPTIMIZATION_METHOD, + OptProblem.JSON_PROPERTY_DATA_SET, + OptProblem.JSON_PROPERTY_MATH_MODEL_SBML_CONTENTS, + OptProblem.JSON_PROPERTY_NUMBER_OF_OPTIMIZATION_RUNS, + OptProblem.JSON_PROPERTY_PARAMETER_DESCRIPTION_LIST, + OptProblem.JSON_PROPERTY_REFERENCE_VARIABLE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OptProblem { + public static final String JSON_PROPERTY_COPASI_OPTIMIZATION_METHOD = "copasiOptimizationMethod"; + private CopasiOptimizationMethod copasiOptimizationMethod; + + public static final String JSON_PROPERTY_DATA_SET = "dataSet"; + private List> dataSet; + + public static final String JSON_PROPERTY_MATH_MODEL_SBML_CONTENTS = "mathModelSbmlContents"; + private String mathModelSbmlContents; + + public static final String JSON_PROPERTY_NUMBER_OF_OPTIMIZATION_RUNS = "numberOfOptimizationRuns"; + private Integer numberOfOptimizationRuns; + + public static final String JSON_PROPERTY_PARAMETER_DESCRIPTION_LIST = "parameterDescriptionList"; + private List parameterDescriptionList; + + public static final String JSON_PROPERTY_REFERENCE_VARIABLE = "referenceVariable"; + private List referenceVariable; + + public OptProblem() { + } + + public OptProblem copasiOptimizationMethod(CopasiOptimizationMethod copasiOptimizationMethod) { + this.copasiOptimizationMethod = copasiOptimizationMethod; + return this; + } + + /** + * Get copasiOptimizationMethod + * @return copasiOptimizationMethod + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_COPASI_OPTIMIZATION_METHOD) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public CopasiOptimizationMethod getCopasiOptimizationMethod() { + return copasiOptimizationMethod; + } + + + @JsonProperty(JSON_PROPERTY_COPASI_OPTIMIZATION_METHOD) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setCopasiOptimizationMethod(CopasiOptimizationMethod copasiOptimizationMethod) { + this.copasiOptimizationMethod = copasiOptimizationMethod; + } + + + public OptProblem dataSet(List> dataSet) { + this.dataSet = dataSet; + return this; + } + + public OptProblem addDataSetItem(List dataSetItem) { + if (this.dataSet == null) { + this.dataSet = new ArrayList<>(); + } + this.dataSet.add(dataSetItem); + return this; + } + + /** + * Get dataSet + * @return dataSet + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_DATA_SET) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List> getDataSet() { + return dataSet; + } + + + @JsonProperty(JSON_PROPERTY_DATA_SET) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setDataSet(List> dataSet) { + this.dataSet = dataSet; + } + + + public OptProblem mathModelSbmlContents(String mathModelSbmlContents) { + this.mathModelSbmlContents = mathModelSbmlContents; + return this; + } + + /** + * Get mathModelSbmlContents + * @return mathModelSbmlContents + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MATH_MODEL_SBML_CONTENTS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getMathModelSbmlContents() { + return mathModelSbmlContents; + } + + + @JsonProperty(JSON_PROPERTY_MATH_MODEL_SBML_CONTENTS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setMathModelSbmlContents(String mathModelSbmlContents) { + this.mathModelSbmlContents = mathModelSbmlContents; + } + + + public OptProblem numberOfOptimizationRuns(Integer numberOfOptimizationRuns) { + this.numberOfOptimizationRuns = numberOfOptimizationRuns; + return this; + } + + /** + * Get numberOfOptimizationRuns + * @return numberOfOptimizationRuns + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_NUMBER_OF_OPTIMIZATION_RUNS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Integer getNumberOfOptimizationRuns() { + return numberOfOptimizationRuns; + } + + + @JsonProperty(JSON_PROPERTY_NUMBER_OF_OPTIMIZATION_RUNS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setNumberOfOptimizationRuns(Integer numberOfOptimizationRuns) { + this.numberOfOptimizationRuns = numberOfOptimizationRuns; + } + + + public OptProblem parameterDescriptionList(List parameterDescriptionList) { + this.parameterDescriptionList = parameterDescriptionList; + return this; + } + + public OptProblem addParameterDescriptionListItem(ParameterDescription parameterDescriptionListItem) { + if (this.parameterDescriptionList == null) { + this.parameterDescriptionList = new ArrayList<>(); + } + this.parameterDescriptionList.add(parameterDescriptionListItem); + return this; + } + + /** + * Get parameterDescriptionList + * @return parameterDescriptionList + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_PARAMETER_DESCRIPTION_LIST) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getParameterDescriptionList() { + return parameterDescriptionList; + } + + + @JsonProperty(JSON_PROPERTY_PARAMETER_DESCRIPTION_LIST) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setParameterDescriptionList(List parameterDescriptionList) { + this.parameterDescriptionList = parameterDescriptionList; + } + + + public OptProblem referenceVariable(List referenceVariable) { + this.referenceVariable = referenceVariable; + return this; + } + + public OptProblem addReferenceVariableItem(ReferenceVariable referenceVariableItem) { + if (this.referenceVariable == null) { + this.referenceVariable = new ArrayList<>(); + } + this.referenceVariable.add(referenceVariableItem); + return this; + } + + /** + * Get referenceVariable + * @return referenceVariable + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_REFERENCE_VARIABLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getReferenceVariable() { + return referenceVariable; + } + + + @JsonProperty(JSON_PROPERTY_REFERENCE_VARIABLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setReferenceVariable(List referenceVariable) { + this.referenceVariable = referenceVariable; + } + + + /** + * Return true if this OptProblem object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OptProblem optProblem = (OptProblem) o; + return Objects.equals(this.copasiOptimizationMethod, optProblem.copasiOptimizationMethod) && + Objects.equals(this.dataSet, optProblem.dataSet) && + Objects.equals(this.mathModelSbmlContents, optProblem.mathModelSbmlContents) && + Objects.equals(this.numberOfOptimizationRuns, optProblem.numberOfOptimizationRuns) && + Objects.equals(this.parameterDescriptionList, optProblem.parameterDescriptionList) && + Objects.equals(this.referenceVariable, optProblem.referenceVariable); + } + + @Override + public int hashCode() { + return Objects.hash(copasiOptimizationMethod, dataSet, mathModelSbmlContents, numberOfOptimizationRuns, parameterDescriptionList, referenceVariable); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OptProblem {\n"); + sb.append(" copasiOptimizationMethod: ").append(toIndentedString(copasiOptimizationMethod)).append("\n"); + sb.append(" dataSet: ").append(toIndentedString(dataSet)).append("\n"); + sb.append(" mathModelSbmlContents: ").append(toIndentedString(mathModelSbmlContents)).append("\n"); + sb.append(" numberOfOptimizationRuns: ").append(toIndentedString(numberOfOptimizationRuns)).append("\n"); + sb.append(" parameterDescriptionList: ").append(toIndentedString(parameterDescriptionList)).append("\n"); + sb.append(" referenceVariable: ").append(toIndentedString(referenceVariable)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `copasiOptimizationMethod` to the URL query string + if (getCopasiOptimizationMethod() != null) { + joiner.add(getCopasiOptimizationMethod().toUrlQueryString(prefix + "copasiOptimizationMethod" + suffix)); + } + + // add `dataSet` to the URL query string + if (getDataSet() != null) { + for (int i = 0; i < getDataSet().size(); i++) { + joiner.add(String.format("%sdataSet%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf(getDataSet().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + + // add `mathModelSbmlContents` to the URL query string + if (getMathModelSbmlContents() != null) { + joiner.add(String.format("%smathModelSbmlContents%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getMathModelSbmlContents()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `numberOfOptimizationRuns` to the URL query string + if (getNumberOfOptimizationRuns() != null) { + joiner.add(String.format("%snumberOfOptimizationRuns%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getNumberOfOptimizationRuns()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `parameterDescriptionList` to the URL query string + if (getParameterDescriptionList() != null) { + for (int i = 0; i < getParameterDescriptionList().size(); i++) { + if (getParameterDescriptionList().get(i) != null) { + joiner.add(getParameterDescriptionList().get(i).toUrlQueryString(String.format("%sparameterDescriptionList%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + // add `referenceVariable` to the URL query string + if (getReferenceVariable() != null) { + for (int i = 0; i < getReferenceVariable().size(); i++) { + if (getReferenceVariable().get(i) != null) { + joiner.add(getReferenceVariable().get(i).toUrlQueryString(String.format("%sreferenceVariable%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProgressItem.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProgressItem.java new file mode 100644 index 0000000000..441e34e8be --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProgressItem.java @@ -0,0 +1,186 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * OptProgressItem + */ +@JsonPropertyOrder({ + OptProgressItem.JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS, + OptProgressItem.JSON_PROPERTY_OBJ_FUNC_VALUE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OptProgressItem { + public static final String JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS = "numFunctionEvaluations"; + private Integer numFunctionEvaluations; + + public static final String JSON_PROPERTY_OBJ_FUNC_VALUE = "objFuncValue"; + private Double objFuncValue; + + public OptProgressItem() { + } + + public OptProgressItem numFunctionEvaluations(Integer numFunctionEvaluations) { + this.numFunctionEvaluations = numFunctionEvaluations; + return this; + } + + /** + * Get numFunctionEvaluations + * @return numFunctionEvaluations + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Integer getNumFunctionEvaluations() { + return numFunctionEvaluations; + } + + + @JsonProperty(JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setNumFunctionEvaluations(Integer numFunctionEvaluations) { + this.numFunctionEvaluations = numFunctionEvaluations; + } + + + public OptProgressItem objFuncValue(Double objFuncValue) { + this.objFuncValue = objFuncValue; + return this; + } + + /** + * Get objFuncValue + * @return objFuncValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OBJ_FUNC_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getObjFuncValue() { + return objFuncValue; + } + + + @JsonProperty(JSON_PROPERTY_OBJ_FUNC_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setObjFuncValue(Double objFuncValue) { + this.objFuncValue = objFuncValue; + } + + + /** + * Return true if this OptProgressItem object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OptProgressItem optProgressItem = (OptProgressItem) o; + return Objects.equals(this.numFunctionEvaluations, optProgressItem.numFunctionEvaluations) && + Objects.equals(this.objFuncValue, optProgressItem.objFuncValue); + } + + @Override + public int hashCode() { + return Objects.hash(numFunctionEvaluations, objFuncValue); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OptProgressItem {\n"); + sb.append(" numFunctionEvaluations: ").append(toIndentedString(numFunctionEvaluations)).append("\n"); + sb.append(" objFuncValue: ").append(toIndentedString(objFuncValue)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `numFunctionEvaluations` to the URL query string + if (getNumFunctionEvaluations() != null) { + joiner.add(String.format("%snumFunctionEvaluations%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getNumFunctionEvaluations()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `objFuncValue` to the URL query string + if (getObjFuncValue() != null) { + joiner.add(String.format("%sobjFuncValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getObjFuncValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProgressReport.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProgressReport.java new file mode 100644 index 0000000000..9911a97fd5 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptProgressReport.java @@ -0,0 +1,216 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.vcell.restclient.model.OptProgressItem; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * OptProgressReport + */ +@JsonPropertyOrder({ + OptProgressReport.JSON_PROPERTY_BEST_PARAM_VALUES, + OptProgressReport.JSON_PROPERTY_PROGRESS_ITEMS +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OptProgressReport { + public static final String JSON_PROPERTY_BEST_PARAM_VALUES = "bestParamValues"; + private Map bestParamValues = new HashMap<>(); + + public static final String JSON_PROPERTY_PROGRESS_ITEMS = "progressItems"; + private List progressItems; + + public OptProgressReport() { + } + + public OptProgressReport bestParamValues(Map bestParamValues) { + this.bestParamValues = bestParamValues; + return this; + } + + public OptProgressReport putBestParamValuesItem(String key, Double bestParamValuesItem) { + if (this.bestParamValues == null) { + this.bestParamValues = new HashMap<>(); + } + this.bestParamValues.put(key, bestParamValuesItem); + return this; + } + + /** + * Get bestParamValues + * @return bestParamValues + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_BEST_PARAM_VALUES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Map getBestParamValues() { + return bestParamValues; + } + + + @JsonProperty(JSON_PROPERTY_BEST_PARAM_VALUES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setBestParamValues(Map bestParamValues) { + this.bestParamValues = bestParamValues; + } + + + public OptProgressReport progressItems(List progressItems) { + this.progressItems = progressItems; + return this; + } + + public OptProgressReport addProgressItemsItem(OptProgressItem progressItemsItem) { + if (this.progressItems == null) { + this.progressItems = new ArrayList<>(); + } + this.progressItems.add(progressItemsItem); + return this; + } + + /** + * Get progressItems + * @return progressItems + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_PROGRESS_ITEMS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getProgressItems() { + return progressItems; + } + + + @JsonProperty(JSON_PROPERTY_PROGRESS_ITEMS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setProgressItems(List progressItems) { + this.progressItems = progressItems; + } + + + /** + * Return true if this OptProgressReport object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OptProgressReport optProgressReport = (OptProgressReport) o; + return Objects.equals(this.bestParamValues, optProgressReport.bestParamValues) && + Objects.equals(this.progressItems, optProgressReport.progressItems); + } + + @Override + public int hashCode() { + return Objects.hash(bestParamValues, progressItems); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OptProgressReport {\n"); + sb.append(" bestParamValues: ").append(toIndentedString(bestParamValues)).append("\n"); + sb.append(" progressItems: ").append(toIndentedString(progressItems)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `bestParamValues` to the URL query string + if (getBestParamValues() != null) { + for (String _key : getBestParamValues().keySet()) { + joiner.add(String.format("%sbestParamValues%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix), + getBestParamValues().get(_key), URLEncoder.encode(String.valueOf(getBestParamValues().get(_key)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + + // add `progressItems` to the URL query string + if (getProgressItems() != null) { + for (int i = 0; i < getProgressItems().size(); i++) { + if (getProgressItems().get(i) != null) { + joiner.add(getProgressItems().get(i).toUrlQueryString(String.format("%sprogressItems%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/OptResultSet.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptResultSet.java new file mode 100644 index 0000000000..6f94a7d649 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptResultSet.java @@ -0,0 +1,273 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import org.vcell.restclient.model.OptProgressReport; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * OptResultSet + */ +@JsonPropertyOrder({ + OptResultSet.JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS, + OptResultSet.JSON_PROPERTY_OBJECTIVE_FUNCTION, + OptResultSet.JSON_PROPERTY_OPT_PARAMETER_VALUES, + OptResultSet.JSON_PROPERTY_OPT_PROGRESS_REPORT +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OptResultSet { + public static final String JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS = "numFunctionEvaluations"; + private Integer numFunctionEvaluations; + + public static final String JSON_PROPERTY_OBJECTIVE_FUNCTION = "objectiveFunction"; + private Double objectiveFunction; + + public static final String JSON_PROPERTY_OPT_PARAMETER_VALUES = "optParameterValues"; + private Map optParameterValues = new HashMap<>(); + + public static final String JSON_PROPERTY_OPT_PROGRESS_REPORT = "optProgressReport"; + private OptProgressReport optProgressReport; + + public OptResultSet() { + } + + public OptResultSet numFunctionEvaluations(Integer numFunctionEvaluations) { + this.numFunctionEvaluations = numFunctionEvaluations; + return this; + } + + /** + * Get numFunctionEvaluations + * @return numFunctionEvaluations + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Integer getNumFunctionEvaluations() { + return numFunctionEvaluations; + } + + + @JsonProperty(JSON_PROPERTY_NUM_FUNCTION_EVALUATIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setNumFunctionEvaluations(Integer numFunctionEvaluations) { + this.numFunctionEvaluations = numFunctionEvaluations; + } + + + public OptResultSet objectiveFunction(Double objectiveFunction) { + this.objectiveFunction = objectiveFunction; + return this; + } + + /** + * Get objectiveFunction + * @return objectiveFunction + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OBJECTIVE_FUNCTION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getObjectiveFunction() { + return objectiveFunction; + } + + + @JsonProperty(JSON_PROPERTY_OBJECTIVE_FUNCTION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setObjectiveFunction(Double objectiveFunction) { + this.objectiveFunction = objectiveFunction; + } + + + public OptResultSet optParameterValues(Map optParameterValues) { + this.optParameterValues = optParameterValues; + return this; + } + + public OptResultSet putOptParameterValuesItem(String key, Double optParameterValuesItem) { + if (this.optParameterValues == null) { + this.optParameterValues = new HashMap<>(); + } + this.optParameterValues.put(key, optParameterValuesItem); + return this; + } + + /** + * Get optParameterValues + * @return optParameterValues + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OPT_PARAMETER_VALUES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Map getOptParameterValues() { + return optParameterValues; + } + + + @JsonProperty(JSON_PROPERTY_OPT_PARAMETER_VALUES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setOptParameterValues(Map optParameterValues) { + this.optParameterValues = optParameterValues; + } + + + public OptResultSet optProgressReport(OptProgressReport optProgressReport) { + this.optProgressReport = optProgressReport; + return this; + } + + /** + * Get optProgressReport + * @return optProgressReport + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OPT_PROGRESS_REPORT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public OptProgressReport getOptProgressReport() { + return optProgressReport; + } + + + @JsonProperty(JSON_PROPERTY_OPT_PROGRESS_REPORT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setOptProgressReport(OptProgressReport optProgressReport) { + this.optProgressReport = optProgressReport; + } + + + /** + * Return true if this OptResultSet object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OptResultSet optResultSet = (OptResultSet) o; + return Objects.equals(this.numFunctionEvaluations, optResultSet.numFunctionEvaluations) && + Objects.equals(this.objectiveFunction, optResultSet.objectiveFunction) && + Objects.equals(this.optParameterValues, optResultSet.optParameterValues) && + Objects.equals(this.optProgressReport, optResultSet.optProgressReport); + } + + @Override + public int hashCode() { + return Objects.hash(numFunctionEvaluations, objectiveFunction, optParameterValues, optProgressReport); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OptResultSet {\n"); + sb.append(" numFunctionEvaluations: ").append(toIndentedString(numFunctionEvaluations)).append("\n"); + sb.append(" objectiveFunction: ").append(toIndentedString(objectiveFunction)).append("\n"); + sb.append(" optParameterValues: ").append(toIndentedString(optParameterValues)).append("\n"); + sb.append(" optProgressReport: ").append(toIndentedString(optProgressReport)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `numFunctionEvaluations` to the URL query string + if (getNumFunctionEvaluations() != null) { + joiner.add(String.format("%snumFunctionEvaluations%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getNumFunctionEvaluations()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `objectiveFunction` to the URL query string + if (getObjectiveFunction() != null) { + joiner.add(String.format("%sobjectiveFunction%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getObjectiveFunction()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `optParameterValues` to the URL query string + if (getOptParameterValues() != null) { + for (String _key : getOptParameterValues().keySet()) { + joiner.add(String.format("%soptParameterValues%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix), + getOptParameterValues().get(_key), URLEncoder.encode(String.valueOf(getOptParameterValues().get(_key)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + + // add `optProgressReport` to the URL query string + if (getOptProgressReport() != null) { + joiner.add(getOptProgressReport().toUrlQueryString(prefix + "optProgressReport" + suffix)); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/OptimizationJobStatus.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptimizationJobStatus.java new file mode 100644 index 0000000000..18755748bc --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/OptimizationJobStatus.java @@ -0,0 +1,333 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.OptJobStatus; +import org.vcell.restclient.model.OptProgressReport; +import org.vcell.restclient.model.Vcellopt; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * OptimizationJobStatus + */ +@JsonPropertyOrder({ + OptimizationJobStatus.JSON_PROPERTY_ID, + OptimizationJobStatus.JSON_PROPERTY_STATUS, + OptimizationJobStatus.JSON_PROPERTY_STATUS_MESSAGE, + OptimizationJobStatus.JSON_PROPERTY_HTC_JOB_ID, + OptimizationJobStatus.JSON_PROPERTY_PROGRESS_REPORT, + OptimizationJobStatus.JSON_PROPERTY_RESULTS +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OptimizationJobStatus { + public static final String JSON_PROPERTY_ID = "id"; + private String id; + + public static final String JSON_PROPERTY_STATUS = "status"; + private OptJobStatus status; + + public static final String JSON_PROPERTY_STATUS_MESSAGE = "statusMessage"; + private String statusMessage; + + public static final String JSON_PROPERTY_HTC_JOB_ID = "htcJobId"; + private String htcJobId; + + public static final String JSON_PROPERTY_PROGRESS_REPORT = "progressReport"; + private OptProgressReport progressReport; + + public static final String JSON_PROPERTY_RESULTS = "results"; + private Vcellopt results; + + public OptimizationJobStatus() { + } + + public OptimizationJobStatus id(String id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ID) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getId() { + return id; + } + + + @JsonProperty(JSON_PROPERTY_ID) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setId(String id) { + this.id = id; + } + + + public OptimizationJobStatus status(OptJobStatus status) { + this.status = status; + return this; + } + + /** + * Get status + * @return status + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public OptJobStatus getStatus() { + return status; + } + + + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(OptJobStatus status) { + this.status = status; + } + + + public OptimizationJobStatus statusMessage(String statusMessage) { + this.statusMessage = statusMessage; + return this; + } + + /** + * Get statusMessage + * @return statusMessage + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_STATUS_MESSAGE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getStatusMessage() { + return statusMessage; + } + + + @JsonProperty(JSON_PROPERTY_STATUS_MESSAGE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } + + + public OptimizationJobStatus htcJobId(String htcJobId) { + this.htcJobId = htcJobId; + return this; + } + + /** + * Get htcJobId + * @return htcJobId + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_HTC_JOB_ID) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getHtcJobId() { + return htcJobId; + } + + + @JsonProperty(JSON_PROPERTY_HTC_JOB_ID) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setHtcJobId(String htcJobId) { + this.htcJobId = htcJobId; + } + + + public OptimizationJobStatus progressReport(OptProgressReport progressReport) { + this.progressReport = progressReport; + return this; + } + + /** + * Get progressReport + * @return progressReport + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_PROGRESS_REPORT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public OptProgressReport getProgressReport() { + return progressReport; + } + + + @JsonProperty(JSON_PROPERTY_PROGRESS_REPORT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setProgressReport(OptProgressReport progressReport) { + this.progressReport = progressReport; + } + + + public OptimizationJobStatus results(Vcellopt results) { + this.results = results; + return this; + } + + /** + * Get results + * @return results + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_RESULTS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Vcellopt getResults() { + return results; + } + + + @JsonProperty(JSON_PROPERTY_RESULTS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setResults(Vcellopt results) { + this.results = results; + } + + + /** + * Return true if this OptimizationJobStatus object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OptimizationJobStatus optimizationJobStatus = (OptimizationJobStatus) o; + return Objects.equals(this.id, optimizationJobStatus.id) && + Objects.equals(this.status, optimizationJobStatus.status) && + Objects.equals(this.statusMessage, optimizationJobStatus.statusMessage) && + Objects.equals(this.htcJobId, optimizationJobStatus.htcJobId) && + Objects.equals(this.progressReport, optimizationJobStatus.progressReport) && + Objects.equals(this.results, optimizationJobStatus.results); + } + + @Override + public int hashCode() { + return Objects.hash(id, status, statusMessage, htcJobId, progressReport, results); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OptimizationJobStatus {\n"); + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" statusMessage: ").append(toIndentedString(statusMessage)).append("\n"); + sb.append(" htcJobId: ").append(toIndentedString(htcJobId)).append("\n"); + sb.append(" progressReport: ").append(toIndentedString(progressReport)).append("\n"); + sb.append(" results: ").append(toIndentedString(results)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `id` to the URL query string + if (getId() != null) { + joiner.add(String.format("%sid%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getId()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `statusMessage` to the URL query string + if (getStatusMessage() != null) { + joiner.add(String.format("%sstatusMessage%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatusMessage()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `htcJobId` to the URL query string + if (getHtcJobId() != null) { + joiner.add(String.format("%shtcJobId%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getHtcJobId()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `progressReport` to the URL query string + if (getProgressReport() != null) { + joiner.add(getProgressReport().toUrlQueryString(prefix + "progressReport" + suffix)); + } + + // add `results` to the URL query string + if (getResults() != null) { + joiner.add(getResults().toUrlQueryString(prefix + "results" + suffix)); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/ParameterDescription.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/ParameterDescription.java new file mode 100644 index 0000000000..bd4862d263 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/ParameterDescription.java @@ -0,0 +1,294 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * ParameterDescription + */ +@JsonPropertyOrder({ + ParameterDescription.JSON_PROPERTY_INITIAL_VALUE, + ParameterDescription.JSON_PROPERTY_MAX_VALUE, + ParameterDescription.JSON_PROPERTY_MIN_VALUE, + ParameterDescription.JSON_PROPERTY_NAME, + ParameterDescription.JSON_PROPERTY_SCALE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class ParameterDescription { + public static final String JSON_PROPERTY_INITIAL_VALUE = "initialValue"; + private Double initialValue; + + public static final String JSON_PROPERTY_MAX_VALUE = "maxValue"; + private Double maxValue; + + public static final String JSON_PROPERTY_MIN_VALUE = "minValue"; + private Double minValue; + + public static final String JSON_PROPERTY_NAME = "name"; + private String name; + + public static final String JSON_PROPERTY_SCALE = "scale"; + private Double scale; + + public ParameterDescription() { + } + + public ParameterDescription initialValue(Double initialValue) { + this.initialValue = initialValue; + return this; + } + + /** + * Get initialValue + * @return initialValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_INITIAL_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getInitialValue() { + return initialValue; + } + + + @JsonProperty(JSON_PROPERTY_INITIAL_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setInitialValue(Double initialValue) { + this.initialValue = initialValue; + } + + + public ParameterDescription maxValue(Double maxValue) { + this.maxValue = maxValue; + return this; + } + + /** + * Get maxValue + * @return maxValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MAX_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getMaxValue() { + return maxValue; + } + + + @JsonProperty(JSON_PROPERTY_MAX_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setMaxValue(Double maxValue) { + this.maxValue = maxValue; + } + + + public ParameterDescription minValue(Double minValue) { + this.minValue = minValue; + return this; + } + + /** + * Get minValue + * @return minValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MIN_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getMinValue() { + return minValue; + } + + + @JsonProperty(JSON_PROPERTY_MIN_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setMinValue(Double minValue) { + this.minValue = minValue; + } + + + public ParameterDescription name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getName() { + return name; + } + + + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setName(String name) { + this.name = name; + } + + + public ParameterDescription scale(Double scale) { + this.scale = scale; + return this; + } + + /** + * Get scale + * @return scale + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_SCALE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getScale() { + return scale; + } + + + @JsonProperty(JSON_PROPERTY_SCALE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setScale(Double scale) { + this.scale = scale; + } + + + /** + * Return true if this ParameterDescription object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ParameterDescription parameterDescription = (ParameterDescription) o; + return Objects.equals(this.initialValue, parameterDescription.initialValue) && + Objects.equals(this.maxValue, parameterDescription.maxValue) && + Objects.equals(this.minValue, parameterDescription.minValue) && + Objects.equals(this.name, parameterDescription.name) && + Objects.equals(this.scale, parameterDescription.scale); + } + + @Override + public int hashCode() { + return Objects.hash(initialValue, maxValue, minValue, name, scale); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ParameterDescription {\n"); + sb.append(" initialValue: ").append(toIndentedString(initialValue)).append("\n"); + sb.append(" maxValue: ").append(toIndentedString(maxValue)).append("\n"); + sb.append(" minValue: ").append(toIndentedString(minValue)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" scale: ").append(toIndentedString(scale)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `initialValue` to the URL query string + if (getInitialValue() != null) { + joiner.add(String.format("%sinitialValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getInitialValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `maxValue` to the URL query string + if (getMaxValue() != null) { + joiner.add(String.format("%smaxValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getMaxValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `minValue` to the URL query string + if (getMinValue() != null) { + joiner.add(String.format("%sminValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getMinValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `name` to the URL query string + if (getName() != null) { + joiner.add(String.format("%sname%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getName()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `scale` to the URL query string + if (getScale() != null) { + joiner.add(String.format("%sscale%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getScale()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/ReferenceVariable.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/ReferenceVariable.java new file mode 100644 index 0000000000..f3ad45601b --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/ReferenceVariable.java @@ -0,0 +1,187 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.ReferenceVariableReferenceVariableType; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * ReferenceVariable + */ +@JsonPropertyOrder({ + ReferenceVariable.JSON_PROPERTY_REFERENCE_VARIABLE_TYPE, + ReferenceVariable.JSON_PROPERTY_VAR_NAME +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class ReferenceVariable { + public static final String JSON_PROPERTY_REFERENCE_VARIABLE_TYPE = "referenceVariableType"; + private ReferenceVariableReferenceVariableType referenceVariableType; + + public static final String JSON_PROPERTY_VAR_NAME = "varName"; + private String varName; + + public ReferenceVariable() { + } + + public ReferenceVariable referenceVariableType(ReferenceVariableReferenceVariableType referenceVariableType) { + this.referenceVariableType = referenceVariableType; + return this; + } + + /** + * Get referenceVariableType + * @return referenceVariableType + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_REFERENCE_VARIABLE_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public ReferenceVariableReferenceVariableType getReferenceVariableType() { + return referenceVariableType; + } + + + @JsonProperty(JSON_PROPERTY_REFERENCE_VARIABLE_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setReferenceVariableType(ReferenceVariableReferenceVariableType referenceVariableType) { + this.referenceVariableType = referenceVariableType; + } + + + public ReferenceVariable varName(String varName) { + this.varName = varName; + return this; + } + + /** + * Get varName + * @return varName + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_VAR_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getVarName() { + return varName; + } + + + @JsonProperty(JSON_PROPERTY_VAR_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setVarName(String varName) { + this.varName = varName; + } + + + /** + * Return true if this ReferenceVariable object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ReferenceVariable referenceVariable = (ReferenceVariable) o; + return Objects.equals(this.referenceVariableType, referenceVariable.referenceVariableType) && + Objects.equals(this.varName, referenceVariable.varName); + } + + @Override + public int hashCode() { + return Objects.hash(referenceVariableType, varName); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ReferenceVariable {\n"); + sb.append(" referenceVariableType: ").append(toIndentedString(referenceVariableType)).append("\n"); + sb.append(" varName: ").append(toIndentedString(varName)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `referenceVariableType` to the URL query string + if (getReferenceVariableType() != null) { + joiner.add(String.format("%sreferenceVariableType%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getReferenceVariableType()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `varName` to the URL query string + if (getVarName() != null) { + joiner.add(String.format("%svarName%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getVarName()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableType.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableType.java new file mode 100644 index 0000000000..a8ffb678c8 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableType.java @@ -0,0 +1,78 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets ReferenceVariableReferenceVariableType + */ +public enum ReferenceVariableReferenceVariableType { + + DEPENDENT("dependent"), + + INDEPENDENT("independent"); + + private String value; + + ReferenceVariableReferenceVariableType(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static ReferenceVariableReferenceVariableType fromValue(String value) { + for (ReferenceVariableReferenceVariableType b : ReferenceVariableReferenceVariableType.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/Vcellopt.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/Vcellopt.java new file mode 100644 index 0000000000..6cacdff16b --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/Vcellopt.java @@ -0,0 +1,261 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.OptProblem; +import org.vcell.restclient.model.OptResultSet; +import org.vcell.restclient.model.VcelloptStatus; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * Vcellopt + */ +@JsonPropertyOrder({ + Vcellopt.JSON_PROPERTY_OPT_PROBLEM, + Vcellopt.JSON_PROPERTY_OPT_RESULT_SET, + Vcellopt.JSON_PROPERTY_STATUS, + Vcellopt.JSON_PROPERTY_STATUS_MESSAGE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class Vcellopt { + public static final String JSON_PROPERTY_OPT_PROBLEM = "optProblem"; + private OptProblem optProblem; + + public static final String JSON_PROPERTY_OPT_RESULT_SET = "optResultSet"; + private OptResultSet optResultSet; + + public static final String JSON_PROPERTY_STATUS = "status"; + private VcelloptStatus status; + + public static final String JSON_PROPERTY_STATUS_MESSAGE = "statusMessage"; + private String statusMessage; + + public Vcellopt() { + } + + public Vcellopt optProblem(OptProblem optProblem) { + this.optProblem = optProblem; + return this; + } + + /** + * Get optProblem + * @return optProblem + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OPT_PROBLEM) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public OptProblem getOptProblem() { + return optProblem; + } + + + @JsonProperty(JSON_PROPERTY_OPT_PROBLEM) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setOptProblem(OptProblem optProblem) { + this.optProblem = optProblem; + } + + + public Vcellopt optResultSet(OptResultSet optResultSet) { + this.optResultSet = optResultSet; + return this; + } + + /** + * Get optResultSet + * @return optResultSet + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OPT_RESULT_SET) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public OptResultSet getOptResultSet() { + return optResultSet; + } + + + @JsonProperty(JSON_PROPERTY_OPT_RESULT_SET) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setOptResultSet(OptResultSet optResultSet) { + this.optResultSet = optResultSet; + } + + + public Vcellopt status(VcelloptStatus status) { + this.status = status; + return this; + } + + /** + * Get status + * @return status + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public VcelloptStatus getStatus() { + return status; + } + + + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatus(VcelloptStatus status) { + this.status = status; + } + + + public Vcellopt statusMessage(String statusMessage) { + this.statusMessage = statusMessage; + return this; + } + + /** + * Get statusMessage + * @return statusMessage + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_STATUS_MESSAGE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getStatusMessage() { + return statusMessage; + } + + + @JsonProperty(JSON_PROPERTY_STATUS_MESSAGE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } + + + /** + * Return true if this Vcellopt object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Vcellopt vcellopt = (Vcellopt) o; + return Objects.equals(this.optProblem, vcellopt.optProblem) && + Objects.equals(this.optResultSet, vcellopt.optResultSet) && + Objects.equals(this.status, vcellopt.status) && + Objects.equals(this.statusMessage, vcellopt.statusMessage); + } + + @Override + public int hashCode() { + return Objects.hash(optProblem, optResultSet, status, statusMessage); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Vcellopt {\n"); + sb.append(" optProblem: ").append(toIndentedString(optProblem)).append("\n"); + sb.append(" optResultSet: ").append(toIndentedString(optResultSet)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" statusMessage: ").append(toIndentedString(statusMessage)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `optProblem` to the URL query string + if (getOptProblem() != null) { + joiner.add(getOptProblem().toUrlQueryString(prefix + "optProblem" + suffix)); + } + + // add `optResultSet` to the URL query string + if (getOptResultSet() != null) { + joiner.add(getOptResultSet().toUrlQueryString(prefix + "optResultSet" + suffix)); + } + + // add `status` to the URL query string + if (getStatus() != null) { + joiner.add(String.format("%sstatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `statusMessage` to the URL query string + if (getStatusMessage() != null) { + joiner.add(String.format("%sstatusMessage%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStatusMessage()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/VcelloptStatus.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/VcelloptStatus.java new file mode 100644 index 0000000000..37a46b9fcf --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/VcelloptStatus.java @@ -0,0 +1,82 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets VcelloptStatus + */ +public enum VcelloptStatus { + + COMPLETE("complete"), + + FAILED("failed"), + + QUEUED("queued"), + + RUNNING("running"); + + private String value; + + VcelloptStatus(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static VcelloptStatus fromValue(String value) { + for (VcelloptStatus b : VcelloptStatus.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/api/OptimizationResourceApiTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/api/OptimizationResourceApiTest.java new file mode 100644 index 0000000000..93c694fe51 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/api/OptimizationResourceApiTest.java @@ -0,0 +1,106 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.api; + +import org.vcell.restclient.ApiException; +import org.vcell.restclient.model.OptProblem; +import org.vcell.restclient.model.OptimizationJobStatus; +import org.vcell.restclient.model.VCellHTTPError; +import org.junit.Test; +import org.junit.Ignore; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +/** + * API tests for OptimizationResourceApi + */ +@Ignore +public class OptimizationResourceApiTest { + + private final OptimizationResourceApi api = new OptimizationResourceApi(); + + + /** + * Get status, progress, or results of an optimization job + * + * + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void getOptimizationStatusTest() throws ApiException { + Long optId = null; + OptimizationJobStatus response = + api.getOptimizationStatus(optId); + + // TODO: test validations + } + + /** + * List optimization jobs for the authenticated user + * + * + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void listOptimizationJobsTest() throws ApiException { + List response = + api.listOptimizationJobs(); + + // TODO: test validations + } + + /** + * Stop a running optimization job + * + * + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void stopOptimizationTest() throws ApiException { + Long optId = null; + OptimizationJobStatus response = + api.stopOptimization(optId); + + // TODO: test validations + } + + /** + * Submit a new parameter estimation optimization job + * + * + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void submitOptimizationTest() throws ApiException { + OptProblem optProblem = null; + OptimizationJobStatus response = + api.submitOptimization(optProblem); + + // TODO: test validations + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodTypeTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodTypeTest.java new file mode 100644 index 0000000000..3acef8f6b9 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodOptimizationMethodTypeTest.java @@ -0,0 +1,32 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for CopasiOptimizationMethodOptimizationMethodType + */ +public class CopasiOptimizationMethodOptimizationMethodTypeTest { + /** + * Model tests for CopasiOptimizationMethodOptimizationMethodType + */ + @Test + public void testCopasiOptimizationMethodOptimizationMethodType() { + // TODO: test CopasiOptimizationMethodOptimizationMethodType + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodTest.java new file mode 100644 index 0000000000..e1777f5784 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationMethodTest.java @@ -0,0 +1,60 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.vcell.restclient.model.CopasiOptimizationMethodOptimizationMethodType; +import org.vcell.restclient.model.CopasiOptimizationParameter; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for CopasiOptimizationMethod + */ +public class CopasiOptimizationMethodTest { + private final CopasiOptimizationMethod model = new CopasiOptimizationMethod(); + + /** + * Model tests for CopasiOptimizationMethod + */ + @Test + public void testCopasiOptimizationMethod() { + // TODO: test CopasiOptimizationMethod + } + + /** + * Test the property 'optimizationMethodType' + */ + @Test + public void optimizationMethodTypeTest() { + // TODO: test optimizationMethodType + } + + /** + * Test the property 'optimizationParameter' + */ + @Test + public void optimizationParameterTest() { + // TODO: test optimizationParameter + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterDataTypeTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterDataTypeTest.java new file mode 100644 index 0000000000..065f4d0173 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterDataTypeTest.java @@ -0,0 +1,32 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for CopasiOptimizationParameterDataType + */ +public class CopasiOptimizationParameterDataTypeTest { + /** + * Model tests for CopasiOptimizationParameterDataType + */ + @Test + public void testCopasiOptimizationParameterDataType() { + // TODO: test CopasiOptimizationParameterDataType + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterParamTypeTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterParamTypeTest.java new file mode 100644 index 0000000000..b2d4b63f0c --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterParamTypeTest.java @@ -0,0 +1,32 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for CopasiOptimizationParameterParamType + */ +public class CopasiOptimizationParameterParamTypeTest { + /** + * Model tests for CopasiOptimizationParameterParamType + */ + @Test + public void testCopasiOptimizationParameterParamType() { + // TODO: test CopasiOptimizationParameterParamType + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterTest.java new file mode 100644 index 0000000000..9c7bf8899a --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/CopasiOptimizationParameterTest.java @@ -0,0 +1,66 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.CopasiOptimizationParameterDataType; +import org.vcell.restclient.model.CopasiOptimizationParameterParamType; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for CopasiOptimizationParameter + */ +public class CopasiOptimizationParameterTest { + private final CopasiOptimizationParameter model = new CopasiOptimizationParameter(); + + /** + * Model tests for CopasiOptimizationParameter + */ + @Test + public void testCopasiOptimizationParameter() { + // TODO: test CopasiOptimizationParameter + } + + /** + * Test the property 'dataType' + */ + @Test + public void dataTypeTest() { + // TODO: test dataType + } + + /** + * Test the property 'paramType' + */ + @Test + public void paramTypeTest() { + // TODO: test paramType + } + + /** + * Test the property 'value' + */ + @Test + public void valueTest() { + // TODO: test value + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/OptJobStatusTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptJobStatusTest.java new file mode 100644 index 0000000000..020dee4983 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptJobStatusTest.java @@ -0,0 +1,32 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for OptJobStatus + */ +public class OptJobStatusTest { + /** + * Model tests for OptJobStatus + */ + @Test + public void testOptJobStatus() { + // TODO: test OptJobStatus + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProblemTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProblemTest.java new file mode 100644 index 0000000000..ceb4fce04c --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProblemTest.java @@ -0,0 +1,93 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.vcell.restclient.model.CopasiOptimizationMethod; +import org.vcell.restclient.model.ParameterDescription; +import org.vcell.restclient.model.ReferenceVariable; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for OptProblem + */ +public class OptProblemTest { + private final OptProblem model = new OptProblem(); + + /** + * Model tests for OptProblem + */ + @Test + public void testOptProblem() { + // TODO: test OptProblem + } + + /** + * Test the property 'copasiOptimizationMethod' + */ + @Test + public void copasiOptimizationMethodTest() { + // TODO: test copasiOptimizationMethod + } + + /** + * Test the property 'dataSet' + */ + @Test + public void dataSetTest() { + // TODO: test dataSet + } + + /** + * Test the property 'mathModelSbmlContents' + */ + @Test + public void mathModelSbmlContentsTest() { + // TODO: test mathModelSbmlContents + } + + /** + * Test the property 'numberOfOptimizationRuns' + */ + @Test + public void numberOfOptimizationRunsTest() { + // TODO: test numberOfOptimizationRuns + } + + /** + * Test the property 'parameterDescriptionList' + */ + @Test + public void parameterDescriptionListTest() { + // TODO: test parameterDescriptionList + } + + /** + * Test the property 'referenceVariable' + */ + @Test + public void referenceVariableTest() { + // TODO: test referenceVariable + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProgressItemTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProgressItemTest.java new file mode 100644 index 0000000000..f78fde8987 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProgressItemTest.java @@ -0,0 +1,56 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for OptProgressItem + */ +public class OptProgressItemTest { + private final OptProgressItem model = new OptProgressItem(); + + /** + * Model tests for OptProgressItem + */ + @Test + public void testOptProgressItem() { + // TODO: test OptProgressItem + } + + /** + * Test the property 'numFunctionEvaluations' + */ + @Test + public void numFunctionEvaluationsTest() { + // TODO: test numFunctionEvaluations + } + + /** + * Test the property 'objFuncValue' + */ + @Test + public void objFuncValueTest() { + // TODO: test objFuncValue + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProgressReportTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProgressReportTest.java new file mode 100644 index 0000000000..0d517b3c06 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptProgressReportTest.java @@ -0,0 +1,61 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.vcell.restclient.model.OptProgressItem; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for OptProgressReport + */ +public class OptProgressReportTest { + private final OptProgressReport model = new OptProgressReport(); + + /** + * Model tests for OptProgressReport + */ + @Test + public void testOptProgressReport() { + // TODO: test OptProgressReport + } + + /** + * Test the property 'bestParamValues' + */ + @Test + public void bestParamValuesTest() { + // TODO: test bestParamValues + } + + /** + * Test the property 'progressItems' + */ + @Test + public void progressItemsTest() { + // TODO: test progressItems + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/OptResultSetTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptResultSetTest.java new file mode 100644 index 0000000000..0d97a196b6 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptResultSetTest.java @@ -0,0 +1,75 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import org.vcell.restclient.model.OptProgressReport; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for OptResultSet + */ +public class OptResultSetTest { + private final OptResultSet model = new OptResultSet(); + + /** + * Model tests for OptResultSet + */ + @Test + public void testOptResultSet() { + // TODO: test OptResultSet + } + + /** + * Test the property 'numFunctionEvaluations' + */ + @Test + public void numFunctionEvaluationsTest() { + // TODO: test numFunctionEvaluations + } + + /** + * Test the property 'objectiveFunction' + */ + @Test + public void objectiveFunctionTest() { + // TODO: test objectiveFunction + } + + /** + * Test the property 'optParameterValues' + */ + @Test + public void optParameterValuesTest() { + // TODO: test optParameterValues + } + + /** + * Test the property 'optProgressReport' + */ + @Test + public void optProgressReportTest() { + // TODO: test optProgressReport + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/OptimizationJobStatusTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptimizationJobStatusTest.java new file mode 100644 index 0000000000..d2224b8487 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/OptimizationJobStatusTest.java @@ -0,0 +1,91 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.OptJobStatus; +import org.vcell.restclient.model.OptProgressReport; +import org.vcell.restclient.model.Vcellopt; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for OptimizationJobStatus + */ +public class OptimizationJobStatusTest { + private final OptimizationJobStatus model = new OptimizationJobStatus(); + + /** + * Model tests for OptimizationJobStatus + */ + @Test + public void testOptimizationJobStatus() { + // TODO: test OptimizationJobStatus + } + + /** + * Test the property 'id' + */ + @Test + public void idTest() { + // TODO: test id + } + + /** + * Test the property 'status' + */ + @Test + public void statusTest() { + // TODO: test status + } + + /** + * Test the property 'statusMessage' + */ + @Test + public void statusMessageTest() { + // TODO: test statusMessage + } + + /** + * Test the property 'htcJobId' + */ + @Test + public void htcJobIdTest() { + // TODO: test htcJobId + } + + /** + * Test the property 'progressReport' + */ + @Test + public void progressReportTest() { + // TODO: test progressReport + } + + /** + * Test the property 'results' + */ + @Test + public void resultsTest() { + // TODO: test results + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/ParameterDescriptionTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/ParameterDescriptionTest.java new file mode 100644 index 0000000000..c67c49a7a8 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/ParameterDescriptionTest.java @@ -0,0 +1,80 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for ParameterDescription + */ +public class ParameterDescriptionTest { + private final ParameterDescription model = new ParameterDescription(); + + /** + * Model tests for ParameterDescription + */ + @Test + public void testParameterDescription() { + // TODO: test ParameterDescription + } + + /** + * Test the property 'initialValue' + */ + @Test + public void initialValueTest() { + // TODO: test initialValue + } + + /** + * Test the property 'maxValue' + */ + @Test + public void maxValueTest() { + // TODO: test maxValue + } + + /** + * Test the property 'minValue' + */ + @Test + public void minValueTest() { + // TODO: test minValue + } + + /** + * Test the property 'name' + */ + @Test + public void nameTest() { + // TODO: test name + } + + /** + * Test the property 'scale' + */ + @Test + public void scaleTest() { + // TODO: test scale + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableTypeTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableTypeTest.java new file mode 100644 index 0000000000..da6182ae2e --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/ReferenceVariableReferenceVariableTypeTest.java @@ -0,0 +1,32 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for ReferenceVariableReferenceVariableType + */ +public class ReferenceVariableReferenceVariableTypeTest { + /** + * Model tests for ReferenceVariableReferenceVariableType + */ + @Test + public void testReferenceVariableReferenceVariableType() { + // TODO: test ReferenceVariableReferenceVariableType + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/ReferenceVariableTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/ReferenceVariableTest.java new file mode 100644 index 0000000000..b3f31436db --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/ReferenceVariableTest.java @@ -0,0 +1,57 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.ReferenceVariableReferenceVariableType; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for ReferenceVariable + */ +public class ReferenceVariableTest { + private final ReferenceVariable model = new ReferenceVariable(); + + /** + * Model tests for ReferenceVariable + */ + @Test + public void testReferenceVariable() { + // TODO: test ReferenceVariable + } + + /** + * Test the property 'referenceVariableType' + */ + @Test + public void referenceVariableTypeTest() { + // TODO: test referenceVariableType + } + + /** + * Test the property 'varName' + */ + @Test + public void varNameTest() { + // TODO: test varName + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/VcelloptStatusTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/VcelloptStatusTest.java new file mode 100644 index 0000000000..ff3b030c6e --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/VcelloptStatusTest.java @@ -0,0 +1,32 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for VcelloptStatus + */ +public class VcelloptStatusTest { + /** + * Model tests for VcelloptStatus + */ + @Test + public void testVcelloptStatus() { + // TODO: test VcelloptStatus + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/VcelloptTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/VcelloptTest.java new file mode 100644 index 0000000000..9bc8cff235 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/VcelloptTest.java @@ -0,0 +1,75 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.vcell.restclient.model.OptProblem; +import org.vcell.restclient.model.OptResultSet; +import org.vcell.restclient.model.VcelloptStatus; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for Vcellopt + */ +public class VcelloptTest { + private final Vcellopt model = new Vcellopt(); + + /** + * Model tests for Vcellopt + */ + @Test + public void testVcellopt() { + // TODO: test Vcellopt + } + + /** + * Test the property 'optProblem' + */ + @Test + public void optProblemTest() { + // TODO: test optProblem + } + + /** + * Test the property 'optResultSet' + */ + @Test + public void optResultSetTest() { + // TODO: test optResultSet + } + + /** + * Test the property 'status' + */ + @Test + public void statusTest() { + // TODO: test status + } + + /** + * Test the property 'statusMessage' + */ + @Test + public void statusMessageTest() { + // TODO: test statusMessage + } + +} diff --git a/vcell-server/src/main/java/cbit/vcell/message/server/batch/opt/OptimizationBatchServer.java b/vcell-server/src/main/java/cbit/vcell/message/server/batch/opt/OptimizationBatchServer.java index 3ad7f923f8..ac12fb0704 100644 --- a/vcell-server/src/main/java/cbit/vcell/message/server/batch/opt/OptimizationBatchServer.java +++ b/vcell-server/src/main/java/cbit/vcell/message/server/batch/opt/OptimizationBatchServer.java @@ -1,329 +1,180 @@ package cbit.vcell.message.server.batch.opt; -import cbit.vcell.message.server.htc.HtcJobStatus; import cbit.vcell.message.server.htc.HtcProxy; import cbit.vcell.resource.PropertyLoader; import cbit.vcell.server.HtcJobID; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.vcell.optimization.CopasiUtils; -import org.vcell.optimization.OptMessage; +import org.vcell.optimization.OptJobStatus; +import org.vcell.optimization.OptRequestMessage; +import org.vcell.optimization.OptStatusMessage; import org.vcell.optimization.jtd.OptProblem; -import org.vcell.optimization.jtd.OptProgressReport; import org.vcell.optimization.jtd.Vcellopt; import org.vcell.util.exe.ExecutableException; +import javax.jms.*; +import org.apache.activemq.ActiveMQConnectionFactory; + import java.io.*; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.Arrays; -import java.util.Random; public class OptimizationBatchServer { private final static Logger lg = LogManager.getLogger(OptimizationBatchServer.class); - private Random random = new Random(System.currentTimeMillis()); - private ServerSocket optimizationServersocket; private HtcProxy.HtcProxyFactory htcProxyFactory = null; - private static class OptServerJobInfo { - private String optID; - private HtcProxy.HtcJobInfo htcJobInfo; - - public OptServerJobInfo(String optID, HtcProxy.HtcJobInfo htcJobInfo) { - super(); - this.optID = optID; - this.htcJobInfo = htcJobInfo; - } - - public String getOptID() { - return optID; - } + public OptimizationBatchServer(HtcProxy.HtcProxyFactory htcProxyFactory){ + this.htcProxyFactory = htcProxyFactory; + } - public HtcProxy.HtcJobInfo getHtcJobInfo() { - return htcJobInfo; - } + private HtcProxy getHtcProxy() { + return htcProxyFactory.getHtcProxy(); } - public class OptCommunicationThread extends Thread { - private final Socket optSocket; + /** + * Initialize a JMS queue listener on "opt-request" for cross-protocol messaging with vcell-rest (AMQP 1.0). + * Receives submit/stop commands as JSON text messages, dispatches to SLURM, and sends status updates + * back on "opt-status". + */ + public void initOptimizationQueue(String jmsHost, int jmsPort) { + Thread optQueueThread = new Thread(() -> { + ObjectMapper objectMapper = new ObjectMapper(); + try { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( + "tcp://" + jmsHost + ":" + jmsPort); + connectionFactory.setTrustAllPackages(true); + Connection connection = connectionFactory.createConnection(); + connection.start(); - public OptCommunicationThread(Socket optSocket){ - super(); - setName("optCommunicationThread"); - this.optSocket = optSocket; - } + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination requestQueue = session.createQueue("opt-request"); + Destination statusQueue = session.createQueue("opt-status"); + MessageConsumer consumer = session.createConsumer(requestQueue); + MessageProducer producer = session.createProducer(statusQueue); + + lg.info("Optimization JMS queue listener started on opt-request"); - @Override - public void run() { - OptServerJobInfo optServerJobInfo = null; - // let the client socket close the connection - keep listening as long as the client is active - try (ObjectInputStream is = new ObjectInputStream(optSocket.getInputStream()); - ObjectOutputStream oos = new ObjectOutputStream(optSocket.getOutputStream()); - Socket myOptSocket = optSocket) { while (true) { - OptMessage.OptCommandMessage optCommandMessage = null; - try { - optCommandMessage = (OptMessage.OptCommandMessage) is.readObject(); - if (optServerJobInfo != null && !optCommandMessage.optID.equals(optServerJobInfo.getOptID())) { - String errMsg = "command optID=" + optCommandMessage.optID + " doesn't match socket optID=" + optServerJobInfo.optID; - oos.writeObject(new OptMessage.OptErrorResponseMessage(optCommandMessage, errMsg)); - oos.flush(); - lg.error(errMsg); - } else if (optCommandMessage instanceof OptMessage.OptJobStopCommandMessage) { - OptMessage.OptJobStopCommandMessage stopRequest = (OptMessage.OptJobStopCommandMessage) optCommandMessage; - optServerStopJob(optServerJobInfo); - oos.writeObject(new OptMessage.OptJobStopResponseMessage(stopRequest)); - oos.flush(); - lg.info("send stop request to batch system for job optID=" + optCommandMessage.optID); - } else if (optCommandMessage instanceof OptMessage.OptJobQueryCommandMessage) { - OptMessage.OptJobQueryCommandMessage jobQuery = (OptMessage.OptJobQueryCommandMessage) optCommandMessage; - Vcellopt optRun = getOptResults(optServerJobInfo.getOptID()); - if (optRun != null) { - // job is done, return results - ObjectMapper objectMapper = new ObjectMapper(); - String optRunJsonString = objectMapper.writeValueAsString(optRun); - oos.writeObject(new OptMessage.OptJobSolutionResponseMessage(jobQuery, optRunJsonString)); - oos.flush(); - lg.info("returned solution for job optID=" + optCommandMessage.optID); - } - // else ask the batch system for the status - HtcJobStatus htcJobStatus = optServerGetJobStatus(optServerJobInfo.getHtcJobInfo()); - if (htcJobStatus == null) {//pending - oos.writeObject(new OptMessage.OptJobStatusResponseMessage(jobQuery, OptMessage.OptJobMessageStatus.QUEUED, "queued", null)); - oos.flush(); - lg.info("returned status of " + OptMessage.OptJobMessageStatus.QUEUED + " for job optID=" + optCommandMessage.optID); + Message message = consumer.receive(2000); // 2 second poll + if (message == null) continue; + + if (message instanceof TextMessage textMessage) { + try { + String json = textMessage.getText(); + OptRequestMessage request = objectMapper.readValue(json, OptRequestMessage.class); + lg.info("Received optimization request: command={}, jobId={}", request.command, request.jobId); + + if ("submit".equals(request.command)) { + handleSubmitRequest(request, session, producer, objectMapper); + } else if ("stop".equals(request.command)) { + handleStopRequest(request); } else { - if (htcJobStatus.isFailed()) { - String errorMsg = "slurm job " + optServerJobInfo.getHtcJobInfo().getHtcJobID() + " failed"; - oos.writeObject(new OptMessage.OptJobStatusResponseMessage( - jobQuery, OptMessage.OptJobMessageStatus.FAILED, errorMsg,null)); - oos.flush(); - lg.error(errorMsg); - throw new Exception(errorMsg); - } else if (htcJobStatus.isComplete()) { // but file not found yet - String optID = optCommandMessage.optID; - String errMsg = "job optID=" + optID + " status is COMPLETE but result file "+generateOptOutputFilePath(optID)+" not found yet"; - String progressReportJsonString = getProgressReportJsonString(optID); - oos.writeObject(new OptMessage.OptJobStatusResponseMessage( - jobQuery, OptMessage.OptJobMessageStatus.RUNNING, errMsg, progressReportJsonString)); - oos.flush(); - lg.error(errMsg); - } else {//running - String optID = optCommandMessage.optID; - String msg = "slurm job " + optServerJobInfo.getHtcJobInfo().getHtcJobID() + " running"; - String progressReportJsonString = getProgressReportJsonString(optID); - if (progressReportJsonString == null) { - lg.warn("failed to read progress report for optID="+optID); - } - oos.writeObject(new OptMessage.OptJobStatusResponseMessage( - jobQuery, OptMessage.OptJobMessageStatus.RUNNING, msg, progressReportJsonString)); - oos.flush(); - lg.info(msg); - } + lg.warn("Unknown optimization command: {}", request.command); } - } else if (optCommandMessage instanceof OptMessage.OptJobRunCommandMessage) { - OptMessage.OptJobRunCommandMessage runCommand = (OptMessage.OptJobRunCommandMessage) optCommandMessage; - lg.info("submitting optimization job"); - ObjectMapper objectMapper = new ObjectMapper(); - OptProblem optProblem = objectMapper.readValue(runCommand.optProblemJsonString, OptProblem.class); - optServerJobInfo = submitOptProblem(optProblem); - String optID = optServerJobInfo.getOptID(); - oos.writeObject(new OptMessage.OptJobRunResponseMessage(optID, runCommand)); - oos.flush(); - } else { - throw new Exception("Unexpected command " + optCommandMessage); - } - } catch (SocketException | EOFException e) { - String optID = (optServerJobInfo!=null) ? optServerJobInfo.optID : "null"; - String errMsg = "Socket exception - shutting down thread for optID=" + optID + ": " + e.getMessage(); - lg.error(errMsg, e); - return; - } catch (Exception e) { - String optID = (optServerJobInfo!=null) ? optServerJobInfo.optID : "null"; - String errMsg = "error processing command for optID=" + optID + ": " + e.getMessage(); - lg.error(errMsg, e); - try { - oos.writeObject(new OptMessage.OptErrorResponseMessage(optCommandMessage, errMsg)); - oos.flush(); - } catch (Exception e2) { - lg.error(e2.getMessage(), e2); + } catch (Exception e) { + lg.error("Error processing optimization request: {}", e.getMessage(), e); } } } } catch (Exception e) { - lg.error(e.getMessage(), e); - } finally { - //cleanup - try { - if (optServerJobInfo != null && optServerJobInfo.getOptID() != null) { - File optDir = generateOptimizeDirName(optServerJobInfo.getOptID()); - if (optDir.exists()) { -// generateOptProblemFilePath(optServerJobInfo.getOptID()).delete(); -// generateOptOutputFilePath(optServerJobInfo.getOptID()).delete(); -// generateOptInterresultsFilePath(optServerJobInfo.getOptID()).delete(); - optDir.delete(); - } - } - }catch (Exception e2){ - lg.error(e2.getMessage(), e2); - } + lg.error("Optimization JMS queue listener failed: {}", e.getMessage(), e); } + }, "optQueueListener"); + optQueueThread.setDaemon(true); + optQueueThread.start(); + } + + /** + * Validate that a file path is under the expected parest_data directory to prevent path traversal. + */ + private static File validateParestPath(String filePath) throws IOException { + File file = new File(filePath).getCanonicalFile(); + java.nio.file.Path parestDir = new File(PropertyLoader.getRequiredProperty( + PropertyLoader.primarySimDataDirInternalProperty), "parest_data").getCanonicalFile().toPath(); + if (!file.toPath().startsWith(parestDir)) { + throw new IOException("Invalid optimization file path (outside parest_data): " + filePath); } + return file; } - private String getProgressReportJsonString(String optID) throws IOException { - String progressReportJsonString = null; - OptProgressReport progressReport = getProgressReport(optID); - lg.info(CopasiUtils.progressReportString(progressReport)); - if (progressReport != null){ - ObjectMapper objectMapper = new ObjectMapper(); - progressReportJsonString = objectMapper.writeValueAsString(progressReport); - } - return progressReportJsonString; - } + private void handleSubmitRequest(OptRequestMessage request, Session session, + MessageProducer producer, ObjectMapper objectMapper) { + try { + // Validate jobId is numeric (database key) to prevent injection in file names + Long.parseLong(request.jobId); - public OptimizationBatchServer(HtcProxy.HtcProxyFactory htcProxyFactory){ - this.htcProxyFactory = htcProxyFactory; - } + // Validate paths are under parest_data directory + File optProblemFile = validateParestPath(request.optProblemFilePath); + File optOutputFile = validateParestPath(request.optOutputFilePath); + File optReportFile = validateParestPath(request.optReportFilePath); - private HtcProxy getHtcProxy() { - return htcProxyFactory.getHtcProxy(); - } + // The OptProblem file is already written by vcell-rest — read it + OptProblem optProblem = objectMapper.readValue(optProblemFile, OptProblem.class); - public void initOptimizationSocket() { - Thread optThread = new Thread(new Runnable() { - @Override - public void run() { - try { - optimizationServersocket = new ServerSocket(8877); - while (true) { - Socket optSocket = optimizationServersocket.accept(); - OptCommunicationThread optCommunicationThread = new OptCommunicationThread(optSocket); - optCommunicationThread.setDaemon(true); - optCommunicationThread.start(); - } - } catch (Exception e) { - lg.error(e.getMessage(), e); - } + HtcProxy htcProxyClone = getHtcProxy().cloneThreadsafe(); + File htcLogDirExternal = new File(PropertyLoader.getRequiredProperty(PropertyLoader.htcLogDirExternal)); + File htcLogDirInternal = new File(PropertyLoader.getRequiredProperty(PropertyLoader.htcLogDirInternal)); + String slurmOptJobName = "CopasiParest_" + request.jobId; + String optSubFileName = slurmOptJobName + ".sub"; + File sub_file_external = new File(htcLogDirExternal, optSubFileName); + File sub_file_internal = new File(htcLogDirInternal, optSubFileName); + + HtcJobID htcJobID = htcProxyClone.submitOptimizationJob( + slurmOptJobName, sub_file_internal, sub_file_external, + optProblemFile, optOutputFile, optReportFile); + + lg.info("Submitted SLURM job {} for optimization jobId={}", htcJobID, request.jobId); + + // Send QUEUED status back with htcJobId + sendStatusMessage(session, producer, objectMapper, + request.jobId, OptJobStatus.QUEUED, null, htcJobID.toDatabase()); + } catch (Exception e) { + lg.error("Failed to submit optimization job {}: {}", request.jobId, e.getMessage(), e); + try { + sendStatusMessage(session, producer, objectMapper, + request.jobId, OptJobStatus.FAILED, e.getMessage(), null); + } catch (JMSException jmsEx) { + lg.error("Failed to send FAILED status for job {}: {}", request.jobId, jmsEx.getMessage(), jmsEx); } - }); - optThread.setDaemon(true); - optThread.start(); - } - - private Vcellopt getOptResults(String optID) throws IOException { - File f = generateOptOutputFilePath(optID); - if (f.exists()) {// opt job done - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(f,Vcellopt.class); } - return null; } - private OptProgressReport getProgressReport(String optID) throws IOException { - File f = generateOptReportFilePath(optID); - if (f.exists()) { // opt has report (may still be open for reading) - return CopasiUtils.readProgressReportFromCSV(f); - }else { - return null; + private void handleStopRequest(OptRequestMessage request) { + if (request.htcJobId == null) { + lg.warn("Cannot stop optimization job {} — no htcJobId", request.jobId); + return; } - } - - private OptServerJobInfo submitOptProblem(OptProblem optProblem) throws IOException, ExecutableException { - HtcProxy htcProxyClone = getHtcProxy().cloneThreadsafe(); - File htcLogDirExternal = new File(PropertyLoader.getRequiredProperty(PropertyLoader.htcLogDirExternal)); - File htcLogDirInternal = new File(PropertyLoader.getRequiredProperty(PropertyLoader.htcLogDirInternal)); - int optID = random.nextInt(1000000); - String optSubFileName = generateOptFilePrefix(optID+"")+".sub"; - File sub_file_external = new File(htcLogDirExternal, optSubFileName); - File sub_file_internal = new File(htcLogDirInternal, optSubFileName); - File optProblemFile = generateOptProblemFilePath(optID+""); - File optOutputFile = generateOptOutputFilePath(optID+""); - File optReportFile = generateOptReportFilePath(optID+""); - CopasiUtils.writeOptProblem(optProblemFile, optProblem);//save param optimization problem to user dir - //make sure all can read and write - File optDir = generateOptimizeDirName(optID+""); - optDir.setReadable(true,false); - optDir.setWritable(true,false); - - String slurmOptJobName = generateOptFilePrefix(optID+""); - HtcJobID htcJobID = htcProxyClone.submitOptimizationJob(slurmOptJobName, sub_file_internal, sub_file_external,optProblemFile,optOutputFile,optReportFile); - return new OptServerJobInfo(optID+"", new HtcProxy.HtcJobInfo(htcJobID, slurmOptJobName)); - } - private void optServerStopJob(OptServerJobInfo optServerJobInfo) { try { HtcProxy htcProxyClone = getHtcProxy().cloneThreadsafe(); - htcProxyClone.killJobSafe(optServerJobInfo.getHtcJobInfo()); -// CommandOutput commandOutput = htcProxyClone.getCommandService().command(new String[] {"scancel",optServerJobInfo.htcJobID.getJobNumber()+""}); -// return commandOutput.getExitStatus()==0; + // htcJobId is in toDatabase() format: "SLURM:12345" or "SLURM:12345.server" + String htcJobIdStr = request.htcJobId; + HtcJobID htcJobID; + if (htcJobIdStr.startsWith("SLURM:")) { + htcJobID = new HtcJobID(htcJobIdStr.substring("SLURM:".length()), HtcJobID.BatchSystemType.SLURM); + } else { + htcJobID = new HtcJobID(htcJobIdStr, HtcJobID.BatchSystemType.SLURM); + } + String jobName = "CopasiParest_" + request.jobId; + htcProxyClone.killJobSafe(new HtcProxy.HtcJobInfo(htcJobID, jobName)); + lg.info("Stopped SLURM job {} for optimization jobId={}", request.htcJobId, request.jobId); } catch (Exception e) { - lg.error(e.getMessage(), e); + lg.error("Failed to stop optimization job {}: {}", request.jobId, e.getMessage(), e); } } - private HtcJobStatus optServerGetJobStatus(HtcProxy.HtcJobInfo htcJobInfo) { - HtcProxy htcProxyClone = getHtcProxy().cloneThreadsafe(); + + private void sendStatusMessage(Session session, MessageProducer producer, ObjectMapper objectMapper, + String jobId, OptJobStatus status, String statusMessage, String htcJobId) + throws JMSException { try { - return htcProxyClone.getJobStatus(Arrays.asList(new HtcProxy.HtcJobInfo[] {htcJobInfo})).get(htcJobInfo); + OptStatusMessage statusMsg = new OptStatusMessage(jobId, status, statusMessage, htcJobId); + String json = objectMapper.writeValueAsString(statusMsg); + TextMessage textMessage = session.createTextMessage(json); + producer.send(textMessage); + lg.info("Sent optimization status: jobId={}, status={}", jobId, status); } catch (Exception e) { - lg.error(e.getMessage(), e); - return null; + lg.error("Failed to send status message for job {}: {}", jobId, e.getMessage(), e); + throw new JMSException("Failed to serialize status message: " + e.getMessage()); } } -// private static boolean hackFileExists(File watchThisFile) { -// try { -// //Force container bind mount to update file status -// ProcessBuilder pb = new ProcessBuilder("sh","-c","ls "+watchThisFile.getAbsolutePath()+"*"); -// pb.redirectErrorStream(true); -// Process p = pb.start(); -// BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); -//// StringBuffer sb = new StringBuffer(); -// String line = null; -// while((line = br.readLine()) != null) { -// //sb.append(line+"\n"); -// System.out.println("'"+line+"'"); -// if(line.trim().startsWith("ls: ")) { -//// System.out.println("false"); -// break; -// }else if(line.trim().equals(watchThisFile.getAbsolutePath())) { -//// System.out.println("true"); -// return true; -// } -// } -// p.waitFor(10, TimeUnit.SECONDS); -// br.close(); -//// System.out.println("false"); -// } catch (Exception e) { -// lg.error(e.getMessage(), e); -// } -// return false; -// } - - private File generateOptimizeDirName(String optID) { - File primaryUserDirInternal = new File(PropertyLoader.getRequiredProperty(PropertyLoader.primarySimDataDirInternalProperty)); - File optProblemDir = new File(primaryUserDirInternal,"parest_data"); - optProblemDir.mkdir(); - return optProblemDir; - } - private File generateOptOutputFilePath(String optID) { - String optOutputFileName = generateOptFilePrefix(optID)+"_optRun.json"; - return new File(generateOptimizeDirName(optID), optOutputFileName); - } - private File generateOptReportFilePath(String optID) { - String optOutputFileName = generateOptFilePrefix(optID)+"_optReport.txt"; - return new File(generateOptimizeDirName(optID), optOutputFileName); - } - private File generateOptProblemFilePath(String optID) { - String optOutputFileName = generateOptFilePrefix(optID)+"_optProblem.json"; - return new File(generateOptimizeDirName(optID), optOutputFileName); - } -// private File generateOptInterresultsFilePath(String optID) { -// return new File(generateOptimizeDirName(optID), "interresults.txt"); -// } - private String generateOptFilePrefix(String optID) { - return "CopasiParest_"+optID; - } } \ No newline at end of file diff --git a/vcell-server/src/main/java/cbit/vcell/message/server/batch/sim/HtcSimulationWorker.java b/vcell-server/src/main/java/cbit/vcell/message/server/batch/sim/HtcSimulationWorker.java index 44503e2ca4..dd39930b15 100644 --- a/vcell-server/src/main/java/cbit/vcell/message/server/batch/sim/HtcSimulationWorker.java +++ b/vcell-server/src/main/java/cbit/vcell/message/server/batch/sim/HtcSimulationWorker.java @@ -110,7 +110,11 @@ public final String getJobSelector() { public void init() { initQueueConsumer(); - optimizationBatchServer.initOptimizationSocket(); + + // Start JMS queue listener for optimization requests from vcell-rest (via Artemis broker) + String artemisHost = PropertyLoader.getRequiredProperty(PropertyLoader.jmsArtemisHostInternal); + int artemisPort = Integer.parseInt(PropertyLoader.getRequiredProperty(PropertyLoader.jmsArtemisPortInternal)); + optimizationBatchServer.initOptimizationQueue(artemisHost, artemisPort); } private static class PostProcessingChores { diff --git a/vcell-server/src/main/java/cbit/vcell/message/server/htc/slurm/SlurmProxy.java b/vcell-server/src/main/java/cbit/vcell/message/server/htc/slurm/SlurmProxy.java index a102dc8bc4..b4bea68fa2 100644 --- a/vcell-server/src/main/java/cbit/vcell/message/server/htc/slurm/SlurmProxy.java +++ b/vcell-server/src/main/java/cbit/vcell/message/server/htc/slurm/SlurmProxy.java @@ -1084,13 +1084,20 @@ HtcJobID submitJobFile(File sub_file_external) throws ExecutableException { public HtcJobID submitOptimizationJob(String jobName, File sub_file_internal, File sub_file_external, File optProblemInputFile,File optProblemOutputFile,File optReportFile) throws ExecutableException{ try { + // Validate sub_file_internal is under the configured htcLogDir to prevent path traversal + String htcLogDirInternal = PropertyLoader.getRequiredProperty(PropertyLoader.htcLogDirInternal); + java.nio.file.Path subFilePath = sub_file_internal.getCanonicalFile().toPath(); + java.nio.file.Path htcLogDirPath = new File(htcLogDirInternal).getCanonicalFile().toPath(); + if (!subFilePath.startsWith(htcLogDirPath)) { + throw new ExecutableException("sub_file_internal path outside htcLogDir: " + sub_file_internal); + } String scriptText = createOptJobScript(jobName, optProblemInputFile, optProblemOutputFile, optReportFile); LG.info("sub_file_internal: " + sub_file_internal.getAbsolutePath() + ", sub_file_external: " + sub_file_external.getAbsolutePath() + ", optProblemInput: " + optProblemInputFile.getAbsolutePath() + ", optProblemOutput: " + optProblemOutputFile.getAbsolutePath() + ", optReport: " + optReportFile.getAbsolutePath()); - Files.writeString(sub_file_internal.toPath(), scriptText); + Files.writeString(sub_file_internal.getCanonicalFile().toPath(), scriptText); } catch (IOException ex) { LG.error(ex); return null; @@ -1119,11 +1126,10 @@ String createOptJobScript(String jobName, File optProblemInputFile, File optProb LineStringBuilder lsb = new LineStringBuilder(); slurmScriptInit(jobName, false, memoryMBAllowed, lsb); + // vcell-rest creates the parest_data directory before writing the input file. + // Compute the external path for the SLURM script bindings (host-visible NFS mount point). File optDataDir = optProblemInputFile.getParentFile(); File optDataDirExternal = new File(optDataDir.getAbsolutePath().replace(primaryDataDirInternal, primaryDataDirExternal)); - if (!optDataDirExternal.exists() && !optDataDirExternal.mkdir()){ - LG.error("failed to make optimization data directory "+optDataDir.getAbsolutePath()); - } List bindings = List.of( new SingularityBinding(optDataDirExternal.getAbsolutePath(), "/simdata"), diff --git a/vcell-server/src/main/java/cbit/vcell/modeldb/OptJobTable.java b/vcell-server/src/main/java/cbit/vcell/modeldb/OptJobTable.java new file mode 100644 index 0000000000..9ca7911942 --- /dev/null +++ b/vcell-server/src/main/java/cbit/vcell/modeldb/OptJobTable.java @@ -0,0 +1,93 @@ +package cbit.vcell.modeldb; + +import cbit.sql.Field; +import cbit.sql.Field.SQLDataType; +import cbit.sql.Table; +import org.vcell.optimization.OptJobRecord; +import org.vcell.optimization.OptJobStatus; +import org.vcell.util.TokenMangler; +import org.vcell.util.document.KeyValue; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * Table definition for vc_optjob — optimization job tracking. + * This is an operational table (not versioned). Access control is enforced + * at the REST layer by checking ownerRef. + */ +public class OptJobTable extends Table { + private static final String TABLE_NAME = "vc_optjob"; + public static final String REF_TYPE = "REFERENCES " + TABLE_NAME + "(" + Table.id_ColumnName + ")"; + + public final Field ownerRef = new Field("ownerRef", SQLDataType.integer, "NOT NULL " + UserTable.REF_TYPE); + public final Field status = new Field("status", SQLDataType.varchar2_32, "NOT NULL"); + public final Field optProblemFile = new Field("optProblemFile", SQLDataType.varchar2_512, "NOT NULL"); + public final Field optOutputFile = new Field("optOutputFile", SQLDataType.varchar2_512, "NOT NULL"); + public final Field optReportFile = new Field("optReportFile", SQLDataType.varchar2_512, "NOT NULL"); + public final Field htcJobId = new Field("htcJobId", SQLDataType.varchar2_128, ""); + public final Field statusMessage = new Field("statusMessage", SQLDataType.varchar2_4000, ""); + public final Field insertDate = new Field("insertDate", SQLDataType.date, "NOT NULL"); + public final Field updateDate = new Field("updateDate", SQLDataType.date, "NOT NULL"); + + private final Field[] fields = { + ownerRef, status, optProblemFile, optOutputFile, optReportFile, + htcJobId, statusMessage, insertDate, updateDate + }; + + public static final OptJobTable table = new OptJobTable(); + + private OptJobTable() { + super(TABLE_NAME); + addFields(fields); + } + + public String getSQLValueList(KeyValue key, KeyValue ownerKey, OptJobStatus jobStatus, + String problemFile, String outputFile, String reportFile, + String htcJob, String message) { + return "(" + + key + "," + + ownerKey + "," + + "'" + jobStatus.name() + "'," + + "'" + TokenMangler.getSQLEscapedString(problemFile) + "'," + + "'" + TokenMangler.getSQLEscapedString(outputFile) + "'," + + "'" + TokenMangler.getSQLEscapedString(reportFile) + "'," + + (htcJob != null ? "'" + TokenMangler.getSQLEscapedString(htcJob) + "'" : "null") + "," + + (message != null ? "'" + TokenMangler.getSQLEscapedString(message, 4000) + "'" : "null") + "," + + "current_timestamp," + + "current_timestamp" + + ")"; + } + + public String getSQLUpdateList(OptJobStatus jobStatus, String message) { + return status + "='" + jobStatus.name() + "'," + + statusMessage + "=" + (message != null ? "'" + TokenMangler.getSQLEscapedString(message, 4000) + "'" : "null") + "," + + updateDate + "=current_timestamp"; + } + + public String getSQLUpdateListHtcJobId(String htcJob, OptJobStatus jobStatus) { + return htcJobId + "=" + (htcJob != null ? "'" + TokenMangler.getSQLEscapedString(htcJob) + "'" : "null") + "," + + status + "='" + jobStatus.name() + "'," + + updateDate + "=current_timestamp"; + } + + public OptJobRecord getOptJobRecord(ResultSet rset) throws SQLException { + KeyValue key = new KeyValue(rset.getBigDecimal(id.toString())); + KeyValue owner = new KeyValue(rset.getBigDecimal(ownerRef.toString())); + OptJobStatus jobStatus = OptJobStatus.valueOf(rset.getString(status.toString())); + String problemFile = rset.getString(optProblemFile.toString()); + String outputFile = rset.getString(optOutputFile.toString()); + String reportFile = rset.getString(optReportFile.toString()); + String htcJob = rset.getString(htcJobId.toString()); + String rawMessage = rset.getString(statusMessage.toString()); + String message = rawMessage != null ? TokenMangler.getSQLRestoredString(rawMessage) : null; + java.sql.Timestamp insertTs = rset.getTimestamp(insertDate.toString()); + java.sql.Timestamp updateTs = rset.getTimestamp(updateDate.toString()); + + return new OptJobRecord( + key, owner, jobStatus, problemFile, outputFile, reportFile, + htcJob, message, + insertTs.toInstant(), updateTs.toInstant() + ); + } +} diff --git a/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java b/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java index 58eb9648ee..5892fab91f 100644 --- a/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java +++ b/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java @@ -376,6 +376,7 @@ public static Table[] getVCellTables() { cbit.vcell.modeldb.VCMetaDataTable.table, // new cbit.vcell.modeldb.SimDelFromDiskTable.table, // new UserIdentityTable.table, + OptJobTable.table, }; return tables; } diff --git a/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES b/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES index 3f284d27af..e6f4a26d5a 100644 --- a/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES +++ b/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES @@ -16,6 +16,8 @@ api/hello-world.service.ts api/hello-world.serviceInterface.ts api/math-model-resource.service.ts api/math-model-resource.serviceInterface.ts +api/optimization-resource.service.ts +api/optimization-resource.serviceInterface.ts api/publication-resource.service.ts api/publication-resource.serviceInterface.ts api/simulation-resource.service.ts @@ -42,6 +44,11 @@ model/biomodel-ref.ts model/composite-curve.ts model/control-point-curve.ts model/coordinate.ts +model/copasi-optimization-method-optimization-method-type.ts +model/copasi-optimization-method.ts +model/copasi-optimization-parameter-data-type.ts +model/copasi-optimization-parameter-param-type.ts +model/copasi-optimization-parameter.ts model/curve-selection-info.ts model/curve.ts model/data-identifier.ts @@ -77,10 +84,19 @@ model/mathmodel-ref.ts model/model-type.ts model/models.ts model/n5-export-request.ts +model/opt-job-status.ts +model/opt-problem.ts +model/opt-progress-item.ts +model/opt-progress-report.ts +model/opt-result-set.ts +model/optimization-job-status.ts model/origin.ts +model/parameter-description.ts model/publication-info.ts model/publication.ts model/publish-models-request.ts +model/reference-variable-reference-variable-type.ts +model/reference-variable.ts model/sampled-curve.ts model/scheduler-status.ts model/simulation-execution-status-record.ts @@ -115,6 +131,8 @@ model/variable-type.ts model/vc-document-type.ts model/vc-image-summary.ts model/vc-simulation-identifier.ts +model/vcellopt-status.ts +model/vcellopt.ts model/version-flag.ts model/version.ts param.ts diff --git a/webapp-ng/src/app/core/modules/openapi/api/api.ts b/webapp-ng/src/app/core/modules/openapi/api/api.ts index 633957d44d..a822c5f79b 100644 --- a/webapp-ng/src/app/core/modules/openapi/api/api.ts +++ b/webapp-ng/src/app/core/modules/openapi/api/api.ts @@ -19,6 +19,9 @@ export * from './hello-world.serviceInterface'; export * from './math-model-resource.service'; import { MathModelResourceService } from './math-model-resource.service'; export * from './math-model-resource.serviceInterface'; +export * from './optimization-resource.service'; +import { OptimizationResourceService } from './optimization-resource.service'; +export * from './optimization-resource.serviceInterface'; export * from './publication-resource.service'; import { PublicationResourceService } from './publication-resource.service'; export * from './publication-resource.serviceInterface'; @@ -34,4 +37,4 @@ export * from './users-resource.serviceInterface'; export * from './vc-image-resource.service'; import { VCImageResourceService } from './vc-image-resource.service'; export * from './vc-image-resource.serviceInterface'; -export const APIS = [AdminResourceService, BioModelResourceService, ExportResourceService, FieldDataResourceService, GeometryResourceService, HelloWorldService, MathModelResourceService, PublicationResourceService, SimulationResourceService, SolverResourceService, UsersResourceService, VCImageResourceService]; +export const APIS = [AdminResourceService, BioModelResourceService, ExportResourceService, FieldDataResourceService, GeometryResourceService, HelloWorldService, MathModelResourceService, OptimizationResourceService, PublicationResourceService, SimulationResourceService, SolverResourceService, UsersResourceService, VCImageResourceService]; diff --git a/webapp-ng/src/app/core/modules/openapi/api/optimization-resource.service.ts b/webapp-ng/src/app/core/modules/openapi/api/optimization-resource.service.ts new file mode 100644 index 0000000000..3f76a3400b --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/api/optimization-resource.service.ts @@ -0,0 +1,360 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +/* tslint:disable:no-unused-variable member-ordering */ + +import { Inject, Injectable, Optional } from '@angular/core'; +import { HttpClient, HttpHeaders, HttpParams, + HttpResponse, HttpEvent, HttpParameterCodec, HttpContext + } from '@angular/common/http'; +import { CustomHttpParameterCodec } from '../encoder'; +import { Observable } from 'rxjs'; + +// @ts-ignore +import { OptProblem } from '../model/opt-problem'; +// @ts-ignore +import { OptimizationJobStatus } from '../model/optimization-job-status'; +// @ts-ignore +import { VCellHTTPError } from '../model/v-cell-http-error'; + +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS } from '../variables'; +import { Configuration } from '../configuration'; +import { + OptimizationResourceServiceInterface +} from './optimization-resource.serviceInterface'; + + + +@Injectable({ + providedIn: 'root' +}) +export class OptimizationResourceService implements OptimizationResourceServiceInterface { + + protected basePath = 'https://vcell.cam.uchc.edu'; + public defaultHeaders = new HttpHeaders(); + public configuration = new Configuration(); + public encoder: HttpParameterCodec; + + constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string|string[], @Optional() configuration: Configuration) { + if (configuration) { + this.configuration = configuration; + } + if (typeof this.configuration.basePath !== 'string') { + if (Array.isArray(basePath) && basePath.length > 0) { + basePath = basePath[0]; + } + + if (typeof basePath !== 'string') { + basePath = this.basePath; + } + this.configuration.basePath = basePath; + } + this.encoder = this.configuration.encoder || new CustomHttpParameterCodec(); + } + + + // @ts-ignore + private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams { + if (typeof value === "object" && value instanceof Date === false) { + httpParams = this.addToHttpParamsRecursive(httpParams, value); + } else { + httpParams = this.addToHttpParamsRecursive(httpParams, value, key); + } + return httpParams; + } + + private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams { + if (value == null) { + return httpParams; + } + + if (typeof value === "object") { + if (Array.isArray(value)) { + (value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key)); + } else if (value instanceof Date) { + if (key != null) { + httpParams = httpParams.append(key, (value as Date).toISOString().substring(0, 10)); + } else { + throw Error("key may not be null if value is Date"); + } + } else { + Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive( + httpParams, value[k], key != null ? `${key}.${k}` : k)); + } + } else if (key != null) { + httpParams = httpParams.append(key, value); + } else { + throw Error("key may not be null if value is not object or array"); + } + return httpParams; + } + + /** + * Get status, progress, or results of an optimization job + * @param optId + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public getOptimizationStatus(optId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable; + public getOptimizationStatus(optId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public getOptimizationStatus(optId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public getOptimizationStatus(optId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { + if (optId === null || optId === undefined) { + throw new Error('Required parameter optId was null or undefined when calling getOptimizationStatus.'); + } + + let localVarHeaders = this.defaultHeaders; + + let localVarCredential: string | undefined; + // authentication (openId) required + localVarCredential = this.configuration.lookupCredential('openId'); + if (localVarCredential) { + } + + let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept; + if (localVarHttpHeaderAcceptSelected === undefined) { + // to determine the Accept header + const httpHeaderAccepts: string[] = [ + 'application/json' + ]; + localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts); + } + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + let localVarHttpContext: HttpContext | undefined = options && options.context; + if (localVarHttpContext === undefined) { + localVarHttpContext = new HttpContext(); + } + + + let responseType_: 'text' | 'json' | 'blob' = 'json'; + if (localVarHttpHeaderAcceptSelected) { + if (localVarHttpHeaderAcceptSelected.startsWith('text')) { + responseType_ = 'text'; + } else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) { + responseType_ = 'json'; + } else { + responseType_ = 'blob'; + } + } + + let localVarPath = `/api/v1/optimization/${this.configuration.encodeParam({name: "optId", value: optId, in: "path", style: "simple", explode: false, dataType: "number", dataFormat: "int64"})}`; + return this.httpClient.request('get', `${this.configuration.basePath}${localVarPath}`, + { + context: localVarHttpContext, + responseType: responseType_, + withCredentials: this.configuration.withCredentials, + headers: localVarHeaders, + observe: observe, + reportProgress: reportProgress + } + ); + } + + /** + * List optimization jobs for the authenticated user + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public listOptimizationJobs(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public listOptimizationJobs(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; + public listOptimizationJobs(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; + public listOptimizationJobs(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { + + let localVarHeaders = this.defaultHeaders; + + let localVarCredential: string | undefined; + // authentication (openId) required + localVarCredential = this.configuration.lookupCredential('openId'); + if (localVarCredential) { + } + + let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept; + if (localVarHttpHeaderAcceptSelected === undefined) { + // to determine the Accept header + const httpHeaderAccepts: string[] = [ + 'application/json' + ]; + localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts); + } + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + let localVarHttpContext: HttpContext | undefined = options && options.context; + if (localVarHttpContext === undefined) { + localVarHttpContext = new HttpContext(); + } + + + let responseType_: 'text' | 'json' | 'blob' = 'json'; + if (localVarHttpHeaderAcceptSelected) { + if (localVarHttpHeaderAcceptSelected.startsWith('text')) { + responseType_ = 'text'; + } else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) { + responseType_ = 'json'; + } else { + responseType_ = 'blob'; + } + } + + let localVarPath = `/api/v1/optimization`; + return this.httpClient.request>('get', `${this.configuration.basePath}${localVarPath}`, + { + context: localVarHttpContext, + responseType: responseType_, + withCredentials: this.configuration.withCredentials, + headers: localVarHeaders, + observe: observe, + reportProgress: reportProgress + } + ); + } + + /** + * Stop a running optimization job + * @param optId + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public stopOptimization(optId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable; + public stopOptimization(optId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public stopOptimization(optId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public stopOptimization(optId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { + if (optId === null || optId === undefined) { + throw new Error('Required parameter optId was null or undefined when calling stopOptimization.'); + } + + let localVarHeaders = this.defaultHeaders; + + let localVarCredential: string | undefined; + // authentication (openId) required + localVarCredential = this.configuration.lookupCredential('openId'); + if (localVarCredential) { + } + + let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept; + if (localVarHttpHeaderAcceptSelected === undefined) { + // to determine the Accept header + const httpHeaderAccepts: string[] = [ + 'application/json' + ]; + localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts); + } + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + let localVarHttpContext: HttpContext | undefined = options && options.context; + if (localVarHttpContext === undefined) { + localVarHttpContext = new HttpContext(); + } + + + let responseType_: 'text' | 'json' | 'blob' = 'json'; + if (localVarHttpHeaderAcceptSelected) { + if (localVarHttpHeaderAcceptSelected.startsWith('text')) { + responseType_ = 'text'; + } else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) { + responseType_ = 'json'; + } else { + responseType_ = 'blob'; + } + } + + let localVarPath = `/api/v1/optimization/${this.configuration.encodeParam({name: "optId", value: optId, in: "path", style: "simple", explode: false, dataType: "number", dataFormat: "int64"})}/stop`; + return this.httpClient.request('post', `${this.configuration.basePath}${localVarPath}`, + { + context: localVarHttpContext, + responseType: responseType_, + withCredentials: this.configuration.withCredentials, + headers: localVarHeaders, + observe: observe, + reportProgress: reportProgress + } + ); + } + + /** + * Submit a new parameter estimation optimization job + * @param optProblem + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public submitOptimization(optProblem?: OptProblem, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable; + public submitOptimization(optProblem?: OptProblem, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public submitOptimization(optProblem?: OptProblem, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public submitOptimization(optProblem?: OptProblem, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { + + let localVarHeaders = this.defaultHeaders; + + let localVarCredential: string | undefined; + // authentication (openId) required + localVarCredential = this.configuration.lookupCredential('openId'); + if (localVarCredential) { + } + + let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept; + if (localVarHttpHeaderAcceptSelected === undefined) { + // to determine the Accept header + const httpHeaderAccepts: string[] = [ + 'application/json' + ]; + localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts); + } + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + let localVarHttpContext: HttpContext | undefined = options && options.context; + if (localVarHttpContext === undefined) { + localVarHttpContext = new HttpContext(); + } + + + // to determine the Content-Type header + const consumes: string[] = [ + 'application/json' + ]; + const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes); + if (httpContentTypeSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected); + } + + let responseType_: 'text' | 'json' | 'blob' = 'json'; + if (localVarHttpHeaderAcceptSelected) { + if (localVarHttpHeaderAcceptSelected.startsWith('text')) { + responseType_ = 'text'; + } else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) { + responseType_ = 'json'; + } else { + responseType_ = 'blob'; + } + } + + let localVarPath = `/api/v1/optimization`; + return this.httpClient.request('post', `${this.configuration.basePath}${localVarPath}`, + { + context: localVarHttpContext, + body: optProblem, + responseType: responseType_, + withCredentials: this.configuration.withCredentials, + headers: localVarHeaders, + observe: observe, + reportProgress: reportProgress + } + ); + } + +} diff --git a/webapp-ng/src/app/core/modules/openapi/api/optimization-resource.serviceInterface.ts b/webapp-ng/src/app/core/modules/openapi/api/optimization-resource.serviceInterface.ts new file mode 100644 index 0000000000..83e8f4556a --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/api/optimization-resource.serviceInterface.ts @@ -0,0 +1,56 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { HttpHeaders } from '@angular/common/http'; + +import { Observable } from 'rxjs'; + +import { OptProblem } from '../model/models'; +import { OptimizationJobStatus } from '../model/models'; +import { VCellHTTPError } from '../model/models'; + + +import { Configuration } from '../configuration'; + + + +export interface OptimizationResourceServiceInterface { + defaultHeaders: HttpHeaders; + configuration: Configuration; + + /** + * Get status, progress, or results of an optimization job + * + * @param optId + */ + getOptimizationStatus(optId: number, extraHttpRequestParams?: any): Observable; + + /** + * List optimization jobs for the authenticated user + * + */ + listOptimizationJobs(extraHttpRequestParams?: any): Observable>; + + /** + * Stop a running optimization job + * + * @param optId + */ + stopOptimization(optId: number, extraHttpRequestParams?: any): Observable; + + /** + * Submit a new parameter estimation optimization job + * + * @param optProblem + */ + submitOptimization(optProblem?: OptProblem, extraHttpRequestParams?: any): Observable; + +} diff --git a/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-method-optimization-method-type.ts b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-method-optimization-method-type.ts new file mode 100644 index 0000000000..1ccbfd2feb --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-method-optimization-method-type.ts @@ -0,0 +1,31 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type CopasiOptimizationMethodOptimizationMethodType = 'SRES' | 'evolutionaryProgram' | 'geneticAlgorithm' | 'geneticAlgorithmSR' | 'hookeJeeves' | 'levenbergMarquardt' | 'nelderMead' | 'particleSwarm' | 'praxis' | 'randomSearch' | 'simulatedAnnealing' | 'steepestDescent' | 'truncatedNewton'; + +export const CopasiOptimizationMethodOptimizationMethodType = { + Sres: 'SRES' as CopasiOptimizationMethodOptimizationMethodType, + EvolutionaryProgram: 'evolutionaryProgram' as CopasiOptimizationMethodOptimizationMethodType, + GeneticAlgorithm: 'geneticAlgorithm' as CopasiOptimizationMethodOptimizationMethodType, + GeneticAlgorithmSr: 'geneticAlgorithmSR' as CopasiOptimizationMethodOptimizationMethodType, + HookeJeeves: 'hookeJeeves' as CopasiOptimizationMethodOptimizationMethodType, + LevenbergMarquardt: 'levenbergMarquardt' as CopasiOptimizationMethodOptimizationMethodType, + NelderMead: 'nelderMead' as CopasiOptimizationMethodOptimizationMethodType, + ParticleSwarm: 'particleSwarm' as CopasiOptimizationMethodOptimizationMethodType, + Praxis: 'praxis' as CopasiOptimizationMethodOptimizationMethodType, + RandomSearch: 'randomSearch' as CopasiOptimizationMethodOptimizationMethodType, + SimulatedAnnealing: 'simulatedAnnealing' as CopasiOptimizationMethodOptimizationMethodType, + SteepestDescent: 'steepestDescent' as CopasiOptimizationMethodOptimizationMethodType, + TruncatedNewton: 'truncatedNewton' as CopasiOptimizationMethodOptimizationMethodType +}; + diff --git a/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-method.ts b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-method.ts new file mode 100644 index 0000000000..c2cc02fe54 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-method.ts @@ -0,0 +1,23 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { CopasiOptimizationParameter } from './copasi-optimization-parameter'; +import { CopasiOptimizationMethodOptimizationMethodType } from './copasi-optimization-method-optimization-method-type'; + + +export interface CopasiOptimizationMethod { + optimizationMethodType?: CopasiOptimizationMethodOptimizationMethodType; + optimizationParameter?: Array; +} +export namespace CopasiOptimizationMethod { +} + + diff --git a/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter-data-type.ts b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter-data-type.ts new file mode 100644 index 0000000000..7aaabe032b --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter-data-type.ts @@ -0,0 +1,20 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type CopasiOptimizationParameterDataType = 'double' | 'int'; + +export const CopasiOptimizationParameterDataType = { + Double: 'double' as CopasiOptimizationParameterDataType, + Int: 'int' as CopasiOptimizationParameterDataType +}; + diff --git a/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter-param-type.ts b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter-param-type.ts new file mode 100644 index 0000000000..4a8adaf816 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter-param-type.ts @@ -0,0 +1,32 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type CopasiOptimizationParameterParamType = 'coolingFactor' | 'iterationLimit' | 'numberOfGenerations' | 'numberOfIterations' | 'pf' | 'populationSize' | 'randomNumberGenerator' | 'rho' | 'scale' | 'seed' | 'startTemperature' | 'stdDeviation' | 'swarmSize' | 'tolerance'; + +export const CopasiOptimizationParameterParamType = { + CoolingFactor: 'coolingFactor' as CopasiOptimizationParameterParamType, + IterationLimit: 'iterationLimit' as CopasiOptimizationParameterParamType, + NumberOfGenerations: 'numberOfGenerations' as CopasiOptimizationParameterParamType, + NumberOfIterations: 'numberOfIterations' as CopasiOptimizationParameterParamType, + Pf: 'pf' as CopasiOptimizationParameterParamType, + PopulationSize: 'populationSize' as CopasiOptimizationParameterParamType, + RandomNumberGenerator: 'randomNumberGenerator' as CopasiOptimizationParameterParamType, + Rho: 'rho' as CopasiOptimizationParameterParamType, + Scale: 'scale' as CopasiOptimizationParameterParamType, + Seed: 'seed' as CopasiOptimizationParameterParamType, + StartTemperature: 'startTemperature' as CopasiOptimizationParameterParamType, + StdDeviation: 'stdDeviation' as CopasiOptimizationParameterParamType, + SwarmSize: 'swarmSize' as CopasiOptimizationParameterParamType, + Tolerance: 'tolerance' as CopasiOptimizationParameterParamType +}; + diff --git a/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter.ts b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter.ts new file mode 100644 index 0000000000..ed460efc77 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/copasi-optimization-parameter.ts @@ -0,0 +1,24 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { CopasiOptimizationParameterDataType } from './copasi-optimization-parameter-data-type'; +import { CopasiOptimizationParameterParamType } from './copasi-optimization-parameter-param-type'; + + +export interface CopasiOptimizationParameter { + dataType?: CopasiOptimizationParameterDataType; + paramType?: CopasiOptimizationParameterParamType; + value?: number; +} +export namespace CopasiOptimizationParameter { +} + + diff --git a/webapp-ng/src/app/core/modules/openapi/model/models.ts b/webapp-ng/src/app/core/modules/openapi/model/models.ts index 9bc33ff6b3..f86e9ddb15 100644 --- a/webapp-ng/src/app/core/modules/openapi/model/models.ts +++ b/webapp-ng/src/app/core/modules/openapi/model/models.ts @@ -10,6 +10,11 @@ export * from './biomodel-ref'; export * from './composite-curve'; export * from './control-point-curve'; export * from './coordinate'; +export * from './copasi-optimization-method'; +export * from './copasi-optimization-method-optimization-method-type'; +export * from './copasi-optimization-parameter'; +export * from './copasi-optimization-parameter-data-type'; +export * from './copasi-optimization-parameter-param-type'; export * from './curve'; export * from './curve-selection-info'; export * from './data-identifier'; @@ -44,10 +49,19 @@ export * from './math-type'; export * from './mathmodel-ref'; export * from './model-type'; export * from './n5-export-request'; +export * from './opt-job-status'; +export * from './opt-problem'; +export * from './opt-progress-item'; +export * from './opt-progress-report'; +export * from './opt-result-set'; +export * from './optimization-job-status'; export * from './origin'; +export * from './parameter-description'; export * from './publication'; export * from './publication-info'; export * from './publish-models-request'; +export * from './reference-variable'; +export * from './reference-variable-reference-variable-type'; export * from './specialclaim'; export * from './sampled-curve'; export * from './scheduler-status'; @@ -82,5 +96,7 @@ export * from './variable-domain'; export * from './variable-mode'; export * from './variable-specs'; export * from './variable-type'; +export * from './vcellopt'; +export * from './vcellopt-status'; export * from './version'; export * from './version-flag'; diff --git a/webapp-ng/src/app/core/modules/openapi/model/opt-job-status.ts b/webapp-ng/src/app/core/modules/openapi/model/opt-job-status.ts new file mode 100644 index 0000000000..355eaa0dd0 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/opt-job-status.ts @@ -0,0 +1,24 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type OptJobStatus = 'SUBMITTED' | 'QUEUED' | 'RUNNING' | 'COMPLETE' | 'FAILED' | 'STOPPED'; + +export const OptJobStatus = { + Submitted: 'SUBMITTED' as OptJobStatus, + Queued: 'QUEUED' as OptJobStatus, + Running: 'RUNNING' as OptJobStatus, + Complete: 'COMPLETE' as OptJobStatus, + Failed: 'FAILED' as OptJobStatus, + Stopped: 'STOPPED' as OptJobStatus +}; + diff --git a/webapp-ng/src/app/core/modules/openapi/model/opt-problem.ts b/webapp-ng/src/app/core/modules/openapi/model/opt-problem.ts new file mode 100644 index 0000000000..39f9f788ef --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/opt-problem.ts @@ -0,0 +1,25 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { CopasiOptimizationMethod } from './copasi-optimization-method'; +import { ReferenceVariable } from './reference-variable'; +import { ParameterDescription } from './parameter-description'; + + +export interface OptProblem { + copasiOptimizationMethod?: CopasiOptimizationMethod; + dataSet?: Array>; + mathModelSbmlContents?: string; + numberOfOptimizationRuns?: number; + parameterDescriptionList?: Array; + referenceVariable?: Array; +} + diff --git a/webapp-ng/src/app/core/modules/openapi/model/opt-progress-item.ts b/webapp-ng/src/app/core/modules/openapi/model/opt-progress-item.ts new file mode 100644 index 0000000000..45a2631cac --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/opt-progress-item.ts @@ -0,0 +1,18 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface OptProgressItem { + numFunctionEvaluations?: number; + objFuncValue?: number; +} + diff --git a/webapp-ng/src/app/core/modules/openapi/model/opt-progress-report.ts b/webapp-ng/src/app/core/modules/openapi/model/opt-progress-report.ts new file mode 100644 index 0000000000..069201725d --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/opt-progress-report.ts @@ -0,0 +1,19 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { OptProgressItem } from './opt-progress-item'; + + +export interface OptProgressReport { + bestParamValues?: { [key: string]: number; }; + progressItems?: Array; +} + diff --git a/webapp-ng/src/app/core/modules/openapi/model/opt-result-set.ts b/webapp-ng/src/app/core/modules/openapi/model/opt-result-set.ts new file mode 100644 index 0000000000..ac40abd3aa --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/opt-result-set.ts @@ -0,0 +1,21 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { OptProgressReport } from './opt-progress-report'; + + +export interface OptResultSet { + numFunctionEvaluations?: number; + objectiveFunction?: number; + optParameterValues?: { [key: string]: number; }; + optProgressReport?: OptProgressReport; +} + diff --git a/webapp-ng/src/app/core/modules/openapi/model/optimization-job-status.ts b/webapp-ng/src/app/core/modules/openapi/model/optimization-job-status.ts new file mode 100644 index 0000000000..90ad5d5a95 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/optimization-job-status.ts @@ -0,0 +1,28 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { OptProgressReport } from './opt-progress-report'; +import { Vcellopt } from './vcellopt'; +import { OptJobStatus } from './opt-job-status'; + + +export interface OptimizationJobStatus { + id?: string; + status?: OptJobStatus; + statusMessage?: string; + htcJobId?: string; + progressReport?: OptProgressReport; + results?: Vcellopt; +} +export namespace OptimizationJobStatus { +} + + diff --git a/webapp-ng/src/app/core/modules/openapi/model/parameter-description.ts b/webapp-ng/src/app/core/modules/openapi/model/parameter-description.ts new file mode 100644 index 0000000000..aa892e34b8 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/parameter-description.ts @@ -0,0 +1,21 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ParameterDescription { + initialValue?: number; + maxValue?: number; + minValue?: number; + name?: string; + scale?: number; +} + diff --git a/webapp-ng/src/app/core/modules/openapi/model/reference-variable-reference-variable-type.ts b/webapp-ng/src/app/core/modules/openapi/model/reference-variable-reference-variable-type.ts new file mode 100644 index 0000000000..308273f6fd --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/reference-variable-reference-variable-type.ts @@ -0,0 +1,20 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type ReferenceVariableReferenceVariableType = 'dependent' | 'independent'; + +export const ReferenceVariableReferenceVariableType = { + Dependent: 'dependent' as ReferenceVariableReferenceVariableType, + Independent: 'independent' as ReferenceVariableReferenceVariableType +}; + diff --git a/webapp-ng/src/app/core/modules/openapi/model/reference-variable.ts b/webapp-ng/src/app/core/modules/openapi/model/reference-variable.ts new file mode 100644 index 0000000000..8e5d012668 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/reference-variable.ts @@ -0,0 +1,22 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { ReferenceVariableReferenceVariableType } from './reference-variable-reference-variable-type'; + + +export interface ReferenceVariable { + referenceVariableType?: ReferenceVariableReferenceVariableType; + varName?: string; +} +export namespace ReferenceVariable { +} + + diff --git a/webapp-ng/src/app/core/modules/openapi/model/vcellopt-status.ts b/webapp-ng/src/app/core/modules/openapi/model/vcellopt-status.ts new file mode 100644 index 0000000000..5c3474893f --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/vcellopt-status.ts @@ -0,0 +1,22 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type VcelloptStatus = 'complete' | 'failed' | 'queued' | 'running'; + +export const VcelloptStatus = { + Complete: 'complete' as VcelloptStatus, + Failed: 'failed' as VcelloptStatus, + Queued: 'queued' as VcelloptStatus, + Running: 'running' as VcelloptStatus +}; + diff --git a/webapp-ng/src/app/core/modules/openapi/model/vcellopt.ts b/webapp-ng/src/app/core/modules/openapi/model/vcellopt.ts new file mode 100644 index 0000000000..3f57be355d --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/vcellopt.ts @@ -0,0 +1,26 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { VcelloptStatus } from './vcellopt-status'; +import { OptProblem } from './opt-problem'; +import { OptResultSet } from './opt-result-set'; + + +export interface Vcellopt { + optProblem?: OptProblem; + optResultSet?: OptResultSet; + status?: VcelloptStatus; + statusMessage?: string; +} +export namespace Vcellopt { +} + +