Skip to content

Commit 9836f15

Browse files
committed
Fix notebook description extraction for same-cell title+description
1 parent a1923ad commit 9836f15

9 files changed

Lines changed: 281 additions & 249 deletions

File tree

‎scripts/lib/notebooks.py‎

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -139,38 +139,70 @@ def _extract_title(notebook: dict) -> str:
139139

140140

141141
def _extract_description(notebook: dict) -> str:
142-
"""Extract description from first paragraph after title."""
143-
found_title = False
142+
"""Extract description from first paragraph after title.
144143
144+
Handles both cases:
145+
- Title and description in same cell (# Title\\n\\nDescription...)
146+
- Title in one cell, description in next markdown cell
147+
"""
145148
for cell in notebook.get("cells", []):
146149
if cell.get("cell_type") == "markdown":
147150
source = cell.get("source", [])
148151
if isinstance(source, list):
149152
source = "".join(source)
150153

151-
if re.match(r"^#\s+.+\s*$", source.strip()):
152-
found_title = True
154+
# Check if cell starts with a title
155+
title_match = re.match(r"^#\s+.+", source)
156+
if title_match:
157+
# Remove the title line and look for description in same cell
158+
after_title = source[title_match.end():].strip()
159+
if after_title:
160+
# Description is in same cell as title
161+
desc = _clean_description(after_title)
162+
if desc:
163+
return desc
164+
# If no description after title in this cell, continue to next cell
153165
continue
154166

155-
if found_title or not re.search(r"^#\s+", source):
156-
# Remove markdown formatting
157-
text = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", source)
158-
text = re.sub(r"`[^`]+`", "", text)
159-
text = re.sub(r"\*\*([^*]+)\*\*", r"\1", text)
160-
text = re.sub(r"\*([^*]+)\*", r"\1", text)
161-
text = re.sub(r"^\s*#+\s+.+$", "", text, flags=re.MULTILINE)
162-
text = re.sub(r"\$[^$]+\$", "", text)
163-
164-
lines = [l.strip() for l in text.split("\n") if l.strip()]
165-
if lines:
166-
desc = lines[0]
167-
if len(desc) > 200:
168-
desc = desc[:197] + "..."
169-
return desc
167+
# This is a markdown cell without a title - could be description
168+
desc = _clean_description(source)
169+
if desc:
170+
return desc
170171

171172
return "Example notebook"
172173

173174

175+
def _clean_description(text: str) -> str:
176+
"""Clean markdown text and extract first meaningful paragraph."""
177+
# Remove markdown formatting
178+
text = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", text) # links
179+
text = re.sub(r"`[^`]+`", "", text) # inline code
180+
text = re.sub(r"\*\*([^*]+)\*\*", r"\1", text) # bold
181+
text = re.sub(r"\*([^*]+)\*", r"\1", text) # italic
182+
text = re.sub(r"^\s*#+\s+.+$", "", text, flags=re.MULTILINE) # headings
183+
text = re.sub(r"\$\$[^$]*\$\$", "", text, flags=re.DOTALL) # display math
184+
text = re.sub(r"\$[^$]+\$", "", text) # inline math
185+
text = re.sub(r"^\s*[-*]\s+", "", text, flags=re.MULTILINE) # list items
186+
text = re.sub(r"^\s*\d+\.\s+", "", text, flags=re.MULTILINE) # numbered lists
187+
188+
# Get first non-empty line that looks like a sentence
189+
lines = [l.strip() for l in text.split("\n") if l.strip()]
190+
for line in lines:
191+
# Skip lines that look like code, equations, or fragments
192+
if line.startswith(("import ", "from ", "```", ">>>")):
193+
continue
194+
if re.match(r"^[\W\d]+$", line): # only symbols/numbers
195+
continue
196+
if len(line) < 10: # too short to be meaningful
197+
continue
198+
# Found a good line
199+
if len(line) > 200:
200+
line = line[:197] + "..."
201+
return line
202+
203+
return ""
204+
205+
174206
def generate_version_manifest(
175207
package_id: str,
176208
tag: str,

‎static/pathsim/v0.10.0/manifest.json‎

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"slug": "harmonic-oscillator",
77
"file": "harmonic_oscillator.ipynb",
88
"title": "Harmonic Oscillator",
9-
"description": "The equation of motion that defines the harmonic oscillator is given by",
9+
"description": "In this example we have a look at the damped harmonic oscillator. A linear dynamical system that models a spring-mass-damper system.",
1010
"category": "getting-started",
1111
"tags": [
1212
"ode",
@@ -18,7 +18,7 @@
1818
"slug": "linear-feedback",
1919
"file": "linear_feedback.ipynb",
2020
"title": "Linear Feedback System",
21-
"description": "Then lets define the system parameters such as the initial value of the integrator, the linear feedback gain and the time dependend source function .",
21+
"description": "Here's a simple example of a linear feedback system, simulated with PathSim.",
2222
"category": "getting-started",
2323
"tags": [
2424
"ode",
@@ -30,7 +30,7 @@
3030
"slug": "pendulum",
3131
"file": "pendulum.ipynb",
3232
"title": "Pendulum",
33-
"description": "Above we have both the mechanical mode, which is a weight dangling from a string with length and diverted by some initial angle, as well as the block diagram representation of the equation of moti...",
33+
"description": "In this example we have a look at the mathematical pendulum.",
3434
"category": "getting-started",
3535
"tags": [
3636
"ode",
@@ -43,7 +43,7 @@
4343
"slug": "vanderpol",
4444
"file": "vanderpol.ipynb",
4545
"title": "Van der Pol",
46-
"description": "$$",
46+
"description": "Here we cover a true classic from the world of dynamical systems. The Van der Pol system!",
4747
"category": "getting-started",
4848
"tags": [
4949
"ode",
@@ -55,7 +55,7 @@
5555
"slug": "cascade-controller",
5656
"file": "cascade_controller.ipynb",
5757
"title": "Cascade Controller",
58-
"description": "The cascade controller consists of:",
58+
"description": "In this example we demonstrate a cascade control architecture with a two-loop PID control system. Cascade control is widely used in process control when a fast inner loop can help improve the perfo...",
5959
"category": "control",
6060
"tags": [
6161
"cascade",
@@ -67,7 +67,7 @@
6767
"slug": "pid-controller",
6868
"file": "pid_controller.ipynb",
6969
"title": "PID Controller",
70-
"description": "First let's import the required classes and blocks:",
70+
"description": "This example demonstrates a PID (Proportional-Integral-Derivative) controller in PathSim, including automatic differentiation for sensitivity analysis. The system tracks a step-changing setpoint an...",
7171
"category": "control",
7272
"tags": [
7373
"pid",
@@ -79,7 +79,7 @@
7979
"slug": "thermostat",
8080
"file": "thermostat.ipynb",
8181
"title": "Thermostat",
82-
"description": "With some algebraic manipulations we can translate the system equation into a block diagram that can be implemented in PathSim. Note the event manager, that watches the state of the integrator and ...",
82+
"description": "In this example we have a look at a thermostat, which is a kind off discrete regulator. It switches a heating element on or of depending on defined upper and lower thresholds.",
8383
"category": "control",
8484
"tags": [
8585
"hybrid",
@@ -91,7 +91,7 @@
9191
"slug": "bouncing-ball",
9292
"file": "bouncing_ball.ipynb",
9393
"title": "Bouncing Ball",
94-
"description": "Systems like this require the location and resolution of discrete events within the timestep and are not easily solved with standard numerical ODE solvers. PathSim implements an event management sy...",
94+
"description": "This example demonstrates PathSim's event handling system. The classical example here is the bouncing ball. The ball accelerates downward due to gravity and once it hits the floor, it bounces back....",
9595
"category": "mechanics",
9696
"tags": [
9797
"events",
@@ -103,7 +103,7 @@
103103
"slug": "bouncing-pendulum",
104104
"file": "bouncing_pendulum.ipynb",
105105
"title": "Bouncing Pendulum",
106-
"description": "The mathematical pendulum is governed by the nonlinear differential equation:",
106+
"description": "This example demonstrates a hybrid system combining continuous pendulum dynamics with discrete bounce events. The pendulum swings until it hits the ground (zero angle), at which point it bounces ba...",
107107
"category": "mechanics",
108108
"tags": [
109109
"events",
@@ -115,7 +115,7 @@
115115
"slug": "stick-slip",
116116
"file": "stick_slip.ipynb",
117117
"title": "Stick Slip",
118-
"description": "This system has two possible states:",
118+
"description": "In this example we simulate a mechanical system that exhibits stick-slip behaviour, typical for coulomb friction. Lets consider the setup below, where we have a box sitting on a driven conveyor bel...",
119119
"category": "mechanics",
120120
"tags": [
121121
"friction",
@@ -127,7 +127,7 @@
127127
"slug": "switched-bouncing-ball",
128128
"file": "switched_bouncing_ball.ipynb",
129129
"title": "Switched Bouncing Ball",
130-
"description": "The ball experiences:",
130+
"description": "This example demonstrates advanced event handling with multiple simultaneous events, event switching, and conditional event logic. The bouncing ball bounces on a table first, and then drops to the ...",
131131
"category": "mechanics",
132132
"tags": [
133133
"events",
@@ -139,7 +139,7 @@
139139
"slug": "delta-sigma-adc",
140140
"file": "delta_sigma_adc.ipynb",
141141
"title": "Delta-Sigma ADC",
142-
"description": "A delta-sigma ADC works by:",
142+
"description": "You can also find this example as a single file in the GitHub repository.This example demonstrates a first-order delta-sigma (\u0394\u03a3) ADC, a popular architecture for high-resolution analog-to-digital c...",
143143
"category": "electronics",
144144
"tags": [
145145
"adc",
@@ -151,7 +151,7 @@
151151
"slug": "diode-circuit",
152152
"file": "diode_circuit.ipynb",
153153
"title": "Diode Circuit",
154-
"description": "Applying Kirchhoff's Voltage Law (KVL):",
154+
"description": "You can also find this example as a single file in the GitHub repository.This example demonstrates a more complex application of algebraic loop solving: a diode circuit with nonlinear characteristi...",
155155
"category": "electronics",
156156
"tags": [
157157
"nonlinear",
@@ -163,7 +163,7 @@
163163
"slug": "sar-adc",
164164
"file": "sar_adc.ipynb",
165165
"title": "SAR ADC",
166-
"description": "A SAR ADC converts analog signals to digital using a binary search algorithm:",
166+
"description": "You can also find this example as a single file in the GitHub repository.This advanced example demonstrates a SAR ADC (Successive Approximation Register Analog-to-Digital Converter), one of the mos...",
167167
"category": "electronics",
168168
"tags": [
169169
"adc",
@@ -175,7 +175,7 @@
175175
"slug": "fmcw-radar",
176176
"file": "fmcw_radar.ipynb",
177177
"title": "FMCW Radar",
178-
"description": "The figure below shows the block diagram of a very basic FMCW radar system consisting of a chirp source (sinusoid with a linearly time dependent frequency), a delay (to model the signal propagation...",
178+
"description": "In this example we simulate a simple frequency modulated continuous wave (FMCW) radar system.",
179179
"category": "signal-processing",
180180
"tags": [
181181
"radar",
@@ -199,7 +199,7 @@
199199
"slug": "spectrum-analysis",
200200
"file": "spectrum_analysis.ipynb",
201201
"title": "Spectrum Analysis",
202-
"description": "We'll create a simple signal chain:",
202+
"description": "In this example we demonstrate frequency domain analysis using PathSim's spectrum block. We'll examine the frequency response of a Butterworth lowpass filter by analyzing its response to a Gaussian...",
203203
"category": "signal-processing",
204204
"tags": [
205205
"fft",
@@ -211,7 +211,7 @@
211211
"slug": "transfer-function",
212212
"file": "transfer_function.ipynb",
213213
"title": "Transfer Function",
214-
"description": "The pole-residue-constant form represents a transfer function as:",
214+
"description": "In this example we demonstrate how to use transfer functions in PathSim using the Pole-Residue-Constant (PRC) form. This representation is particularly convenient for transfer functions with comple...",
215215
"category": "signal-processing",
216216
"tags": [
217217
"frequency",
@@ -223,7 +223,7 @@
223223
"slug": "chemical-reactor",
224224
"file": "chemical_reactor.ipynb",
225225
"title": "Chemical Reactor",
226-
"description": "We define the physical and chemical parameters for the reactor.",
226+
"description": "You can also find this example as a single file in the GitHub repository.This example demonstrates a Continuous Stirred Tank Reactor (CSTR) with consecutive exothermic reactions. This is a classic ...",
227227
"category": "chemical",
228228
"tags": [
229229
"cstr",
@@ -235,7 +235,7 @@
235235
"slug": "algebraic-loop",
236236
"file": "algebraic_loop.ipynb",
237237
"title": "Algebraic Loop",
238-
"description": "An algebraic loop occurs when the output of a block depends on its own input in the same timestep. This creates an implicit equation that must be solved:",
238+
"description": "You can also find this example as a single file in the GitHub repository.This example demonstrates PathSim's ability to handle algebraic loops - situations where a signal feeds back on itself insta...",
239239
"category": "advanced",
240240
"tags": [
241241
"algebraic",
@@ -247,7 +247,7 @@
247247
"slug": "lorenz-attractor",
248248
"file": "lorenz_attractor.ipynb",
249249
"title": "Lorenz Attractor",
250-
"description": "We create blocks for each equation:",
250+
"description": "You can also find this example as a single file in the GitHub repository.This example demonstrates the famous Lorenz attractor, a system of ordinary differential equations that exhibits chaotic beh...",
251251
"category": "advanced",
252252
"tags": [
253253
"chaos",
@@ -259,7 +259,7 @@
259259
"slug": "nested-subsystems",
260260
"file": "nested_subsystems.ipynb",
261261
"title": "Nested Subsystems",
262-
"description": "First, we create a subsystem that computes",
262+
"description": "You can also find this example as a single file in the GitHub repository.This example demonstrates PathSim's hierarchical modeling capabilities using nested subsystems. We'll build a complex Van de...",
263263
"category": "advanced",
264264
"tags": [
265265
"hierarchy",
@@ -280,7 +280,7 @@
280280
"slug": "fmu-cosimulation",
281281
"file": "fmu_cosimulation.ipynb",
282282
"title": "FMU Co-Simulation",
283-
"description": "Note that FMPy must be installed to use FMU blocks:",
283+
"description": "This example demonstrates how to integrate a Functional Mock-up Unit (FMU) as a PathSim block using the co-simulation interface. FMUs are standardized model exchange and co-simulation packages that...",
284284
"category": "fmu",
285285
"tags": [
286286
"fmu",

0 commit comments

Comments
 (0)