Conversation
…into simulate-icm
james-isbister
left a comment
There was a problem hiding this comment.
Thanks @AurelienJaquier , looks good!
I'll think through some alternatives for how we could approach the conductances for each selected ion channel, and the recording of any parameter for the selected ion channels. And then we can discuss soon!
| group=BlockGroup.STIMULI_RECORDINGS, | ||
| group_order=0, | ||
| ) | ||
| # can we have recording union depending on what model we choose? |
There was a problem hiding this comment.
This seems like an extension of the: ui_element: entity_property_dropdown
At the moment we have the example:
node_set: NodeSetType = Field(
ui_element="entity_property_dropdown",
entity_type=EntityType.CIRCUIT,
property=CircuitPropertyType.NODE_SET,
title="Node Set",
description="Name of the node set to use.",
min_length=1,
)
Which specifies that the dropdown should display values returned by the mapped_circuit_properties endpoint - specifically the values in the list under the key CircuitPropertyType.NODE_SET
I think we could have a RecordVariable(Block) (or another name), which has a parameter recorded_variable with:
ui_element="entity_property_dropdown",
entity_type=EntityType.ION_CHANNEL_MODEL,
property=CircuitPropertyType.RECORDABLE_VARIABLES,
In the circuit simulation / extraction case there is only one circuit though so the dropdown only shows variables for one circuit
But in this case there will be multiple ion channels (selected somewhere in the configuration) - so we will have to think about how it is represented in the schema that the dropdown for recorded_variable should display values for all the ion channels (grouped by ion channel).
For now though, I think we could start by making a mapped_ion_channel_model_properties endpoint as we have for circuits, and we can go from there? what do you think?
There was a problem hiding this comment.
Good idea. I have implemented a mapped_ion_channel_properties_endpoint in my latest commit.
Here are some things that we should keep in the back of our minds: each ion channel can have multiple variables (although most of the time they will only have one), and we might have ion channels models with common variables (e.g. if we have two calcium mixing mechanisms, we would have calcium concentration as an available recording for both).
Also, we should always have voltage recording available in case the user wants to do some current clamp experiment.
Also, is the dropdown already somewhere in the platform? I would like to see what it looks like in the UI if possible.
There was a problem hiding this comment.
Nice!
Just to be sure, for the common variables, is there a single value that are we recording (that is shared between the two mechanisms) or two values which are later combined into a third value (which we also might record)?
Atm we have a simple dropdown in the PredefinedNeuronSet. But on top of that we could add some sort of grouping by ion channel
There was a problem hiding this comment.
For the common variable, it would be a single value that is shared between the two mechanisms. The only case right now would be the calcium concentration that can be modified by several mechanisms.
I like the grouping by ion channel, because it would make it very explicit from what ion channel the variable is recorded from.
| } | ||
|
|
||
| class Initialize(Block): | ||
| ion_channel_models: list[IonChannelModelFromID] = Field( |
There was a problem hiding this comment.
One approach would be to have a block_dictionary i.e similar to what we have for Stimuli and NeuronSets in simulation.
So there would be an "Add Ion Channel Model" button under a heading say "Ion Channel Models"
When the user presses this button, the a new block is added to the dictionary with two parameters:
- ion_channel_model_entity - clicking on this launches a selection - similar to what we have for the selection of the ion channel recordings in the current ion channel build
- conductance
There was a problem hiding this comment.
I have added the block dictionary.
We will have edge cases of ion channel models with no conductances. In which case, I think we could have the conductance field being greyed out. I assume this will be handled by the UI, and I don't have to care for it in obi-one, correct?
|
What is lacking in this PR right now:
|
|
I tried implementing the recording union. Would that do the trick @james-isbister or is this implementation still missing something? |
…into simulate-icm
…into simulate-icm
| "conductance_name__isnull": False, | ||
| }, | ||
| }, | ||
| ) |
There was a problem hiding this comment.
I wonder can't we use normal pydantic schemas? It is the first time I see this kind of schema declaration and frankly it's far from intuitive.
There was a problem hiding this comment.
Is there is a better way to specify an entity filter? This was suggested by @bilalesi as a filter which can easily be applied in the frontend, but ideally I would like a way of specifying a filter which is usable both in obi-one through entitysdk and the frontend
There was a problem hiding this comment.
- the suggested filter is the same as entitycore, and it should align strictly with the terminology and naming conventions defined by entitycore, it's not something specific to the FE
- in this case, we are specifying the filter (key: value) that should be used in the
configuration-editorand it must be exactly what the ui element is expecting to use it and render the expected data and not the type so i don't see why using pydantic schema here, may be i'm missing smthg ? - for the properties used
model_selector_entity_typeandmodel_selector_property_filter, wouldn't be better to have one single dictionary defining the query shape as:
entity_query or model_query = {
type: xxxxx,
filters: {
conductance_name__isnull: xxxx,
yyyy: aaaa
}There was a problem hiding this comment.
I followed your suggestion in my latest commit @bilalesi . Does it look ok to you?
| if isinstance(circuit, Circuit): | ||
| L.info("initialize.circuit is a Circuit instance.") | ||
| self._circuit = self.config.initialize.circuit | ||
| self._sonata_config["network"] = self.config.initialize.circuit.path | ||
| self._circuit = circuit | ||
| self._sonata_config["network"] = circuit.path | ||
|
|
||
| elif isinstance( | ||
| self.config.initialize.circuit, | ||
| (CircuitFromID, MEModelFromID, MEModelWithSynapsesCircuitFromID), | ||
| circuit, | ||
| ( | ||
| CircuitFromID, | ||
| MEModelFromID, | ||
| MEModelWithSynapsesCircuitFromID, | ||
| FakeCircuitFromIonChannelModels, | ||
| ), |
There was a problem hiding this comment.
I’ve noticed several conditional checks (e.g., configuration value checks, isinstance of types) that route execution into different flows. This approach makes the code difficult to follow and reason about, as it’s not clear what will be executed for any given task without tracing multiple branches.
A more maintainable design would define a dedicated task for each simulation type, with each task encapsulating all logic and responsibilities specific to that simulation type. This would improve readability, separation of concerns, and testability.
In its current form, the code is hard to maintain and will likely become increasingly difficult to extend or modify safely over time.
There was a problem hiding this comment.
Yes, thank you for highlighting this - these types of comments are very useful to us so please keep them coming. We integrated a lot of your suggestions about separattion of concerns last year, which has improved the code base a lot. Sometimes there is just a lag given how many other things we're working on
I agree that we need to improve readability, separation of concerns and testability - and this if statement logic needs to be majorly simplified or indeed removed as you suggest.
I'm not yet totally convinced about separating into separate tasks for each config but I'm totally open to it - I just need to think a bit more about it.
I'd be very happy to discuss this further at some point once I've had time to think about it.
| else: | ||
| circuit_config_path = dest_dir / "circuit_config.json" | ||
|
|
||
| return MEModelCircuit(name="single_cell", path=str(circuit_config_path)) |
There was a problem hiding this comment.
Having staging logic inside config classes feels out of place. Staging is a task-level concern, while config classes should just hold and provide configuration data. Mixing the two blurs responsibilities and can make the code harder to maintain. It’s usually better to keep config focused on data, and handle staging or other task-specific logic elsewhere.
There was a problem hiding this comment.
Good point.
I was trying to stay close to the logic used in the from_id classes.
Maybe we can keep this logic for now (here and in from_id classes), and think about how to disentangle staging logic from config classes in another PR after the webinar
There was a problem hiding this comment.
Yeah, fine with me. I just left some comments here an there with things I noticed.
…into simulate-icm
|
I think all the comments have been answered. Is this good to be merged or do you have more comments @james-isbister @eleftherioszisis @bilalesi ? |
|
Given the extent of the PR I cannot give my approval without any tests. Maybe someone that is more familiar with the correctness of the code or has tested the feature could approve. |
….config.ion_channel_models
There was a problem hiding this comment.
Very nice work, thank you.
I just applied some minor renaming:
- config.ion_channel_model(s).py
- Removed "Fake"
@AurelienJaquier Please give it a quick test with @bilalesi core-web-app branch locally. If it works as expected we can merge this and make a release
|
How am I supposed to test it exactly? |
|
the simulation is not yet done, I will notify you when the branch preview link will be ready |
|
I tested with bilal's core web app branch and everything is good. |
This is not complete yet.
This is missing
IonChannelModelStimulusUnionandIonChannelModelRecordingUnionimplementation. Also theentitysdkimplementation is not done yet.