diff --git a/examples/src/Viewer.tsx b/examples/src/Viewer.tsx index aff050d8..f82d321b 100644 --- a/examples/src/Viewer.tsx +++ b/examples/src/Viewer.tsx @@ -128,6 +128,7 @@ class Viewer extends React.Component { private panMode = false; private focusMode = true; private orthoMode = false; + private smoldynInput = "100"; private netConnectionSettings: NetConnectionParams; public constructor(props: InputParams) { @@ -353,6 +354,28 @@ class Viewer extends React.Component { }); } + public loadSmoldynSim() { + simulariumController.checkServerHealth( + this.onHealthCheckResponse, + this.netConnectionSettings + ); + const fileName = "smoldyn_sim" + uuidv4() + ".simularium" + simulariumController + .startSmoldynSim(this.netConnectionSettings, fileName, this.smoldynInput) + .then(() => { + this.clearPendingFile(); + }) + .then(() => { + simulariumController.initNewFile( + { netConnectionSettings: this.netConnectionSettings, }, + true, + ) + }) + .catch((err) => { + console.error(err); + }); + } + public clearPendingFile() { this.setState({ filePending: null }); } @@ -430,11 +453,10 @@ class Viewer extends React.Component { public receiveConvertedFile(): void { simulariumController - .changeFile( + .initNewFile( { netConnectionSettings: this.netConnectionSettings, }, - this.state.conversionFileName ) .then(() => { simulariumController.gotoTime(0); @@ -773,6 +795,17 @@ class Viewer extends React.Component { Load a smoldyn trajectory
+ + +
diff --git a/src/controller/index.ts b/src/controller/index.ts index 07ee2c61..3f9f202f 100644 --- a/src/controller/index.ts +++ b/src/controller/index.ts @@ -118,6 +118,9 @@ export default class SimulariumController { this.setFocusMode = this.setFocusMode.bind(this); this.convertTrajectory = this.convertTrajectory.bind(this); this.setCameraType = this.setCameraType.bind(this); + this.startSmoldynSim = this.startSmoldynSim.bind(this); + this.cancelCurrentFile = this.cancelCurrentFile.bind(this); + this.initNewFile = this.initNewFile.bind(this); } private createSimulatorConnection( @@ -240,6 +243,8 @@ export default class SimulariumController { fileType: TrajectoryType, providedFileName?: string ): Promise { + const fileName = providedFileName ?? `${uuidv4()}.simularium`; + this.cancelCurrentFile(fileName); try { if (!this.isRemoteOctopusClientConfigured()) { this.configureNetwork(netConnectionConfig); @@ -250,7 +255,6 @@ export default class SimulariumController { if (!this.simulator) { throw new Error("Simulator not initialized"); } - const fileName = providedFileName ?? `${uuidv4()}.simularium`; return this.octopusClient.convertTrajectory( dataToConvert, fileType, @@ -278,6 +282,28 @@ export default class SimulariumController { } } + public startSmoldynSim( + netConnectionConfig: NetConnectionParams, + fileName: string, + smoldynInput: string + ): Promise { + this.cancelCurrentFile(fileName); + try { + if (!this.isRemoteOctopusClientConfigured()) { + this.configureNetwork(netConnectionConfig); + } + if (!this.octopusClient) { + throw new Error("Octopus client not configured"); + } + if (!this.simulator) { + throw new Error("Simulator not initialized"); + } + return this.octopusClient.sendSmoldynData(fileName, smoldynInput); + } catch (e) { + return Promise.reject(e); + } + } + public gotoTime(time: number): void { // If in the middle of changing files, ignore any gotoTime requests if (this.isFileChanging || !this.simulator) return; @@ -331,12 +357,7 @@ export default class SimulariumController { } } - public changeFile( - connectionParams: SimulatorConnectionParams, - // TODO: push newFileName into connectionParams - newFileName: string, - keepRemoteConnection = false - ): Promise { + public cancelCurrentFile(newFileName: string): void { this.isFileChanging = true; this.playBackFile = newFileName; @@ -345,7 +366,12 @@ export default class SimulariumController { this.visData.WaitForFrame(0); this.visData.clearForNewTrajectory(); + } + public initNewFile( + connectionParams: SimulatorConnectionParams, + keepRemoteConnection = false + ): Promise { const shouldConfigureNewSimulator = !( keepRemoteConnection && this.isRemoteOctopusClientConfigured() ); @@ -391,6 +417,16 @@ export default class SimulariumController { }); } + public changeFile( + connectionParams: SimulatorConnectionParams, + // TODO: push newFileName into connectionParams + newFileName: string, + keepRemoteConnection = false + ): Promise { + this.cancelCurrentFile(newFileName); + return this.initNewFile(connectionParams, keepRemoteConnection); + } + public markFileChangeAsHandled(): void { this.isFileChanging = false; } diff --git a/src/simularium/OctopusClient.ts b/src/simularium/OctopusClient.ts index bf68f87b..eece0003 100644 --- a/src/simularium/OctopusClient.ts +++ b/src/simularium/OctopusClient.ts @@ -62,4 +62,20 @@ export class OctopusServicesClient { "Request server health check" ); } + + public async sendSmoldynData( + outFileName: string, + smoldynInput: string + ): Promise { + await this.webSocketClient.connectToRemoteServer(); + this.lastRequestedFile = outFileName; + this.webSocketClient.sendWebSocketRequest( + { + msgType: NetMessageEnum.ID_START_SMOLDYN, + fileName: outFileName, + smoldynInputVal: smoldynInput ?? undefined, + }, + "Start smoldyn simulation" + ); + } } diff --git a/src/simularium/WebsocketClient.ts b/src/simularium/WebsocketClient.ts index 3175eab0..a8b8ac8b 100644 --- a/src/simularium/WebsocketClient.ts +++ b/src/simularium/WebsocketClient.ts @@ -57,6 +57,7 @@ export const enum NetMessageEnum { ID_CHECK_HEALTH_REQUEST = 22, ID_SERVER_HEALTHY_RESPONSE = 23, ID_CANCEL_CONVERSION = 24, + ID_START_SMOLDYN = 25, // insert new values here before LENGTH LENGTH, } @@ -70,6 +71,7 @@ export const enum ServerErrorCodes { FRAME_NOT_FOUND = 5, FILENAME_MISMATCH = 6, NO_RUNNING_SIMULATION = 7, + SMOLDYN_ERROR = 8, LENGTH, }