{"id":4668,"date":"2026-02-23T17:48:38","date_gmt":"2026-02-23T21:48:38","guid":{"rendered":"https:\/\/faculty.fiu.edu\/~theobald\/?page_id=4668"},"modified":"2026-02-23T18:07:08","modified_gmt":"2026-02-23T22:07:08","slug":"axon_conduction","status":"publish","type":"page","link":"https:\/\/faculty.fiu.edu\/~theobald\/fun\/neurobiology-fun\/axon_conduction\/","title":{"rendered":"axon_conduction"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4668\" class=\"elementor elementor-4668\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-bdfe56a elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"bdfe56a\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f99aee8\" data-id=\"f99aee8\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d7f5ab4 elementor-widget elementor-widget-html\" data-id=\"d7f5ab4\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" \/>\n  <title>Axon demo (HH)<\/title>\n  <style>\n    :root{\n      --bg:#0f1115;\n      --panel:#141823;\n      --panel2:#10141d;\n      --fg:#e6e8ee;\n      --muted:#aeb4c2;\n      --grid:#2a2f3a;\n      --accent:#7aa2ff;\n    }\n    html,body{height:100%; margin:0; background:var(--bg); color:var(--fg); font-family:system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;}\n    .wrap{display:grid; grid-template-columns: 320px 1fr; gap:12px; padding:12px; box-sizing:border-box; height:100%;}\n    .main{display:grid; grid-template-rows: 1fr 260px; gap:12px; min-width:0; min-height:0;}\n    .panel{background:var(--panel); border:1px solid #1f2530; border-radius:12px; padding:12px; box-sizing:border-box;}\n    .scene{background:var(--panel2); border:1px solid #1f2530; border-radius:12px; overflow:hidden; position:relative;}\n    canvas{display:block; width:100%; height:100%;}\n    h2{font-size:16px; margin:0 0 10px 0; font-weight:650;}\n    .row{display:flex; align-items:center; gap:10px; margin:10px 0;}\n    .row label{flex: 1 1 auto; font-size:13px; color:var(--muted);}\n    .row input[type=\"range\"]{flex: 1 1 180px;}\n    .row .val{width:78px; text-align:right; font-variant-numeric: tabular-nums; color:var(--fg); font-size:13px;}\n    .small{font-size:12px; color:var(--muted); line-height:1.3;}\n    .hint{margin-top:8px; padding-top:8px; border-top:1px solid #222836;}\n    .scopes{display:grid; grid-template-columns: 1fr; gap:12px; min-width:0;}\n    .scopeBox{background:var(--panel2); border:1px solid #1f2530; border-radius:12px; overflow:hidden;}\n    .scopeTitle{position:absolute; left:10px; top:8px; font-size:12px; color:var(--muted); pointer-events:none;}\n    .scopeWrap{position:relative; height:124px;}\n    .btnrow{display:flex; gap:10px; margin-top:10px;}\n    button{\n      background:#1b2230; color:var(--fg); border:1px solid #2a3242; border-radius:10px;\n      padding:8px 10px; cursor:pointer; font-weight:600;\n    }\n    button:hover{border-color:#3a4761;}\n    .kbd{display:inline-block; padding:1px 6px; border:1px solid #3a4150; border-bottom-width:2px; border-radius:6px; background:#111522; color:#cfd6e6; font-size:12px;}\n  <\/style>\n<\/head>\n<body>\n  <div class=\"wrap\">\n    <div class=\"panel\">\n      <h2>Axon conduction<\/h2>\n\n      <div class=\"row\">\n        <label style=\"justify-content:flex-start; gap:10px; color: var(--fg);\">\n          <input id=\"chkColor\" type=\"checkbox\" checked \/>\n          <span>Voltage coloration<\/span>\n        <\/label>\n      <\/div>\n\n      <div class=\"row\">\n        <label for=\"diam\">Axon diameter scale<\/label>\n        <input id=\"diam\" type=\"range\" min=\"0.4\" max=\"2.5\" step=\"0.01\" value=\"1.00\" \/>\n        <div class=\"val\" id=\"diamVal\">1.00\u00d7<\/div>\n      <\/div>\n\n      <div class=\"row\">\n        <label for=\"rax\">Axial resistance scale<\/label>\n        <input id=\"rax\" type=\"range\" min=\"0.4\" max=\"3.0\" step=\"0.01\" value=\"1.00\" \/>\n        <div class=\"val\" id=\"raxVal\">1.00\u00d7<\/div>\n      <\/div>\n\n      <div class=\"row\">\n        <label for=\"cm\">Membrane capacitance scale<\/label>\n        <input id=\"cm\" type=\"range\" min=\"0.25\" max=\"4.0\" step=\"0.01\" value=\"1.00\" \/>\n        <div class=\"val\" id=\"cmVal\">1.00\u00d7<\/div>\n      <\/div>\n\n\n      <div class=\"row\">\n        <label for=\"iinj\">Pulse amplitude<\/label>\n        <input id=\"iinj\" type=\"range\" min=\"0\" max=\"30\" step=\"0.1\" value=\"10.5\" \/>\n        <div class=\"val\" id=\"iinjVal\">10.5<\/div>\n      <\/div>\n\n      <div class=\"small\">\n        Click a compartment to place electrodes (recording).<br\/>\n        Hold <span class=\"kbd\">Shift<\/span> while clicking to place stimulating electrodes.\n      <\/div>\n\n      <div class=\"hint small\">\n        Press <span class=\"kbd\">1<\/span> to stimulate stim electrode #1, <span class=\"kbd\">2<\/span> for stim #2.<br\/>\n        (We capture these keys globally to avoid browser \u201ctype ahead find\u201d.)\n      <\/div>\n\n      <div class=\"btnrow\">\n        <button id=\"btnReset\">Reset sliders<\/button>\n        <button id=\"btnClear\">Clear electrodes<\/button>\n      <\/div>\n    <\/div>\n\n    <div class=\"main\">\n    <div class=\"scene\">\n      <canvas id=\"sceneCanvas\"><\/canvas>\n    <\/div>\n\n    <div class=\"scopes\">\n      <div class=\"scopeBox\">\n        <div class=\"scopeWrap\">\n          <div class=\"scopeTitle\" id=\"scopeTitleA\">Scope A<\/div>\n          <canvas id=\"scopeA\"><\/canvas>\n        <\/div>\n      <\/div>\n      <div class=\"scopeBox\">\n        <div class=\"scopeWrap\">\n          <div class=\"scopeTitle\" id=\"scopeTitleB\">Scope B<\/div>\n          <canvas id=\"scopeB\"><\/canvas>\n        <\/div>\n      <\/div>\n    <\/div>\n    <\/div>\n\n  <\/div>\n\n  <script type=\"module\">\n    \/\/ Adjust these paths for WordPress later.\n    import { Neuron } from \"\/~theobald\/wp-content\/plugins\/neuro_demos\/assets\/neuron.js\";\n    import { NeuronRenderer, makeFitXform, RingBuffer, drawScope } from \"\/~theobald\/wp-content\/plugins\/neuro_demos\/assets\/render.js\";\n\n    \/\/ ---------- Canvas sizing ----------\n    const sceneCanvas = document.getElementById(\"sceneCanvas\");\n    const sceneCtx = sceneCanvas.getContext(\"2d\", { alpha: false });\n\n    const scopeA = document.getElementById(\"scopeA\");\n    const scopeB = document.getElementById(\"scopeB\");\n    const scopeCtxA = scopeA.getContext(\"2d\", { alpha: false });\n    const scopeCtxB = scopeB.getContext(\"2d\", { alpha: false });\n\n    function resizeCanvasToCSS(canvas){\n      const dpr = window.devicePixelRatio || 1;\n      const rect = canvas.getBoundingClientRect();\n      const w = Math.max(2, Math.floor(rect.width * dpr));\n      const h = Math.max(2, Math.floor(rect.height * dpr));\n      if (canvas.width !== w || canvas.height !== h){\n        canvas.width = w; canvas.height = h;\n      }\n    }\n    function resizeAll(){\n      resizeCanvasToCSS(sceneCanvas);\n      resizeCanvasToCSS(scopeA);\n      resizeCanvasToCSS(scopeB);\n    }\n    window.addEventListener(\"resize\", () => { resizeAll(); });\n\n    \/\/ ---------- Electrode models ----------\n    class RecordingElectrode {\n      constructor({ compName, scopeIndex, label, color }){\n        this.type = \"record\";\n        this.compName = compName;\n        this.scopeIndex = scopeIndex; \/\/ 0 or 1\n        this.label = label || `V(${compName})`;\n        this.color = color || \"rgba(140,180,255,0.95)\";\n        this.trace = new RingBuffer(2500);\n      }\n      primeWith(v){\n        this.trace.fill(v);\n      }\n      sample(neuron){\n        const c = neuron.getCompByName(this.compName);\n        if (!c) return;\n        this.trace.push(c.V);\n      }\n    }\n\n    class StimElectrode {\n      constructor({ compName, label, color }){\n        this.type = \"stim\";\n        this.compName = compName;\n        this.label = label || `I\u2192${compName}`;\n        this.color = color || \"rgba(255,190,120,0.95)\";\n      }\n    }\n\n    \/\/ Manages up to 2 record + 2 stim\n    class Electrodes {\n      constructor({ maxRecord = 2, maxStim = 2 } = {}){\n        this.maxRecord = maxRecord;\n        this.maxStim = maxStim;\n        this.record = [];\n        this.stim = [];\n        this._nextScope = 0; \/\/ alternates A\/B\n        this._recordColors = [\"rgba(120,170,255,0.95)\", \"rgba(110,220,180,0.95)\"];\n      }\n\n      clear(){\n        this.record.length = 0;\n        this.stim.length = 0;\n        this._nextScope = 0;\n      }\n\n      addRecording(compName, neuron){\n        if (this.record.length >= this.maxRecord) this.record.shift();\n        const scopeIndex = this._nextScope % 2;\n        this._nextScope++;\n\n        const color = this._recordColors[scopeIndex];\n        const e = new RecordingElectrode({ compName, scopeIndex, label: `V(${compName})`, color });\n\n        \/\/ prefill so the scope starts \"flat\" instead of squishing\n        const c = neuron.getCompByName(compName);\n        e.primeWith(c ? c.V : -0.065);\n\n        this.record.push(e);\n        return e;\n      }\n\n      addStim(compName){\n        if (this.stim.length >= this.maxStim) this.stim.shift();\n        const idx = this.stim.length;\n        const colors = [\"rgba(255,190,120,0.95)\", \"rgba(255,130,190,0.95)\"];\n        const e = new StimElectrode({ compName, label: `Stim ${idx+1}`, color: colors[idx % colors.length] });\n        this.stim.push(e);\n        return e;\n      }\n\n      sampleAll(neuron){\n        for (const e of this.record) e.sample(neuron);\n      }\n    }\n\n    \/\/ ---------- Build neuron ----------\n    function buildNeuron(){\n      const n = new Neuron();\n      const soma = n.addSoma([0.5, 0.0], 0.5);\n\n      n.addAxon({\n        num_pts: 140,\n        cpts: [[0.9, 0.0], [4.5, 0.35], [2.0, -2.8], [8.0, -3.2]],\n        connect: soma,\n        draw_rad: 0.05\n      });\n\n      return n;\n    }\n\n    let neuron = buildNeuron();\n    \/\/ Remember baseline radii so we can scale axon diameter visually\n    for (const section of neuron.sections){\n      for (const c of section){\n        c._base_draw_rad = (c.draw_rad ?? null);\n      }\n    }\n\n    const renderer = new NeuronRenderer();\n\n    \/\/ Voltage coloration toggle\n    const chkColor = document.getElementById('chkColor');\n    renderer.useVoltageColor = chkColor ? chkColor.checked : true;\n    if (chkColor) chkColor.addEventListener('change', () => { renderer.useVoltageColor = chkColor.checked; });\n\n    \/\/ default electrodes: record soma + distal, stim soma + mid-axon\n    const electrodes = new Electrodes();\n\n    function addDefaultElectrodes(){\n      const soma = neuron.sections.find(s => s?.length === 1)?.[0];\n      const ax = neuron.sections.find(s => s?.[0]?.name?.startsWith(\"A\"));\n      if (!soma || !ax) return;\n\n      electrodes.addRecording(soma.name, neuron);\n      electrodes.addRecording(ax[Math.floor(ax.length*0.85)].name, neuron);\n      electrodes.addStim(soma.name);\n      electrodes.addStim(ax[Math.floor(ax.length*0.35)].name);\n    }\n    addDefaultElectrodes();\n\n    \/\/ Fixed world window (so the neuron doesn't inflate to fill the canvas)\n    function makeFixedXform(canvas, world, paddingPx=30){\n      const W = canvas.width, H = canvas.height;\n      const spanX = world.xmax - world.xmin;\n      const spanY = world.ymax - world.ymin;\n\n      const sx = (W - 2*paddingPx) \/ spanX;\n      const sy = (H - 2*paddingPx) \/ spanY;\n      const scale = Math.min(sx, sy);\n\n      const cx = 0.5*(world.xmin + world.xmax);\n      const cy = 0.5*(world.ymin + world.ymax);\n\n      const map = (x,y) => {\n        const X = (x - cx)*scale + W\/2;\n        const Y = -(y - cy)*scale + H\/2;\n        return [X,Y];\n      };\n      return { map, scale };\n    }\n\n    let xform = null;\n    function updateXform(){\n      \/\/ choose a fixed window that comfortably contains soma+axon\n      xform = makeFixedXform(sceneCanvas, { xmin: -2.5, xmax: 9.5, ymin: -5.2, ymax: 3.2 }, 30);\n    }\n\n    \/\/ ---------- Axial scaling ----------\n    \/\/ The model currently treats axial coupling as an electrical conductance (Siemens) stored per connection.\n    \/\/ We'll update all axial links whenever sliders move.\n    function setAllAxialG(neuron, gNew){\n      for (const section of neuron.sections){\n        for (const c of section){\n          if (!c.axial) continue;\n          for (const link of c.axial){\n            link.g = gNew;\n          }\n        }\n      }\n    }\n\n    \/\/ baseline axial conductance from the model as-built (axon uses g_axial_S in Neuron.addAxon)\n    function estimateBaselineAxialG(neuron){\n      \/\/ pick the first non-empty axial link\n      for (const section of neuron.sections){\n        for (const c of section){\n          if (c.axial && c.axial.length){\n            return c.axial[0].g;\n          }\n        }\n      }\n      return 5e-8;\n    }\n    const gAxial0 = estimateBaselineAxialG(neuron);\n\n    \n    function applyDiameterVisual(neuron, diamScale){\n      for (const section of neuron.sections){\n        if (!section || section.length < 2) continue; \/\/ skip soma\n        for (const c of section){\n          const baseRad = c._base_draw_rad ?? c.draw_rad ?? 0.05;\n          c.draw_rad = baseRad * diamScale;\n        }\n      }\n    }\n\n\n    function applyCapacitance(neuron, cmScale, diamScale){\n      for (const section of neuron.sections){\n        if (!section || section.length < 2) continue; \/\/ skip soma\n        for (const c of section){\n          if (!c?.p) continue;\n          if (c.p._Cm_base_uF_cm2 === undefined){\n            c.p._Cm_base_uF_cm2 = c.p.Cm_uF_cm2;\n          }\n          \/\/ In this simplified demo, diameter increases effective membrane area per compartment,\n          \/\/ so it scales total capacitance. We implement that by scaling the specific Cm term.\n          c.p.Cm_uF_cm2 = c.p._Cm_base_uF_cm2 * cmScale * diamScale;\n        }\n      }\n    }\n\n\n    function applyCableFromSliders(){\n      const diam = Number(document.getElementById(\"diam\").value);\n      applyDiameterVisual(neuron, diam);\n      const rax = Number(document.getElementById(\"rax\").value);\n\n      const cm = Number(document.getElementById(\"cm\").value);\n      applyCapacitance(neuron, cm, diam);\n\n      \/\/ toy cable rule: g \u221d diameter^2, and \u221d 1\/Rax\n      const g = gAxial0 * (diam*diam) \/ rax;\n      setAllAxialG(neuron, g);\n\n      document.getElementById(\"diamVal\").textContent = diam.toFixed(2) + \"\u00d7\";\n      document.getElementById(\"raxVal\").textContent = rax.toFixed(2) + \"\u00d7\";\n      document.getElementById(\"cmVal\").textContent = cm.toFixed(2) + \"\u00d7\";\n    }\n\n    document.getElementById(\"diam\").addEventListener(\"input\", applyCableFromSliders);\n    document.getElementById(\"rax\").addEventListener(\"input\", applyCableFromSliders);\n    document.getElementById(\"cm\").addEventListener(\"input\", applyCableFromSliders);\n    applyCableFromSliders();\n\n    \/\/ ---------- Pulse injection ----------\n    const iinj = document.getElementById(\"iinj\");\n    const iinjVal = document.getElementById(\"iinjVal\");\n    iinj.addEventListener(\"input\", () => { iinjVal.textContent = Number(iinj.value).toFixed(1); });\n    iinjVal.textContent = Number(iinj.value).toFixed(1);\n\n    const pulseDur_s = 0.5e-3; \/\/ 0.5 ms\n    const activePulses = new Map(); \/\/ compName -> {tEnd, amp_uAcm2}\n\n    function fireStim(index){\n      const e = electrodes.stim[index];\n      if (!e) return;\n      const amp = Number(iinj.value); \/\/ uA\/cm^2\n      activePulses.set(e.compName, { tEnd: neuron.t + pulseDur_s, amp_uAcm2: amp });\n    }\n\n    \/\/ Prevent browser type-ahead find: capture 1\/2 globally (unless typing in a text field)\n    window.addEventListener(\"keydown\", (ev) => {\n      const el = ev.target;\n      const tag = el?.tagName?.toLowerCase() || \"\";\n      const isTextEntry =\n        tag === \"textarea\" ||\n        tag === \"select\" ||\n        (tag === \"input\" && ![\"range\", \"checkbox\", \"button\"].includes((el.type || \"\").toLowerCase())) ||\n        el?.isContentEditable;\n\n      if (isTextEntry) return;\n\n      if (ev.key === \"1\" || ev.key === \"2\") {\n        ev.preventDefault();\n        ev.stopPropagation();\n        if (ev.repeat) return;\n        fireStim(ev.key === \"1\" ? 0 : 1);\n      }\n    }, { capture: true });\n\n    \/\/ ---------- Click to place electrodes ----------\n    sceneCanvas.addEventListener(\"click\", (ev) => {\n      const rect = sceneCanvas.getBoundingClientRect();\n      const dpr = window.devicePixelRatio || 1;\n      const x = (ev.clientX - rect.left) * dpr;\n      const y = (ev.clientY - rect.top) * dpr;\n\n      const comp = renderer.hitTestScreen(neuron, xform, x, y, 18);\n      if (!comp) return;\n\n      if (ev.shiftKey) {\n        const e = electrodes.addStim(comp.name);\n        console.log(\"Added stim electrode:\", e.label, \"at\", comp.name);\n      } else {\n        const e = electrodes.addRecording(comp.name, neuron);\n        console.log(\"Added recording electrode:\", e.label, \"\u2192 scope\", e.scopeIndex === 0 ? \"A\" : \"B\");\n      }\n    });\n\n    \/\/ ---------- Buttons ----------\n    document.getElementById(\"btnClear\").addEventListener(\"click\", () => {\n      electrodes.clear();\n      activePulses.clear();\n      document.getElementById(\"scopeTitleA\").textContent = \"Scope A\";\n      document.getElementById(\"scopeTitleB\").textContent = \"Scope B\";\n    });\n\n    const defaults = { diam: 1.00, rax: 1.00, iinj: 10.5 };\n    document.getElementById(\"btnReset\").addEventListener(\"click\", () => {\n      document.getElementById(\"diam\").value = defaults.diam;\n      document.getElementById(\"rax\").value = defaults.rax;\n      document.getElementById(\"iinj\").value = defaults.iinj;\n      iinjVal.textContent = defaults.iinj.toFixed(1);\n      applyCableFromSliders();\n    });\n\n    \/\/ ---------- Main loop ----------\n    resizeAll();\n    updateXform();\n\n    const stepsPerFrame = 10;\n\n    function frame(){\n      resizeAll();\n      updateXform();\n\n      \/\/ Build injected current map in Amps\n      const currentsA_byName = {};\n      for (const [name, p] of activePulses.entries()){\n        if (neuron.t <= p.tEnd){\n          const c = neuron.getCompByName(name);\n          if (c){\n            currentsA_byName[name] = p.amp_uAcm2 * 1e-6 * c.p.area_cm2; \/\/ (uA\/cm^2) * (A\/uA) * area (cm^2)\n          }\n        } else {\n          activePulses.delete(name);\n        }\n      }\n\n      \/\/ integrate neuron\n      for (let k=0;k<stepsPerFrame;k++){\n        neuron.step(neuron.dt, currentsA_byName);\n      }\n\n      \/\/ record after stepping\n      electrodes.sampleAll(neuron);\n\n      \/\/ draw neuron + electrodes\n      sceneCtx.clearRect(0,0,sceneCanvas.width,sceneCanvas.height);\n      renderer.drawNeuron(sceneCtx, neuron, xform);\n      renderer.drawElectrodes(sceneCtx, neuron, electrodes, xform);\n\n      \/\/ draw scopes\n      const rec0 = electrodes.record.find(e => e.scopeIndex === 0);\n      const rec1 = electrodes.record.find(e => e.scopeIndex === 1);\n\n      document.getElementById(\"scopeTitleA\").textContent = rec0 ? rec0.label : \"Scope A\";\n      document.getElementById(\"scopeTitleB\").textContent = rec1 ? rec1.label : \"Scope B\";\n\n      drawScope(scopeCtxA, scopeA, rec0 ? rec0.trace.toArray() : null, \"\", rec0 ? rec0.color : \"rgba(230,232,238,0.35)\", { autoscale:false, vmin:-0.100, vmax:0.070 });\n      drawScope(scopeCtxB, scopeB, rec1 ? rec1.trace.toArray() : null, \"\", rec1 ? rec1.color : \"rgba(230,232,238,0.35)\", { autoscale:false, vmin:-0.100, vmax:0.070 });\n\n      requestAnimationFrame(frame);\n    }\n    requestAnimationFrame(frame);\n  <\/script>\n<\/body>\n<\/html>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Axon demo (HH) Axon conduction Voltage coloration Axon diameter scale 1.00\u00d7 Axial resistance scale 1.00\u00d7 Membrane capacitance scale 1.00\u00d7 Pulse amplitude 10.5 Click a compartment to place electrodes (recording). Hold Shift while clicking to place stimulating electrodes. Press 1 to stimulate stim electrode #1, 2 for stim #2. (We capture these keys globally to avoid [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":4438,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-4668","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/pages\/4668","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/comments?post=4668"}],"version-history":[{"count":10,"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/pages\/4668\/revisions"}],"predecessor-version":[{"id":4686,"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/pages\/4668\/revisions\/4686"}],"up":[{"embeddable":true,"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/pages\/4438"}],"wp:attachment":[{"href":"https:\/\/faculty.fiu.edu\/~theobald\/wp-json\/wp\/v2\/media?parent=4668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}