From 267ac36e11abf833eac104633bbcab8ad154f617 Mon Sep 17 00:00:00 2001 From: meganrm Date: Fri, 19 Jan 2024 10:28:30 -0800 Subject: [PATCH 01/11] cleanup types --- src/App.tsx | 7 ++++--- src/components/Concentration.tsx | 2 +- src/components/Slider.tsx | 5 ++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 80f1e27..f09117e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -59,10 +59,11 @@ function App() { }, [timeFactor, clientSimulator]); const handleConcentrationChange = ( - name: AvailableAgentNames, + name: string, value: number ) => { - const agentId = AVAILABLE_AGENTS[name].id; + const agentName = name as AvailableAgentNames; + const agentId = AVAILABLE_AGENTS[agentName].id; clientSimulator.changeConcentration(agentId, value); setConcentration({ ...concentration, [name]: value }); const time = simulariumController.time(); @@ -93,7 +94,7 @@ function App() { onChange={handleConcentrationChange} /> setActiveAgents(e.target.value.split(",") as AvailableAgentNames[])} + onChange={(e) => + setActiveAgents( + e.target.value.split(",") as AvailableAgentNames[] + ) + } defaultValue={trajectories[0]} > - - + + - - +
+ + +
); diff --git a/src/BindingSimulator2D.ts b/src/BindingSimulator2D.ts index 75febb6..ff8c3bf 100644 --- a/src/BindingSimulator2D.ts +++ b/src/BindingSimulator2D.ts @@ -141,46 +141,46 @@ class BindingInstance extends Circle { return [x, y]; } - public unBind(ligand: BindingInstance) { + public unBind(ligand: BindingInstance): boolean { if (ligand.kOff === undefined) { - return; + return false; } const willUnBind = random(0, 1, true) > ligand.kOff; if (!willUnBind) { - return; + return false; } this.child = null; this.isTrigger = false; ligand.bound = false; ligand.isTrigger = false; - return; + return true; } - public bind(ligand: BindingInstance) { + public bind(ligand: BindingInstance): boolean { if (ligand.bound || this.child) { // already have bound ligand or already bound // can't bind to another ligand - return; + return false; } if (ligand.kOn === undefined) { - return; + return false; } const willBind = random(0, 1, true) > ligand.kOn; if (!willBind) { - return; + return false; } this.child = ligand; this.isTrigger = true; ligand.bound = true; ligand.isTrigger = true; - return; + return true; } } const size = 100; export default class BindingSimulator implements IClientSimulatorImpl { - instances: BindingInstance[]; + instances: BindingInstance[] = []; currentFrame: number; agents: InputAgent[] = []; system: System; @@ -188,10 +188,11 @@ export default class BindingSimulator implements IClientSimulatorImpl { timeFactor: number; static: boolean = false; initialState: boolean = true; + currentNumberBound: number = 0; + onUpdate: (data: number) => void = () => {}; constructor(agents: InputAgent[], timeFactor: number = 25) { this.system = new System(); this.agents = agents; - this.instances = []; this.createBoundingLines(); this.distanceFactor = 10; this.timeFactor = timeFactor; @@ -201,6 +202,7 @@ export default class BindingSimulator implements IClientSimulatorImpl { } private clearAgents() { + this.currentNumberBound = 0; this.system = new System(); this.instances = []; } @@ -231,10 +233,6 @@ export default class BindingSimulator implements IClientSimulatorImpl { } } - public setTimeScale(timeScale: number) { - this.timeFactor = timeScale; - } - public changeConcentration(agentId: number, newConcentration: number) { const agent = this.agents.find((agent) => agent.id === agentId); if (!agent) { @@ -308,6 +306,12 @@ export default class BindingSimulator implements IClientSimulatorImpl { return count; } + private convertCountToConcentration(count: number) { + const volume = size * size * 1 * this.distanceFactor ** 2; + const concentration = count / (volume * 10 ** -6 * 6.022); + return concentration; + } + private getRandomPointOnSide(side: number, total: number) { const buffer = size / 5; const dFromSide = random(0 + buffer, size / 2, true); @@ -342,6 +346,14 @@ export default class BindingSimulator implements IClientSimulatorImpl { // }, } + public setTimeScale(timeScale: number) { + this.timeFactor = timeScale; + } + + public getCurrentConcentrationBound() { + return this.convertCountToConcentration(this.currentNumberBound); + } + public staticUpdate() { // update the number of agents without // changing their positions @@ -397,20 +409,28 @@ export default class BindingSimulator implements IClientSimulatorImpl { if (response) { if (a.isBoundPair(b)) { + let unbound = false; if (a.r < b.r) { - b.unBind(a); + unbound = b.unBind(a); } else { // b is the ligand - a.unBind(b); + unbound = a.unBind(b); + } + if (unbound) { + this.currentNumberBound--; } } if (a.partners.includes(b.id)) { // a is the ligand + let bound = false; if (a.r < b.r) { - b.bind(a); + bound = b.bind(a); } else { // b is the ligand - a.bind(b); + bound = a.bind(b); + } + if (bound) { + this.currentNumberBound++; } } if (a.isTrigger && b.isTrigger && !a.isBoundPair(b)) { @@ -455,6 +475,7 @@ export default class BindingSimulator implements IClientSimulatorImpl { ], fileName: "hello world", }; + this.currentFrame++; return frameData; } diff --git a/src/components/Concentration.tsx b/src/components/Concentration.tsx index d637998..db6ff90 100644 --- a/src/components/Concentration.tsx +++ b/src/components/Concentration.tsx @@ -4,12 +4,16 @@ import { map } from "lodash"; import { AvailableAgentNames } from "../types"; interface AgentProps { - agents: { [key in AvailableAgentNames]: number }; + activeAgents: AvailableAgentNames[]; + concentration: { [key in AvailableAgentNames]: number }; onChange: (name: string, value: number) => void; } -const Concentration: React.FC = ({ agents, onChange }) => { - return map(agents, (concentration, agent: AvailableAgentNames) => { +const Concentration: React.FC = ({ concentration, onChange, activeAgents }) => { + return map(concentration, (concentration, agent: AvailableAgentNames) => { + if (!activeAgents.includes(agent)) { + return null; + } return ( = ({ data }) => { + const traces = map( + data, + (yValues: number[], id: string): Partial => { + if (yValues.length === 0) { + return {}; + } + return { + x: yValues.map((_, i) => i), + y: yValues, + type: "scatter" as const, + mode: "lines" as const, + name: id, + }; + } + ); + + const layout = { + title: "Concentration over Time", + xaxis: { title: "Time", range: [0, "auto"] }, + yaxis: { title: "Concentration" }, + }; + + return ; +}; + +export default LinePlot; diff --git a/src/components/Viewer.tsx b/src/components/Viewer.tsx index b056d13..5068857 100644 --- a/src/components/Viewer.tsx +++ b/src/components/Viewer.tsx @@ -8,8 +8,10 @@ import "@aics/simularium-viewer/style/style.css"; export default function Viewer({ controller, + handleTimeChange, }: { controller: SimulariumController; + handleTimeChange: () => void; }): ReactNode { const agentColors = [ "#fee34d", @@ -36,9 +38,7 @@ export default function Viewer({ hiddenAgents: [], colorChange: null, }); - const handleTimeChange = () => { - // console.log("time changed", timeData); - }; + return (
{}} selectionStateInfo={selectionStateInfo} onUIDisplayDataChanged={() => { - return undefined + return undefined; }} loadInitialData={true} agentColors={agentColors} diff --git a/src/constants/trajectories.ts b/src/constants/trajectories.ts index e907c08..cc4e81f 100644 --- a/src/constants/trajectories.ts +++ b/src/constants/trajectories.ts @@ -11,8 +11,8 @@ const agentB = { concentration: 10, radius: 0.7, partners: [0], - kOn: 0.1, - kOff: 0.5, + kOn: 0.5, + kOff: 0.3, }; const agentC = { @@ -20,8 +20,8 @@ const agentC = { concentration: 10, radius: 1, partners: [0], - kOn: 0.1, - kOff: 0.5, + kOn: 0.5, + kOff: 0.8, }; export const AVAILABLE_AGENTS = { diff --git a/src/main.tsx b/src/main.tsx index 3d7150d..8821f6a 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -4,7 +4,6 @@ import App from './App.tsx' import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( - + // - , ) From 0ac6332d905ace7bf078909ad1661af4dd9ae633 Mon Sep 17 00:00:00 2001 From: meganrm Date: Tue, 23 Jan 2024 15:05:34 -0800 Subject: [PATCH 03/11] cleanup --- src/App.tsx | 12 +++++------- src/components/Viewer.tsx | 2 +- src/main.tsx | 17 +++++++++-------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 5a84dba..b6d7a63 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import "./App.css"; import Viewer from "./components/Viewer"; @@ -39,7 +39,6 @@ function App() { }, [activeAgents]); const handleTimeChange = () => { - const newValue = clientSimulator.getCurrentConcentrationBound(); const currentConcentration = concentration[AvailableAgentNames.B]; const currentArray = concentrationOverTime[currentConcentration]; @@ -65,7 +64,7 @@ function App() { if (isPlaying) { clientSimulator.initialState = false; simulariumController.resume(); - console.log("playing") + console.log("playing"); } else { simulariumController.pause(); console.log("paused"); @@ -80,6 +79,7 @@ function App() { const agentName = name as AvailableAgentNames; const agentId = AVAILABLE_AGENTS[agentName].id; clientSimulator.changeConcentration(agentId, value); + setConcentration({ ...concentration, [name]: value }); const time = simulariumController.time(); const newState = { @@ -111,7 +111,7 @@ function App() { /> @@ -131,7 +131,7 @@ function App() { controller={simulariumController} handleTimeChange={handleTimeChange} /> - +
From b8e513231f1c12623325b810f379cbf16ee6bdd2 Mon Sep 17 00:00:00 2001 From: meganrm Date: Tue, 23 Jan 2024 15:18:26 -0800 Subject: [PATCH 06/11] make kOn and Off more consistent --- src/BindingSimulator2D.ts | 4 ++-- src/constants/trajectories.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/BindingSimulator2D.ts b/src/BindingSimulator2D.ts index ff8c3bf..d05ba6e 100644 --- a/src/BindingSimulator2D.ts +++ b/src/BindingSimulator2D.ts @@ -145,7 +145,7 @@ class BindingInstance extends Circle { if (ligand.kOff === undefined) { return false; } - const willUnBind = random(0, 1, true) > ligand.kOff; + const willUnBind = random(0, 1, true) < ligand.kOff; if (!willUnBind) { return false; } @@ -165,7 +165,7 @@ class BindingInstance extends Circle { if (ligand.kOn === undefined) { return false; } - const willBind = random(0, 1, true) > ligand.kOn; + const willBind = random(0, 1, true) < ligand.kOn; if (!willBind) { return false; } diff --git a/src/constants/trajectories.ts b/src/constants/trajectories.ts index cc4e81f..11e43f2 100644 --- a/src/constants/trajectories.ts +++ b/src/constants/trajectories.ts @@ -11,8 +11,8 @@ const agentB = { concentration: 10, radius: 0.7, partners: [0], - kOn: 0.5, - kOff: 0.3, + kOn: 0.6, + kOff: 0.2, }; const agentC = { From 4238e2900fe4c30250133ca816d1028aabb33fc0 Mon Sep 17 00:00:00 2001 From: meganrm Date: Fri, 26 Jan 2024 13:41:09 -0800 Subject: [PATCH 07/11] disable sliders while playing --- src/App.tsx | 3 ++- src/components/Concentration.tsx | 4 +++- src/components/Plot.tsx | 5 ++++- src/components/Slider.tsx | 9 +++++++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index bdbdaa2..4754084 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -19,7 +19,7 @@ const INITIAL_CONCENTRATIONS = { A: 10, B: 10, C: 10 }; function App() { const [isPlaying, setIsPlaying] = useState(false); const [inputConcentration, setInputConcentration] = useState(INITIAL_CONCENTRATIONS); - const [timeFactor, setTimeFactor] = useState(25); + const [timeFactor, setTimeFactor] = useState(30); const [productOverTime, setProductOverTime] = useState({ [inputConcentration[AvailableAgentNames.B]]: [0], }); @@ -113,6 +113,7 @@ function App() { activeAgents={activeAgents} concentration={inputConcentration} onChange={handleNewInputConcentration} + disabled={isPlaying} />