EStiMapp: A practical tool for mapping clinical symptoms evoked by electrical stimulation in intracranial EEG for epilepsy surgery.
The 7 matches
- [1] § Methods › Workflow using the graphical user interface ↔ estimapp.py, lines 1–56 · score 0.75 · implanted electrodes, electrode scheme, electrical stimulation, duration, Optional, channel
- [2] § Results › The graphical user interface ↔ estimapp.py, lines 1–56 · score 0.69 · stimulated electrode pair, implanted electrodes, electrode scheme, optionally, rendering, PLY
- [3] § Results › Categories of evoked clinical symptoms ↔ functions/estimapp_create_stimulations_overview.py, lines 32–143 · score 0.61 · affective, auditory, vestibular, autonomic, discharge, doubt
- [4] § Results › Co-designing the graphical user interface ↔ functions/estimapp_create_stimulations_overview.py, lines 32–143 · score 0.60 · elementary motor, complex motor, discharge, doubt, somatosensory, seizure
- [5] § Results › Co-designing the graphical user interface ↔ functions/estimapp_generate_3d_plot.py, lines 29–150 · score 0.60 · elementary motor, complex motor, discharge, doubt, somatosensory, seizure
- [6] § Results › Categories of evoked clinical symptoms ↔ functions/estimapp_generate_3d_plot.py, lines 29–150 · score 0.58 · auditory, vestibular, autonomic, discharge, doubt, somatosensory
- [7] § Methods › Workflow using the graphical user interface ↔ estimapp.py, lines 69–100 · score 0.56 · medical device, UMC Utrecht, Render, installed, committee, hosted
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 482 lines · 21 KB · no license · 3 matches
- """
- Created on Mon May 26, 2025
- @author: Irene Heijink
- Run this dash app to host the webpage at localhost:8050/
- The app visualises the result of electrical stimulation during intracranial monitoring.
- Input:
- Electrodes overview: an excel file with the patient specific electrode scheme.
- Annotations: one or multiple csv files with the EEG annotations during stimulation.
- The categories of clinical symptoms should be annotated using the correct abbreviations,
- please find the user instructions. Column names: ['Start from:', 'Time End', 'Duration', 'Category', 'Comment']
- Optional, required for 3D rendering:
- Electrode coordinates: an excel file with the patient specific electrode names,
- number of channels, and entry and target coordinates of the implanted electrodes.
- Column names: ['electrode_name', 'nr_of_channels', 'entry_x', 'entry_y', 'entry_z', 'target_x', 'target_y', 'target_z']
- PLY brain rendering: a PLY file with the patient specific 3D brain rendering.
- Can be saved via EpiNav or other visualization software.
- Example data is available for all input data at DataVerseNL.
- Output:
- 2D figure: the projection of clinical symptom categories on the electrode overview.
- Table: category of clinical symptoms, free text annotations, and stimulation type
- sorted per stimulated electrode pair.
- 3D figure: the projection of clinical symptom categories on the implanted electrodes
- and brain rendering in 3D. The end-user can rotate and translate the figure and
- change the opacity.
- """
- import dash
- from dash import html, dcc, Input, Output, State, dash_table
- import dash_mantine_components as dmc
- import base64
- import io
- import pandas as pd
- import trimesh
- import csv
- import os
- from functions.estimapp_process_annotations import estimapp_process_annotations
- from functions.estimapp_generate_plot import estimapp_generate_plot
- from functions.estimapp_generate_table import estimapp_generate_table
- from functions.estimapp_generate_3d_plot import estimapp_generate_3d_plot
- from functions.estimapp_create_upload_button import estimapp_create_upload_button
- app = dash.Dash(__name__, suppress_callback_exceptions=True)
- server = app.server
- app.title = "EStiMapp"
- # Layouts
- app.layout = dmc.MantineProvider(
- children=html.Div([
- dcc.Location(id="main-url", refresh=False),
- dcc.Store(id="session-data", storage_type='memory'),
- html.Div(id="warning-alert"),
- html.Div(id="page-content")],
- style={"backgroundColor":"rgb(243,250,255)"}
- )
- )
- def layout_home():
- return dmc.Container(
- dmc.Stack([
- dmc.Title("EStiMapp", order=2),
- dmc.Text("A practical tool for mapping clinical symptoms evoked by electrical stimulation in intracranial EEG for epilepsy surgery",
- fw=500, ta="center", w="450px"),
- html.Br(),
- html.Br(),
- dmc.TextInput(
- id="name-input",
- label="Enter patient name or ID (optional)",
- placeholder="e.g., John Doe",
- required=False,
- style={"marginBottom": 20}),
- estimapp_create_upload_button("upload-electrodes", "upload-overview-electrodes", "Upload overview electrodes",
- "xlsx file containing electrode names and ordering. Example file: ","https://doi.org/10.34894/KMT3VI"),
- estimapp_create_upload_button("upload-annotations", "upload-overview-annotations", "Upload overview annotations",
- "csv file(s) containing annotations from iEEG software. Multiple files can be uploaded at once. \n For Micromed users: these files can be compiled automatically from a Micromed TRC using the Export Notes option in Micromed. Example files: ","https://doi.org/10.34894/KMT3VI", multiple=True),
- dmc.Text("Optional, required for 3D rendering:", fw=500),
- estimapp_create_upload_button("upload-coordinates", "upload-electrode-coordinates", "Upload electrode coordinates",
- "xlsx file containing electrode names, number of contacts, and entry and target coordinates. Example file: ","https://doi.org/10.34894/KMT3VI"),
- estimapp_create_upload_button("upload-ply", "upload-ply-rendering", "Upload PLY brain rendering",
- "ply file containing 3D brain rendering. Example file: ","https://doi.org/10.34894/KMT3VI"),
- html.Br(),
- dmc.Button("Create EStiMapp", id="submit-btn"),
- dmc.Text("EStiMapp is a visualization tool that was evaluated by the CE-committee of the UMC Utrecht and was labeled not to be a medical device. The use or reliance of any information contained on the site is solely at your own risk. Data privacy cannot be guaranteed when using the app hosted on Render. For patient data, the locally installed version is recommended.",
- fw=300, ta="center", w="450px"),
- html.Div(id="warning-alert"),
- ], align="center", gap="sm"),size="sm")
- def layout_result():
- print("layout_result is called")
- return html.Div([
- html.H3("Result Page", style={'font-family':'verdana'}),
- html.H4(id="result-name", style={'font-family':'verdana'}),
- dcc.Tabs(id="result-tabs", value="tab-2d", children=[
- dcc.Tab(label="2D visualization", value="tab-2d",
- style={'background':'white', 'color':'black', 'font-family':'verdana'},
- selected_style={'background':'blue', 'color':'white', 'font-family':'verdana'}),
- dcc.Tab(label="3D visualization", value="tab-3d",
- style={'background':'white', 'color': 'black', 'font-family': 'verdana'},
- selected_style={'background':'blue', 'color':'white', 'font-family':'verdana'})]),
- html.Div(id="result-tab-content"),
- html.Br(),
- dcc.Store(id="processed-annotations"),
- dcc.Store(id="edited-processed-annotations"),
- html.Div(id="result-table") # table is outside tab
- ])
- # Show uploaded file names
- @app.callback(
- Output("upload-overview-electrodes", "children"),
- Input("upload-electrodes", "filename")
- )
- def update_electrodes(filename):
- return f"Selected: {filename}" if filename else ""
- @app.callback(
- Output("upload-overview-annotations", "children"),
- Input("upload-annotations", "filename")
- )
- def update_annotations(filenames):
- if filenames:
- return "Selected: " + ", ".join(filenames)
- return ""
- @app.callback(
- Output("upload-electrode-coordinates", "children"),
- Input("upload-coordinates", "filename")
- )
- def update_coordinates(filename):
- if filename:
- return f"Selected: {filename}" if filename else ""
- return ""
- @app.callback(
- Output("upload-ply-rendering", "children"),
- Input("upload-ply", "filename")
- )
- def update_ply(filename):
- if filename:
- return f"Selected: {filename}" if filename else ""
- return ""
- # Result page
- def show_result(data):
- print("⚡ show_result called")
- name = data.get("name", "")
- electrodes = data.get("electrodes")
- annotations = data.get("annotations")
- coordinates = data.get("coordinates")
- ply = data.get("ply")
- def decode_excel(content):
- _, content_string = content.split(',')
- decoded = base64.b64decode(content_string)
- xls = pd.ExcelFile(io.BytesIO(decoded))
- sheet_names = xls.sheet_names
- print("sheet names", sheet_names)
- if len(sheet_names) > 1 and "sjabloon" in sheet_names:
- sheet_name = "sjabloon"
- elif len(sheet_names) > 1 and "Sheet 1" in sheet_names:
- sheet_name = "Sheet 1"
- elif len(sheet_names) > 1 and "Sheet1" in sheet_names:
- sheet_name = "Sheet1"
- elif len(sheet_names) > 1 and "elektroden" in sheet_names:
- sheet_name = "elektroden"
- elif len(sheet_names) > 1 and "Elektroden" in sheet_names:
- sheet_name = "Elektroden"
- else:
- sheet_name = 0 # Default to read first worksheet of excel file
- decoded_excel = pd.read_excel(io.BytesIO(decoded), sheet_name=sheet_name, keep_default_na=False)
- return decoded_excel
- # def decode_annotations(content):
- # _, content_string = content.split(',')
- # decoded = base64.b64decode(content_string)
- # annotations = pd.read_csv(io.BytesIO(decoded),
- # encoding="latin1", # handles special characters like °, é, etc.
- # sep="\t", # tab-delimited
- # engine="python", # more forgiving parser
- # quoting=csv.QUOTE_NONE # <-- ignore quotes completely
- # )
- # return annotations
- def decode_annotations(content):
- content_type, content_string = content.split(',')
- decoded = base64.b64decode(content_string)
- if 'csv' in content_type or 'text' in content_type:
- annotations = pd.read_csv(io.BytesIO(decoded),
- encoding="latin1",
- sep="\t",
- engine="python",
- quoting=csv.QUOTE_NONE
- )
- elif 'excel' in content_type or 'spreadsheetml' in content_type or 'xls' in content_type:
- #xls = pd.ExcelFile(io.BytesIO(decoded))
- #sheet_name = xls.sheet_names[0] # take first sheet
- annotations = pd.read_excel(io.BytesIO(decoded), keep_default_na=False)
- print('excel file is decoded')
- else:
- raise ValueError(f"Unsupported file type: {content_type}")
- return annotations
- def decode_ply(content):
- _, content_string = content.split(',')
- decoded = base64.b64decode(content_string)
- mesh = trimesh.load(io.BytesIO(decoded), file_type='ply')
- return mesh
- print("decode annotations, file type:", type(annotations), type(annotations[0])) # <class 'list'> <class 'str'>
- annotations_df = pd.DataFrame()
- for file in annotations:
- decoded_annotations = decode_annotations(file)
- print("decoded annotations type", type(decoded_annotations), decoded_annotations.shape)
- print("add annotations to dataframe")
- annotations_df = pd.concat([annotations_df, decoded_annotations], ignore_index=True)
- print("decoded annotations", type(annotations_df), "size df", annotations_df.shape, annotations_df['Comment']) #decoded annotations <class 'list'> <class 'pandas.core.frame.DataFrame'>
- print('decoding electrodes')
- decoded_electrodes = decode_excel(electrodes) # df
- stimulations_df, processed_annotations, categories_dict = estimapp_process_annotations(annotations_df)
- print("stimulations_df", stimulations_df.head())
- print("processed_annotations:", processed_annotations)
- # 3D
- coordinates_df = decode_excel(coordinates) if data.get("coordinates") else None
- mesh = decode_ply(ply) if data.get("ply") else None
- return name, decoded_electrodes, processed_annotations, categories_dict, coordinates_df, mesh
- # Page routing
- @app.callback(
- Output("page-content", "children"),
- Input("main-url", "pathname")
- )
- def display_page(pathname):
- print("📍 Navigated to pathname:", pathname)
- if pathname == "/result":
- return layout_result()
- else:
- return layout_home()
- # Handle submit
- @app.callback(
- Output("main-url", "pathname"),
- Output("session-data", "data"),
- Output("warning-alert", "children"),
- Input("submit-btn", "n_clicks"),
- State("name-input", "value"),
- State("upload-electrodes", "contents"),
- State("upload-annotations", "contents"),
- State("upload-coordinates", "contents"),
- State("upload-ply", "contents"),
- prevent_initial_call=True
- )
- def handle_submit(n_clicks, name, electrodes, annotations, coordinates, ply):
- if n_clicks is None:
- raise dash.exceptions.PreventUpdate
- print("🚨 Submit clicked")
- print(" ↳ Electrodes content present:", isinstance(electrodes, str))
- print(" ↳ Annotations content list:", isinstance(annotations, list), "Length:", len(annotations) if annotations else 0)
- print(" ↳ Electrode coordinates content present:", isinstance(coordinates, str))
- print(" ↳ PLY content present:", isinstance(ply, str)) # string?
- missing = []
- if not electrodes or not isinstance(electrodes, str):
- missing.append("Excel electrodes")
- if not annotations or not isinstance(annotations, list) or len(annotations) == 0:
- missing.append("Annotations")
- if missing:
- return dash.no_update, dash.no_update, dmc.Alert(
- title="Missing Information",
- color="red",
- radius="md",
- children="Please provide: " + ", ".join(missing)
- )
- data = {
- "name": name or "",
- "electrodes": electrodes,
- "annotations": annotations,
- "coordinates": coordinates,
- "ply": ply # Default value if missing is None
- }
- return "/result", data, None # None is default value for Alert missing data
- # Result Display
- @app.callback(
- Output("result-name", "children"),
- Output("result-table", "children"),
- Output("result-tab-content", "children"),
- Output("processed-annotations", "data"),
- Input("result-tabs", "value"),
- Input("session-data", "data"),
- )
- def update_result_tabs(tab, data):
- if not data:
- return "No data submitted", html.Div(), html.Div(), html.Div()
- name, decoded_electrodes, processed_annotations, categories_dict, coordinates_df, mesh = show_result(data)
- table, table_columns = estimapp_generate_table(processed_annotations)
- dropdown_individual_cat = set(categories_dict.values())
- dropdown_multiple_cat = set(table["Category"].unique())
- dropdown_menu = sorted(dropdown_individual_cat | dropdown_multiple_cat) # removes duplicates
- table_section = html.Div([html.Label("Overview of all annotations per stimulation pair ", style={'font-family':'verdana', 'font': 'bold'}),
- html.Div( html.Button("Download table", id="download-table-btn", style={
- "backgroundColor": "white", "border": "2px solid #228be6", "color": "#228be6", "padding": "6px 14px",
- "borderRadius": "6px", "cursor": "pointer", "fontSize": "14px",}),
- style={"display":"flex", "justifyContent":"flex-end", "marginBottom":"10px"}),
- dcc.Download(id="download-table"),
- dash_table.DataTable(id="editable-table", data=table.to_dict("records"),
- #columns=[{"name": col, "id": col} for col in table_columns],
- columns=[{"name": "Electrode 1", "id": "Electrode 1", "editable": False},
- {"name": "Electrode 2", "id": "Electrode 2", "editable": False},
- {"name": "Category", "id": "Category", "editable": True, "presentation": "dropdown"},
- {"name": "Free text", "id": "Free text", "editable": True},
- {"name": "Stim type", "id": "Stim type", "editable": False},
- {"name": "Settings", "id": "Settings", "editable": False},
- ],
- dropdown = {
- "Category": {
- "options": [{"label": v, "value": v} for v in dropdown_menu]
- }
- },
- sort_action="native", # Allow user to sort columns
- filter_action="native", # Optional: Allow column filtering
- filter_options={'case':'insensitive'},
- row_deletable=True,
- editable=True,
- #row_addable=True,
- style_table={"overflowX": "auto"},
- style_cell={"textAlign": "left"},#, "whiteSpace": "pre-line"},
- style_data={"whiteSpace": "normal", "height": "auto"}
- ),
- ])
- if tab == "tab-2d":
- print("Generating figure")
- fig2d = dcc.Graph(id="result-plot-2d", figure = estimapp_generate_plot(decoded_electrodes, processed_annotations))
- return f"{name}" if name else "No name provided", table_section, html.Div([
- html.Div(fig2d,
- style={"width": "auto", "display": "inline-block", "verticalAlign": "top", "margin": "0", "padding": "0", "backgroundColor": "rgba(0,0,0,0)"}),
- html.Img(src='/assets/Legend.png', style={'width': '400px', "margin": "0", "marginBottom": "75px", "padding": "5px", "alignSelf": "flex-end"}) ],
- style={"textAlign": "left", "whiteSpace": "nowrap", "display": "flex", "alignItems": "flex-end", "justifyContent": "flex-start"}), processed_annotations.to_json(date_format="iso", orient="split")
- elif tab == "tab-3d" and mesh:
- fig3d = estimapp_generate_3d_plot(mesh, coordinates_df, processed_annotations)
- return f"{name}" if name else "No name provided", table_section, html.Div([
- html.Div([
- dcc.Graph(id="result-plot-3d", figure=fig3d, clear_on_unhover=True, style={"width":"1200px","height":"800px"}),
- html.Div(id="hover-coords", style={
- "position": "absolute",
- "bottom": "80px",
- "left": "20px",
- "backgroundColor": "rgba(255,255,255,0.85)",
- "padding": "6px 12px",
- "borderRadius": "5px",
- "fontFamily": "monospace",
- "fontSize": "12px",
- "zIndex": "1000",
- "border": "1px solid #ccc",
- "boxShadow": "0px 2px 4px rgba(0,0,0,0.1)"
- }),
- html.Label("Adjust cortex opacity:"),
- dcc.Slider(id="opacity", min=0, max=1, step=0.1, value=0.8, marks={0: "0", 0.5: "0.5", 1: "1"}, updatemode="drag"),
- ], style={"position": "relative", "display": "inline-block", "verticalAlign": "top"}),
- html.Img(src="/assets/Legend.png", style={
- "width": "400px",
- "margin": "0 0 0 20px",
- "padding": "5px",
- "display": "inline-block",
- "verticalAlign": "top"
- })
- ], style={"whiteSpace": "nowrap", "textAlign": "left"}), processed_annotations.to_json(date_format="iso", orient="split")
- else:
- return f"{name}" if name else "No name provided", table_section, html.Div("No PLY data uploaded for 3D visualization.", style={'font-family':'verdana'}), processed_annotations.to_json(date_format="iso", orient="split")
- # Table callbacks
- @app.callback(
- Output("edited-processed-annotations", "data"),
- Input("editable-table", "data")
- )
- def save_edits(data):
- # Store the edited table in JSON format
- return pd.DataFrame(data).to_json(date_format="iso", orient="split")
- @app.callback(
- Output("download-table", "data"),
- Input("download-table-btn", "n_clicks"),
- State("result-name", "children"),
- State("edited-processed-annotations", "data"),
- prevent_initial_call=True
- )
- def download_table(n_clicks, name, processed_annotations_json):
- if not processed_annotations_json:
- raise dash.exceptions.PreventUpdate
- processed_annotations = pd.read_json(processed_annotations_json, orient="split")
- print("download table")
- # return as CSV
- return dcc.send_data_frame(
- processed_annotations.to_csv,
- filename=f"{name}_annotations.csv",
- index=False
- )
- # 3D interaction functions
- @app.callback(
- Output("result-plot-3d", "figure"),
- Input("opacity", "value"),
- State("result-plot-3d", "figure"),
- State("result-plot-3d","relayoutData"),
- prevent_initial_call=True
- )
- def update_opacity(opacity, fig, relayoutData):
- if not fig:
- raise dash.exceptions.PreventUpdate
- # Preserve current camera
- camera = None
- if relayoutData and "scene.camera" in relayoutData:
- camera = relayoutData["scene.camera"]
- # Update mesh opacity
- for trace in fig["data"]:
- if trace["type"] == "mesh3d":
- trace["opacity"] = opacity
- # Reapply preserved camera
- if camera:
- fig["layout"]["scene"]["camera"] = camera
- return fig
- @app.callback(
- Output("hover-coords", "children"),
- Input("result-plot-3d", "hoverData"),
- prevent_initial_call=True
- )
- def display_hover_coordinates(hoverData):
- if not hoverData or "points" not in hoverData:
- return ""
- point = hoverData["points"][0]
- x, y, z = point.get("x"), point.get("y"), point.get("z")
- customdata = point.get("customdata")
- electrode_label = customdata if customdata and len(customdata) > 0 else "N/A"
- return html.Div([
- html.Div(f"Electrode: {electrode_label}"),
- html.Div(f"x: {x:.2f}, y: {y:.2f}, z: {z:.2f}")
- ])
- # To run app on server:
- if __name__ == "__main__":
- app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8050)), debug=False)
- #app.run(debug=False)
estimapp.py at commit 1299b34, no license · at the source
Overview
- Department of Neurology and Neurosurgery, University Medical Center Utrecht Brain Center, University Medical Center Utrecht, Full Member of European Reference Network EpiCARE, P.O. box 85500, 3508, GA, Utrecht, the Netherlands
- Stichting Epilepsie Instellingen Nederland (SEIN), P.O. box 540, 2130, AM, Hoofddorp, the Netherlands
Abstract
Objective: Electrical stimulation of intracranial electrodes can map the patient's specific functional regions and seizure related symptoms. In our clinical practice, evoked functional symptoms and electrographic responses are manually annotated and visualized in a schematic electrode overview: an error-prone and time-consuming process. We here present an open-source graphical user interface (GUI) that standardizes the workflow and automatizes the visualization of intracranial EEG (iEEG) electrical stimulation results.
Methods: We defined categories of evoked clinical symptoms based on a literature study and consensus session. A co-design team participated in brainstorm sessions to set the requirements of the GUI. We built the GUI and tested its usability with qualitative and quantitative assessments (System Usability Scales (SUS) questionnaires).
Results: The workflow included standardized annotation of categories of evoked clinical symptoms in the iEEG software. The GUI visualized these evoked clinical symptoms in a 2D schematic overview, a 3D visualization of the brain with locations of evoked symptoms, and showed additional annotations per stimulated electrodes in a table. A mean SUS score of 82.3 (SD 9.2) was reached, which is considered excellent.
Conclusions: We present an in-house developed workflow and graphical user interface (GUI) to categorize and directly visualize evoked clinical symptoms resulting from electrical stimulation on intracranial electrodes.
Significance: Our open-source GUI facilitates standardization of the intracranial stimulation workflow and directly enables straightforward and uniform interpretation of evoked clinical symptoms.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 7 matches between paragraphs and lines of code.
UMCU-EpiLAB/umcuEpi_estimapp
1299b341ada0d87aed6255a87c7b4b56b91aa91a, 26 May 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
15 files
- estimapp.py, Python, 482 lines, 3 matches
- functions/
estimapp_create_stimulat , Python, 143 lines, 2 matchesions_overview.py - functions/
estimapp_create_upload_b , Python, 67 linesutton.py - functions/
estimapp_define_stimulat , Python, 29 linesion_period.py - functions/
estimapp_generate_3d_plo , Python, 150 lines, 2 matchest.py - functions/
estimapp_generate_plot.p , Python, 153 linesy - functions/
estimapp_generate_table. , Python, 52 linespy - functions/
estimapp_interpolate_ele , Python, 50 linesctrodes.py - functions/
estimapp_localize_annota , Python, 27 linested_categories.py - functions/
estimapp_localize_electr , Python, 52 linesode_positions.py - functions/
estimapp_merge_stimpairs , Python, 54 lines.py - functions/
estimapp_open_icon.py , Python, 28 lines - functions/
estimapp_process_annotat , Python, 72 linesions.py - functions/
estimapp_rearrange_elect , Python, 54 linesrodescheme.py - README.md, Text, 2 lines
estimapp.onrender.com
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 14 scripts, each with its path and the digest of its content;
- 7 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Data and code availability statement
The source code and web application are publicly available on GitHub (https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, pages, dates, 9 authors, 7 keywords, 4 funders, 45 references.
Cite
This paper
Heijink, I. B., Jelsma, S. B., van der Salm, S. M., van Klink, N. E., Ferrier, C. H., Hoogteijling, S., van Asch, C. J., van Blooijs, D., & Zijlmans, M. (2026). EStiMapp: A practical tool for mapping clinical symptoms evoked by electrical stimulation in intracranial EEG for epilepsy surgery. Clinical neurophysiology practice, 11, 492-502. https://
BibTeX
@article{heijink2026esti
author = {Heijink, Irene B and Jelsma, Susanne B and van der Salm, Sandra MA and van Klink, Nicole EC and Ferrier, Cyrille H and Hoogteijling, Sem and van Asch, Charlotte JJ and van Blooijs, Dorien and Zijlmans, Maeike},
title = {{EStiMapp: A practical tool for mapping clinical symptoms evoked by electrical stimulation in intracranial EEG for epilepsy surgery}},
journal = {Clinical neurophysiology practice},
year = {2026},
month = jun,
volume = {11},
pages = {492--502},
publisher = {Elsevier},
issn = {2467-981X},
doi = {10.1016/
url = {https://
pmid = {42440465},
pmcid = {PMC13333301}
}
RIS
TY - JOUR
AU - Heijink, Irene B
AU - Jelsma, Susanne B
AU - van der Salm, Sandra MA
AU - van Klink, Nicole EC
AU - Ferrier, Cyrille H
AU - Hoogteijling, Sem
AU - van Asch, Charlotte JJ
AU - van Blooijs, Dorien
AU - Zijlmans, Maeike
TI - EStiMapp: A practical tool for mapping clinical symptoms evoked by electrical stimulation in intracranial EEG for epilepsy surgery
T2 - Clinical neurophysiology practice
J2 - Clin Neurophysiol Pract
PY - 2026
DA - 2026/
VL - 11
SP - 492
EP - 502
SN - 2467-981X
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "EStiMapp: A practical tool for mapping clinical symptoms evoked by electrical stimulation in intracranial EEG for epilepsy surgery",
"container-title": "Clinical neurophysiology practice",
"author": [
{
"family": "Heijink",
"given": "Irene B"
},
{
"family": "Jelsma",
"given": "Susanne B"
},
{
"family": "van der Salm",
"given": "Sandra MA"
},
{
"family": "van Klink",
"given": "Nicole EC"
},
{
"family": "Ferrier",
"given": "Cyrille H"
},
{
"family": "Hoogteijling",
"given": "Sem"
},
{
"family": "van Asch",
"given": "Charlotte JJ"
},
{
"family": "van Blooijs",
"given": "Dorien"
},
{
"family": "Zijlmans",
"given": "Maeike"
}
],
"container-title-short":
"volume": "11",
"page": "492-502",
"DOI": "10.1016/
"PMID": "42440465",
"PMCID": "PMC13333301",
"ISSN": "2467-981X",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
12
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.3389/fncir.2026.1814667 [code]
- A modular and flexible pipeline for intraoperative electrode reconstruction and localization in patients with brain lesions.Journal: Frontiers in neural circuitsIn common: pandas, NumPy, intracranial EEG (iEEG / ECoG / SEEG), epilepsy, 3 references
- [2] doi:10.1002/epi4.70311 [code]
- Bridging computational and clinical strategies for presurgical identification of epileptogenic networks.Journal: Epilepsia openIn common: NumPy, intracranial EEG (iEEG / ECoG / SEEG), epilepsy, clinical / translational, 2 references
- [3] doi:10.1002/mco2.70931 [code]
- Unveiling Functional Architecture of Human Thalamus: AStereoelectroencephalog
raphy Study. Journal: MedCommIn common: epilepsy, 3 references - [4] doi:10.1093/braincomms/fcag187 [code]
- 50 Hz Cortical stimulation increases interictal epileptiform discharges at the seizure onset zone.Journal: Brain communicationsIn common: intracranial EEG (iEEG / ECoG / SEEG), epilepsy, clinical / translational, 2 references
- [5] doi:10.1002/brb3.71507 [code]
- Anti-Seizure Medications Alter Functional and Effective Connectivity as Measured With Intracranial Electroencephalography.Journal: Brain and behaviorIn common: intracranial EEG (iEEG / ECoG / SEEG), epilepsy, 2 references
- [6] doi:10.1162/imag.a.1276 [code]
- High-resolution whole-brain magnetic resonance spectroscopic imaging in youth at risk for psychosis.Journal: Imaging neuroscience (Cambridge, Mass.)In common: Plotly, Pillow, pandas, 1 other tool, clinical / translational
- [7] doi:10.1186/s12880-026-02481-2 [code]
- Deep learning-based neuroanatomical profiling reveals population-specific brain changes in multiple sclerosis: a large-scale Middle Eastern study.Journal: BMC medical imagingIn common: Plotly, Pillow, pandas, 1 other tool, clinical / translational
- [8] doi:10.1093/braincomms/fcag176 [code]
- Tau topography subtypes account for clinical heterogeneity and longitudinal trajectories in early-onset Alzheimer's disease.Journal: Brain communicationsIn common: Plotly, Pillow, pandas, 1 other tool, clinical / translational
- [9] doi:10.1371/journal.pone.0348866 [code]
- Using deep learning to identify inherited retinal diseases based on wide-field retinal imaging data.Journal: PloS oneIn common: Plotly, Pillow, pandas, 1 other tool, clinical / translational
- [10] doi:10.34133/csbj.0042 [code]
- Using Steady-State Visual Evoked Potentials to Characterize Wide-Ranging Retinopathy Linked to &
lt;i& gt;CRB1& lt;/ i& gt;: Implications for Clinical Trials. Journal: Computational and structural biotechnology journalIn common: Plotly, Pillow, pandas, 1 other tool, clinical / translational
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 2 repositories of the authors' code, each at its verified commit and with its license, 14 scripts, and 7 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:8801dc59ce19ba8d…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
