-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/low affinity values #186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
4b46385
7798a02
0649009
662c7e9
c29a3af
259648b
2701ae8
edaaa71
8cc356c
5d4ba32
2acfa93
1afdc20
a714d6c
88965e2
d3e750c
bee4391
2d145db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -275,6 +275,7 @@ function App() { | |
| uniqMeasuredConcentrations.length >= 3 | ||
| ); | ||
| }, [hasAValueAboveKd, hasAValueBelowKd, uniqMeasuredConcentrations]); | ||
|
|
||
| const handleNewInputConcentration = useCallback( | ||
| (name: string, value: number) => { | ||
| if (value === 0) { | ||
|
|
@@ -292,10 +293,10 @@ function App() { | |
| name as keyof typeof LiveSimulationData.AVAILABLE_AGENTS; | ||
| const agentId = LiveSimulationData.AVAILABLE_AGENTS[agentName].id; | ||
| clientSimulator.changeConcentration(agentId, value); | ||
| simulariumController.gotoTime(time + 1); | ||
| simulariumController.gotoTime(1); // the number isn't used, but it triggers the update | ||
| resetCurrentRunAnalysisState(); | ||
| }, | ||
| [clientSimulator, time, simulariumController] | ||
| [clientSimulator, simulariumController] | ||
| ); | ||
| const totalReset = useCallback(() => { | ||
| setLiveConcentration({ | ||
|
|
@@ -348,6 +349,7 @@ function App() { | |
| usePageNumber( | ||
| page, | ||
| (page) => | ||
| currentModule === 1 && | ||
meganrm marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| page === PROMPT_TO_ADJUST_B && | ||
| isPlaying && | ||
| recordedInputConcentration.length > 0 && | ||
|
|
@@ -417,12 +419,18 @@ function App() { | |
|
|
||
| useEffect(() => { | ||
| const { section } = content[currentModule][page]; | ||
| if (section === Section.Experiment) { | ||
| if ( | ||
| section === Section.Experiment && | ||
| timeFactor !== LiveSimulationData.DEFAULT_TIME_FACTOR | ||
| ) { | ||
| setTimeFactor(LiveSimulationData.DEFAULT_TIME_FACTOR); | ||
| } else if (section === Section.Introduction) { | ||
| } else if ( | ||
| section === Section.Introduction && | ||
| timeFactor !== LiveSimulationData.INITIAL_TIME_FACTOR | ||
| ) { | ||
|
||
| setTimeFactor(LiveSimulationData.INITIAL_TIME_FACTOR); | ||
| } | ||
| }, [currentModule, page]); | ||
| }, [currentModule, page, timeFactor]); | ||
|
|
||
| const addProductionTrace = (previousConcentration: number) => { | ||
| const traces = productOverTimeTraces; | ||
|
|
@@ -447,7 +455,6 @@ function App() { | |
| const handleStartExperiment = () => { | ||
| simulariumController.pause(); | ||
| totalReset(); | ||
| setTimeFactor(LiveSimulationData.DEFAULT_TIME_FACTOR); | ||
| setPage(page + 1); | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,8 +3,9 @@ import React, { useContext, useEffect } from "react"; | |
| import Slider from "./shared/Slider"; | ||
| import { BG_DARK, LIGHT_GREY } from "../constants/colors"; | ||
| import { SimulariumContext } from "../simulation/context"; | ||
| import { SliderSingleProps } from "antd"; | ||
| import { InputNumber, SliderSingleProps } from "antd"; | ||
| import { zStacking } from "../constants/z-stacking"; | ||
| import { Module } from "../types"; | ||
|
|
||
| interface AdminUIProps { | ||
| totalPages: number; | ||
|
|
@@ -72,18 +73,15 @@ const AdminUI: React.FC<AdminUIProps> = ({ | |
| name="time factor (ns)" | ||
| /> | ||
| <h4>Module number</h4> | ||
| <Slider | ||
| <InputNumber | ||
| min={1} | ||
| max={totalNumberOfModules} | ||
| step={1} | ||
| initialValue={module} | ||
| onChange={(_, value): void => { | ||
| setModule(value); | ||
| value={Number(module)} | ||
| onChange={(value): void => { | ||
| setModule(value as Module); | ||
| }} | ||
| overrideValue={module} | ||
| marks={moduleMarks} | ||
| disabled={false} | ||
| name="time factor (ns)" | ||
| /> | ||
| </div> | ||
| <div style={{ padding: 12 }}> | ||
|
|
@@ -94,6 +92,7 @@ const AdminUI: React.FC<AdminUIProps> = ({ | |
| max={100} | ||
| step={1} | ||
| initialValue={timeFactor} | ||
| overrideValue={timeFactor} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, it's basically "value". it's because Slider itself is a wrapper on the Antd component that already stores it's own value on update |
||
| onChange={(_, value) => { | ||
| setTimeFactor(value); | ||
| }} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,18 +62,21 @@ const ConcentrationSlider: React.FC<SliderProps> = ({ | |
| }) => { | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| const disabledNumbers = [0]; | ||
|
|
||
| const stepSize = useRef(0); | ||
|
||
| const marks = useMemo(() => { | ||
| stepSize.current = (max - min) / 5; | ||
| const marks: SliderSingleProps["marks"] = {}; | ||
| for (let index = min; index <= max; index = index + 2) { | ||
| for (let index = min; index <= max; index = index + stepSize.current) { | ||
| marks[index] = { | ||
| label: ( | ||
| <Mark | ||
| index={index} | ||
| disabledNumbers={disabledNumbers} | ||
| onMouseUp={() => | ||
| onChangeComplete && onChangeComplete(name, index) | ||
| } | ||
| onMouseUp={() => { | ||
| if (onChangeComplete) { | ||
| onChangeComplete(name, index); | ||
| } | ||
| }} | ||
meganrm marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /> | ||
| ), | ||
| }; | ||
|
|
@@ -87,7 +90,7 @@ const ConcentrationSlider: React.FC<SliderProps> = ({ | |
| name={name} | ||
| min={min} | ||
| max={max} | ||
| step={2} | ||
| step={stepSize.current} | ||
|
||
| onChange={onChange} | ||
| onChangeComplete={onChangeComplete} | ||
| marks={marks} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| import React, { useState } from "react"; | ||
| import React, { useContext, useEffect, useState } from "react"; | ||
| import { valueType } from "antd/es/statistic/utils"; | ||
| import { Flex } from "antd"; | ||
|
|
||
|
|
@@ -8,6 +8,7 @@ import InputNumber from "../shared/InputNumber"; | |
| import { FormState } from "./types"; | ||
| import styles from "./popup.module.css"; | ||
| import { MICRO } from "../../constants"; | ||
| import { SimulariumContext } from "../../simulation/context"; | ||
|
|
||
| interface KdQuestionProps { | ||
| kd: number; | ||
|
|
@@ -18,6 +19,41 @@ const KdQuestion: React.FC<KdQuestionProps> = ({ kd, canAnswer }) => { | |
| const [selectedAnswer, setSelectedAnswer] = useState<number | null>(null); | ||
| const [formState, setFormState] = useState(FormState.Clear); | ||
|
|
||
| const { module } = useContext(SimulariumContext); | ||
|
|
||
| useEffect(() => { | ||
| setSelectedAnswer(null); | ||
| setFormState(FormState.Clear); | ||
| }, [module]); | ||
|
|
||
| const getSuccessMessage = (selectedAnswer: number) => { | ||
| if (selectedAnswer < 5) { | ||
| return ( | ||
|
Comment on lines
+29
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. optional: function could live outside component body |
||
| <> | ||
| {selectedAnswer} {MICRO}M is considered a{" "} | ||
| <strong> | ||
| low K<sub>d</sub> | ||
| </strong> | ||
| , which means A and B have a <strong>high affinity</strong>{" "} | ||
| for one another because it takes a low amount of B to create | ||
| the complex. | ||
| </> | ||
| ); | ||
| } else { | ||
| return ( | ||
| <> | ||
| {selectedAnswer} {MICRO}M is considered a{" "} | ||
| <strong> | ||
| high K<sub>d</sub> | ||
| </strong> | ||
| , which means A and C have a <strong>low affinity</strong>{" "} | ||
| for one another because it takes a lot of C to create the | ||
| complex. | ||
| </> | ||
| ); | ||
| } | ||
| }; | ||
|
|
||
| const handleAnswerSelection = (answer: valueType | null) => { | ||
| setSelectedAnswer(Number(answer)); | ||
|
|
||
|
|
@@ -77,17 +113,7 @@ const KdQuestion: React.FC<KdQuestionProps> = ({ kd, canAnswer }) => { | |
| title="What is the binding affinity?" | ||
| formContent={formContent} | ||
| onSubmit={handleSubmit} | ||
| successMessage={ | ||
| <> | ||
| {selectedAnswer} {MICRO}M is considered a{" "} | ||
| <strong> | ||
| low K<sub>d</sub> | ||
| </strong> | ||
| , which means A and B have a{" "} | ||
| <strong>high affinity</strong> for one another because | ||
| it takes a low amount of B to create the complex. | ||
| </> | ||
| } | ||
| successMessage={getSuccessMessage(selectedAnswer!)} | ||
| failureMessage="Visit the “Learn how to derive Kd” button above, then use the Equilibrium concentration plot to answer." | ||
| formState={formState} | ||
| id="Kd Value" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In an ideal world, what would the API for this look like? Something like
update()oradvance()for simulations?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the way I was doing it before may be more ideal (ie "give me the next time step"). the issue was because of the async nature of the connection between the app and the viewer, sometimes what the app thought was the next frame, the viewer thought was the current frame, so it wouldn't update.
It might be nice to be able to pass something like "++1" to gotoTime meaning "whatever you think is the next frame, give it to me".