diff --git a/packages/frontend/src/components/parameters/GlobalParamsView.tsx b/packages/frontend/src/components/parameters/GlobalParamsView.tsx index 88fcd7c..8b20e39 100644 --- a/packages/frontend/src/components/parameters/GlobalParamsView.tsx +++ b/packages/frontend/src/components/parameters/GlobalParamsView.tsx @@ -11,11 +11,11 @@ export const GlobalParamsView: React.FC = ({ params }) => - Time Step: {params.timeStep} + Time Step: {params.timeStep} (h/cycle) Log Frequency: {params.logFreq} - Nutrient Diffusivity: {params.defaultDiffConst} cm2/s - Default VMax: {params.defaultVMax} - Default KM: {params.defaultKm} + Nutrient Diffusivity: {params.defaultDiffConst} (cm^2/s) + Default VMax: {params.defaultVMax} (mmol/gh) + Default KM: {params.defaultKm} (M) Max Cycles: {params.maxCycles} diff --git a/packages/frontend/src/components/parameters/MetaboliteParamsView.tsx b/packages/frontend/src/components/parameters/MetaboliteParamsView.tsx index 4330c37..2487319 100644 --- a/packages/frontend/src/components/parameters/MetaboliteParamsView.tsx +++ b/packages/frontend/src/components/parameters/MetaboliteParamsView.tsx @@ -13,7 +13,7 @@ export const MetaboliteParamsView: React.FC = ({ para Type: {getMetaboliteName(params.type)} - Amount: {params.concentration} mmol/cm3 + Amount: {params.concentration} (M) diff --git a/packages/frontend/src/components/parameters/ModelParamsView.tsx b/packages/frontend/src/components/parameters/ModelParamsView.tsx index 649b763..64e0d9f 100644 --- a/packages/frontend/src/components/parameters/ModelParamsView.tsx +++ b/packages/frontend/src/components/parameters/ModelParamsView.tsx @@ -29,8 +29,8 @@ const SingleModelParamsView: React.FC<{ params: ModelParametersInput }> = ({ par Neutral Drift: {params.neutralDrift ? 'True' : 'False'} Neutral Drift Amp: {params.neutralDriftAmp} Death Rate: {params.deathRate} - Linear Diffusivity: {params.linearDiffusivity} - Nonlinear Diffusivity: {params.nonlinearDiffusivity} + Linear Diffusivity: {params.linearDiffusivity} (cm^2/s) + Nonlinear Diffusivity: {params.nonlinearDiffusivity} (cm^2/sg) ); diff --git a/packages/frontend/src/pages/ExperimentForm.tsx b/packages/frontend/src/pages/ExperimentForm.tsx index ccdd49d..adec2b5 100644 --- a/packages/frontend/src/pages/ExperimentForm.tsx +++ b/packages/frontend/src/pages/ExperimentForm.tsx @@ -1,6 +1,6 @@ import { JsonForms } from '@jsonforms/react'; import { materialRenderers, materialCells } from '@jsonforms/material-renderers'; -import { JsonSchema } from '@jsonforms/core'; +import { JsonSchema7 } from '@jsonforms/core'; import { Box, Stack, Button } from '@mui/material'; import { ErrorObject } from 'ajv'; import { useState } from 'react'; @@ -29,7 +29,40 @@ const getSchema = (metaboliteType: MetaboliteType | null) => { ]; } - const schema: JsonSchema = { + const metaboliteParams: JsonSchema7 = { + type: 'object', + title: 'Metabolite Parameters', + properties: { + type: { + type: 'string', + oneOf: [ + { + const: MetaboliteType.Glucose, + title: getMetaboliteName(MetaboliteType.Glucose) + }, + { + const: MetaboliteType.Acetate, + title: getMetaboliteName(MetaboliteType.Acetate) + }, + { + const: MetaboliteType.Rich, + title: getMetaboliteName(MetaboliteType.Rich) + } + ] + } + }, + required: ['type'] + }; + + if (metaboliteType != MetaboliteType.Rich) { + metaboliteParams!.properties!['concentration'] = { + type: 'number', + title: 'Concentration (M)' + }; + metaboliteParams.required!.push('concentration'); + } + + const schema: JsonSchema7 = { type: 'object', properties: { layoutParams: { @@ -60,34 +93,7 @@ const getSchema = (metaboliteType: MetaboliteType | null) => { }, required: ['type', 'volume'] }, - metaboliteParams: { - type: 'object', - title: 'Metabolite Parameters', - properties: { - type: { - type: 'string', - oneOf: [ - { - const: MetaboliteType.Glucose, - title: getMetaboliteName(MetaboliteType.Glucose) - }, - { - const: MetaboliteType.Acetate, - title: getMetaboliteName(MetaboliteType.Acetate) - }, - { - const: MetaboliteType.Rich, - title: getMetaboliteName(MetaboliteType.Rich) - } - ] - }, - concentration: { - type: 'number', - title: 'Concentration (mmol/cm3)' - } - }, - required: ['type', 'concentration'] - }, + metaboliteParams: metaboliteParams, modelParams: { type: 'array', title: 'Model Parameters', @@ -111,11 +117,13 @@ const getSchema = (metaboliteType: MetaboliteType | null) => { }, linearDiffusivity: { type: 'number', - default: 0.001 + default: 0.001, + title: 'Linear Diffusivity (cm^2/s)' }, nonlinearDiffusivity: { type: 'number', - default: 0.6 + default: 0.6, + title: 'Nonlinear Diffusivity (cm^2/sg)' } }, required: ['name', 'neutralDriftAmp', 'deathRate', 'linearDiffusivity', 'nonlinearDiffusivity'] @@ -127,7 +135,8 @@ const getSchema = (metaboliteType: MetaboliteType | null) => { properties: { timeStep: { type: 'number', - default: 0.1 + default: 0.1, + title: 'Timestep (Hours/Cycle)' }, logFreq: { type: 'number', @@ -136,15 +145,17 @@ const getSchema = (metaboliteType: MetaboliteType | null) => { defaultDiffConst: { type: 'number', default: 0.000006, - title: 'Nutrient Diffusivity (cm2/s)' + title: 'Nutrient Diffusivity (cm^2/s)' }, defaultVMax: { type: 'number', - default: 10 + default: 10, + title: 'Default VMax (mmol/gh)' }, defaultKm: { type: 'number', - default: 0.00001 + default: 0.00001, + title: 'Default KM (M)' }, maxCycles: { type: 'number', diff --git a/packages/frontend/src/pages/SummaryReview.tsx b/packages/frontend/src/pages/SummaryReview.tsx index eb73ccf..7ab6784 100644 --- a/packages/frontend/src/pages/SummaryReview.tsx +++ b/packages/frontend/src/pages/SummaryReview.tsx @@ -58,6 +58,12 @@ const InformationSection: React.FC = ({ data }) => { for (const model of data['modelParams']) { model['neutralDrift'] = !!model['neutralDrift']; } + + // If the concentration value is not present, provide a default + if (!data.metaboliteParams.concentration) { + data.metaboliteParams.concentration = 0.0; + } + requestSimulation({ variables: { request: { diff --git a/packages/runner/runner/savers.py b/packages/runner/runner/savers.py index 68d6c91..757e894 100644 --- a/packages/runner/runner/savers.py +++ b/packages/runner/runner/savers.py @@ -23,9 +23,9 @@ def upload_file(self, config: SaveConfig, key: str, filename: Path) -> None: @abstractmethod def save(self, experiment: c.comets, config: SaveConfig) -> dict: - """ + ''' Handles saving a component of the comets experiment - """ + ''' class BiomassSaver(Saver): def save(self, experiment: c.comets, config: SaveConfig) -> dict: @@ -219,17 +219,16 @@ def save(self, experiment: c.comets, config: SaveConfig) -> dict: output_path = config.output_folder / filename bucket_location = f'{config.s3_folder}/{filename}' - media = experiment.media.copy() - media['time'] = media['cycle'] * experiment.parameters.get_param('timeStep') - media = media[media.conc_mmol<900] + # Get the time series media data and convert time to hours + media = experiment.get_metabolite_time_series(upper_threshold=900) + media['cycle'] = media['cycle'] * experiment.parameters.get_param('timeStep') + # Plot the media time series fig, ax = plt.subplots() - media.groupby('metabolite').plot(x='time', ax =ax, y='conc_mmol') - ax.legend(('acetate','CO2', 'formate', 'glucose')) - ax.set_ylabel("Concentration (mmol)") - ax.set_xlabel("Time (h)") + ax = media.plot(x='cycle', ax=ax) + ax.set_ylabel('Concentration (mmol)') + ax.set_xlabel('Time (h)') - # Save the file and upload plt.savefig(output_path, format='png', bbox_inches='tight') self.upload_file(config, bucket_location, output_path)