diff --git a/.agents/2026-04-22.md b/.agents/2026-04-22.md new file mode 100644 index 00000000..0fcdb6f7 --- /dev/null +++ b/.agents/2026-04-22.md @@ -0,0 +1,32 @@ +# Session: 2026-04-22 + +**Authoring agent:** opencode + +## Objective +Implemented `NmlPythonizer` — converts NeuroML XML files into Python scripts using the libNeuroML API. + +## Completed +- Created `pyneuroml/utils/nml2py.py` with `NmlPythonizer` class +- Traverses object tree via `info()`, generates `parent.add()` calls with string-literal references +- Extracts inline cells/channels/synapses to separate files; preserves includes +- Orders output by human-logical construction: networks -> populations -> cells -> channels -> synapses -> projections -> connections -> inputs -> metadata +- Type classification uses substring matching (`"Cell" in type_name`) rather than hardcoded sets to avoid maintenance drift +- All NmlId and population references kept as string literals (XML paths like `cell/0/soma/3` cannot be reliably resolved) +- Verified round-trip: generated script produces model identical to original XML + +## Key Design Decisions +- Root doc via `component_factory()`, all others via `parent.add()` +- Variable names from component `id` attributes; type-based names with counters for idless components +- `_is_default_value()` compares against fresh instance defaults to skip cluttering output + +## Lessons Learned +- `read_neuroml2_file` (not `read_neuroml2`) is the correct import from `pyneuroml.io` +- `Connection.id` can be an integer — `_sanitize_var_name` must handle both +- Some attributes have non-None defaults (e.g., `Connection.pre_segment_id = 0`) — must compare against defaults, not just `None` + +## Open Questions +- Future: handle cell XML files with morphologies (currently skipped due to size) + +## References +- [libNeuroML generatedssupersuper.py](https://github.com/NeuralEnsemble/libNeuroML/blob/master/neuroml/nml/generatedssupersuper.py) - `add()`, `component_factory()`, `info()` implementation +- [Test XML](https://github.com/NeuroML/Documentation/raw/refs/heads/main/source/Userdocs/NML2_examples/izhikevich2007_network.nml) - 2 populations, 20 connections, 5 pulse generators diff --git a/.agents/2026-04-29.md b/.agents/2026-04-29.md new file mode 100644 index 00000000..f4aa2d6c --- /dev/null +++ b/.agents/2026-04-29.md @@ -0,0 +1,16 @@ +# Session: 2026-04-29 + +**Authoring agent:** opencode + +## Objective +Reviewed include path handling in `nml2py.py` and discussed round-trip test strategy. + +## Completed +- Decided to keep original include hrefs as-is (no `../` prefix) with a user note explaining they may need to update paths or copy files + +## Open Questions +- Round-trip test design: `info()` dict comparison is closest option, but must account for different include paths and extracted inline components. Need to compare children by type+id rather than position. Deeper discussion deferred. + +## Notes +- Branch: `feat-xml2py` +- Latest commit: `9e86aff` (feat: add nml2py entry point) diff --git a/.agents/2026-05-12.md b/.agents/2026-05-12.md new file mode 100644 index 00000000..37274777 --- /dev/null +++ b/.agents/2026-05-12.md @@ -0,0 +1,19 @@ +# Session: 2026-05-12 + +**Authoring agent:** opencode + +## Objective +Diagnosed pytest logging capture issues and added tests for nml2py.py generator methods. + +## Completed +- Identified root cause: `--log-cli-level` doesn't work with xdist; `--log-level=DEBUG` captures logs but hides them for passing tests (need `-rP`) +- Updated AGENTS.md with logging quirks and "be concise" convention +- Added `test_generated_code_structure` (string assertions) and `test_generated_code_exec` (exec + namespace) for nml2py.py +- Removed `_is_default_value` from nml2py.py — now always includes all values explicitly + +## Errors and Lessons +- `tests/lems/` directory shadows real `lems` package in sys.path when cwd is `tests/` — caused confusing import errors +- `pyneuroml` and `tests.*` loggers are in different branches of the logger hierarchy; `propagate=False` on pyneuroml has no effect on test loggers + +## References +- AGENTS.md for full pytest logging quirks diff --git a/.agents/Readme.md b/.agents/Readme.md new file mode 100644 index 00000000..356102e1 --- /dev/null +++ b/.agents/Readme.md @@ -0,0 +1,46 @@ +# Agent Session Summaries + +Directory for storing summaries from chats with coding agents for future context. + +## Session File Format + +Based on Claude Code's session memory structure. + +```markdown +# Session: YYYY-MM-DD + +**Authoring agent:** + +## Objective +Brief 1-2 sentence overview of what was discussed/accomplished. + +## Completed +- Completed item 1 +- Completed item 2 + +## Errors and Lessons +- Lesson learned (from error) + +## Open Questions +- Question 1 + +## Notes +Any other relevant context for future agents + +## References +- [Title](URL) - brief description +``` + +## Naming Convention + +Session files should be named with the date: +``` +YYYY-MM-DD.md +``` + +## Guidelines + +- **Be concise**: Logs are added to agent context. Aim for 5-10 lines total. Focus on decisions and outcomes, not task-by-task details. +- **Focus on continuity**: Capture what's needed to continue work in future sessions. +- **Omit routine work**: Don't log every lint fix or commit unless noteworthy. +- **Preserve information**: When updating a session log, do not remove existing content. Merge new information with what's already there. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c3e6557..7c191a04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] fail-fast: false steps: @@ -36,15 +36,16 @@ jobs: echo "github.ref is: ${{ github.ref }}" echo "github.base_ref is: ${{ github.base_ref }}" + - name: Upgrade pip, install deps run: | python -m pip install --upgrade pip - pip install 'numpy<2.0.0' # due to lingering issues with other modules pip install .[dev] - name: List packages so far run: | pip list + env - name: Run tests run: | diff --git a/.gitignore b/.gitignore index 754e8687..a4997a1f 100644 --- a/.gitignore +++ b/.gitignore @@ -138,7 +138,7 @@ examples/results/*.dat .mypy_cache/ /examples/test_data/TwoCell.net.png /examples/test_data/Purk2M9s.png -/.coverage +**/.coverage /Nav.channel.nml /iv_izh2007RS0.net.nml /leak_chan.channel.nml @@ -181,3 +181,10 @@ coverage.xml /examples/hhcell.swc /examples/metadata.rdf /tests/utils/test_translation.net.nml +/examples/LEMS_NML2_Ex5_DetCell.neux.zip +/examples/NML2_SingleCompHHCell.neux.zip +/tests/HH_example.neux.zip + +.opencode/ + +/tests/temp_nml2py* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f83cf7e..4d2e6fdd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,13 +2,14 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v6.0.0 hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-added-large-files + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-added-large-files + args: [ "--maxkb=5000"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.1 + rev: v0.15.12 hooks: - id: ruff args: [ "--select", "I", "--fix" ] diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..a9f9c8e9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,74 @@ +# AGENTS.md - pyNeuroML + +Single Python package for reading, writing, simulating and analysing NeuroML2/LEMS models. + +## Architecture + +- **Single package** — all code under `pyneuroml/`, tests under `tests/`, examples under `examples/` +- **Bundled jNeuroML** — `pyneuroml/lib/*.jar` provides Java simulation backend +- **CLI entry points** — `pynml` (main), `jnml`, `pynml-channelanalysis`, `pynml-povray`, `pynml-tune`, `pynml-swc2nml`, `pynml-xpp`, and others (see `setup.cfg` `[options.entry_points]`) +- **Core modules**: `pynml.py` (main CLI), `io.py`, `runners.py`, `lems/`, `analysis/`, `neuron/`, `channelml/`, `plot/`, `tune/`, `swc/`, `xppaut/` + +## Developer Commands + +```bash +# Install for development (from repo root) +pip install .[dev] + +# Run lint + format (ruff) +ruff check . --fix +ruff format . + +# Run full test suite (installs deps, runs CLI tests + pytest + examples) +./test.sh # or ./test-ghactions.sh +./test-ghactions.sh -neuron # includes NEURON examples + +# Run pytest only (skips tests marked localonly — they segfault on CI) +pytest -m "not localonly" + +# Run a single test file +pytest tests/test_pynml.py + +# Run pre-commit hooks manually +pre-commit run --all-files +``` + +## Testing Quirks + +- `pyproject.toml` defines a `localonly` marker — tests with it are skipped on GitHub Actions because they segfault +- `test-ghactions.sh` is the authoritative test script; it installs the package, verifies all CLI tools, runs pytest, and executes examples +- Some tests require a display (matplotlib); they're guarded by `if [[ "$CI" != "true" ]]` +- NEURON examples require the `-neuron` flag and `nrniv` on PATH +- **Pytest logging**: `--log-level=DEBUG` captures logs but hides them for passing tests by default — use `-rP` to show. `--log-cli-level` does not work with xdist. + +## CI + +- **ci.yml** — matrix build on Python 3.9–3.13, runs `./test-ghactions.sh -neuron` +- **ruff.yml** — ruff check on PRs (changed files only) +- **python-publish.yml** — PyPI publishing + +## Conventions + +- **Be concise**: no fluff, no explanations, no summaries of what was done — just the answer. +- **No unicode characters in code**: use ASCII only in comments and strings. +- **Branch**: development is the working branch; master is stable +- **Ruff config**: ignores `F403`, `F405` (wildcard imports); excludes `examples/` +- **mypy**: `ignore_missing_imports = True` (minimal type checking) +- **Pre-commit**: trailing whitespace, EOF fixer, large file check (<5MB), ruff import sort + format +- **Python support**: 3.9–3.13 + +## Session Continuity + +- Check `.agents/` for prior session logs (`YYYY-MM-DD.md`) at session start +- Use the template in `.agents/Readme.md` for new session summaries + +## Dependencies + +- **External**: Java (JRE) for jNeuroML, Graphviz (`dot`) for diagrams +- **Optional backends**: NEURON, Brian2, NetPyNE, Tellurium (installed via extras like `[neuron]`, `[brian]`, etc.) + +## References + +- `setup.cfg` — authoritative source for entry points, extras, and dependencies +- `pyproject.toml` — pytest, ruff, and coverage config +- `test-ghactions.sh` — full integration test flow diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 00000000..47dc3e3d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/LICENSE.lesser b/LICENSE.lesser index 341c30bd..65c5ca88 100644 --- a/LICENSE.lesser +++ b/LICENSE.lesser @@ -163,4 +163,3 @@ whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. - diff --git a/README.md b/README.md index 3765c912..553adf7d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ A single package in Python unifying scripts and modules for reading, writing, si Builds on: [libNeuroML](https://github.com/NeuralEnsemble/libNeuroML) & [PyLEMS](https://github.com/LEMS/pylems) and wraps functionality from [jNeuroML](https://github.com/NeuroML/jNeuroML). -Installation +Installation ------------ ### Dependencies diff --git a/docs/source/_static/pynml_jnml.svg b/docs/source/_static/pynml_jnml.svg index 2cef3dd4..83ac4d90 100644 --- a/docs/source/_static/pynml_jnml.svg +++ b/docs/source/_static/pynml_jnml.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/docs/source/pyneuroml.analysis.rst b/docs/source/pyneuroml.analysis.rst index fb0bc350..1b80fab7 100644 --- a/docs/source/pyneuroml.analysis.rst +++ b/docs/source/pyneuroml.analysis.rst @@ -29,4 +29,3 @@ pyneuroml.analysis.ChannelHelper module :members: :undoc-members: :show-inheritance: - diff --git a/docs/source/pyneuroml.channelml.rst b/docs/source/pyneuroml.channelml.rst index eb3a7a30..3683601f 100644 --- a/docs/source/pyneuroml.channelml.rst +++ b/docs/source/pyneuroml.channelml.rst @@ -5,4 +5,3 @@ pyneuroml.channelml package :members: :undoc-members: :show-inheritance: - diff --git a/docs/source/pyneuroml.neuron.rst b/docs/source/pyneuroml.neuron.rst index 24b2808a..691b683f 100644 --- a/docs/source/pyneuroml.neuron.rst +++ b/docs/source/pyneuroml.neuron.rst @@ -13,4 +13,3 @@ pyneuroml.neuron.analysis module :members: :undoc-members: :show-inheritance: - diff --git a/docs/source/pyneuroml.povray.rst b/docs/source/pyneuroml.povray.rst index 4a78cc28..2df0c901 100644 --- a/docs/source/pyneuroml.povray.rst +++ b/docs/source/pyneuroml.povray.rst @@ -29,4 +29,3 @@ pyneuroml.povray.OverlaySimulation module :members: :undoc-members: :show-inheritance: - diff --git a/docs/source/pyneuroml.swc.rst b/docs/source/pyneuroml.swc.rst index 928f51fd..2f084369 100644 --- a/docs/source/pyneuroml.swc.rst +++ b/docs/source/pyneuroml.swc.rst @@ -21,3 +21,11 @@ pyneuroml.swc.ExportSWC module :members: :undoc-members: :show-inheritance: + +pyneuroml.swc.ExportNML module +------------------------------ + +.. automodule:: pyneuroml.swc.ExportNML + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pyneuroml.utils.rst b/docs/source/pyneuroml.utils.rst index 8647c8c0..63c3f9ce 100644 --- a/docs/source/pyneuroml.utils.rst +++ b/docs/source/pyneuroml.utils.rst @@ -6,18 +6,26 @@ pyneuroml.utils package :undoc-members: :show-inheritance: -pyneuroml.utils.info module +pyneuroml.utils.cli module --------------------------- -.. automodule:: pyneuroml.utils.info +.. automodule:: pyneuroml.utils.cli :members: :undoc-members: :show-inheritance: -pyneuroml.utils.plot module +pyneuroml.utils.components module +---------------------------------- + +.. automodule:: pyneuroml.utils.components + :members: + :undoc-members: + :show-inheritance: + +pyneuroml.utils.info module --------------------------- -.. automodule:: pyneuroml.utils.plot +.. automodule:: pyneuroml.utils.info :members: :undoc-members: :show-inheritance: @@ -30,10 +38,18 @@ pyneuroml.utils.misc module :undoc-members: :show-inheritance: -pyneuroml.utils.cli module +pyneuroml.utils.plot module --------------------------- -.. automodule:: pyneuroml.utils.cli +.. automodule:: pyneuroml.utils.plot + :members: + :undoc-members: + :show-inheritance: + +pyneuroml.utils.simdata module +------------------------------- + +.. automodule:: pyneuroml.utils.simdata :members: :undoc-members: :show-inheritance: diff --git a/docs/source/refs.bib b/docs/source/refs.bib index 0eba5e03..d6e55e0b 100644 --- a/docs/source/refs.bib +++ b/docs/source/refs.bib @@ -20,4 +20,3 @@ @Article{Vella2014 timestamp = {2019-02-20}, year = {2014}, } - diff --git a/examples/IM.channel.nml b/examples/IM.channel.nml index 7a79e341..354adec6 100644 --- a/examples/IM.channel.nml +++ b/examples/IM.channel.nml @@ -6,25 +6,25 @@ Slow M-type K+ current for spike frequency adaptation - + Comment from original mod file: M-current, responsible for the adaptation of firing rate and the afterhyperpolarization (AHP) of cortical pyramidal cells First-order model described by hodgkin-Hyxley like equations. K+ current, activated by depolarization, noninactivating. -Model taken from Yamada, W.M., Koch, C. and Adams, P.R. Multiple channels and calcium dynamics. In: Methods in Neuronal Modeling, +Model taken from Yamada, W.M., Koch, C. and Adams, P.R. Multiple channels and calcium dynamics. In: Methods in Neuronal Modeling, edited by C. Koch and I. Segev, MIT press, 1989, p 97-134. - -See also: McCormick, D.A., Wang, Z. and Huguenard, J. Neurotransmitter control of neocortical neuronal activity and excitability. + +See also: McCormick, D.A., Wang, Z. and Huguenard, J. Neurotransmitter control of neocortical neuronal activity and excitability. Cerebral Cortex 3: 387-398, 1993. Written by Alain Destexhe, Laval University, 1995 - + - + Minimal Hodgkin-Huxley type models for different classes of cortical and thalamic neurons @@ -32,7 +32,7 @@ Written by Alain Destexhe, Laval University, 1995 - + K channels @@ -48,7 +48,7 @@ Written by Alain Destexhe, Laval University, 1995 - + diff --git a/examples/KConductance.channel.nml b/examples/KConductance.channel.nml index 008ec9da..1d7f046d 100644 --- a/examples/KConductance.channel.nml +++ b/examples/KConductance.channel.nml @@ -1,7 +1,7 @@ - Channel file containing a single channel description @@ -9,11 +9,11 @@ HH K Channel - + - + A. L. Hodgkin and A. F. Huxley, A quantitative description of membrane current and its application @@ -22,7 +22,7 @@ - + K channels @@ -38,7 +38,7 @@ - + diff --git a/examples/Kd.channel.nml b/examples/Kd.channel.nml index 426a004e..0ebfb5d0 100644 --- a/examples/Kd.channel.nml +++ b/examples/Kd.channel.nml @@ -6,7 +6,7 @@ Delayed rectifier K+ current based on Traub and Miles 1991. - + Comment from original mod file: Hippocampal HH channels Fast Na+ and K+ currents responsible for action potentials Iterative equations @@ -16,11 +16,11 @@ Equations modified by Traub, for Hippocampal Pyramidal cells, in: Traub and Mile - range variable vtraub adjust threshold - Written by Alain Destexhe, Salk Institute, Aug 1992 - Modified Oct 96 for compatibility with Windows: trap low values of arguments - + - + Minimal Hodgkin-Huxley type models for different classes of cortical and thalamic neurons @@ -28,7 +28,7 @@ Equations modified by Traub, for Hippocampal Pyramidal cells, in: Traub and Mile - + K channels @@ -44,7 +44,7 @@ Equations modified by Traub, for Hippocampal Pyramidal cells, in: Traub and Mile - + diff --git a/examples/LEMS_NML2_Ex5_DetCell.xml b/examples/LEMS_NML2_Ex5_DetCell.xml index 2a6b681b..504f123d 100644 --- a/examples/LEMS_NML2_Ex5_DetCell.xml +++ b/examples/LEMS_NML2_Ex5_DetCell.xml @@ -3,8 +3,8 @@ @@ -23,7 +23,7 @@ - + @@ -42,20 +42,20 @@ - - + + - - - + + + - - - - - - + + + + + + - \ No newline at end of file + diff --git a/examples/LEMS_NML2_Ex9_FN.xml b/examples/LEMS_NML2_Ex9_FN.xml index 2ca5f070..65dc3802 100644 --- a/examples/LEMS_NML2_Ex9_FN.xml +++ b/examples/LEMS_NML2_Ex9_FN.xml @@ -2,15 +2,15 @@ - @@ -41,13 +41,13 @@ - + - - - + + + - \ No newline at end of file + diff --git a/examples/LeakConductance.channel.nml b/examples/LeakConductance.channel.nml index 08a45def..aad5c5a6 100644 --- a/examples/LeakConductance.channel.nml +++ b/examples/LeakConductance.channel.nml @@ -1,7 +1,7 @@ - Channel file containing a single Channel description diff --git a/examples/LeakConductance.mod b/examples/LeakConductance.mod index b2eb98ce..ebbdfabb 100644 --- a/examples/LeakConductance.mod +++ b/examples/LeakConductance.mod @@ -3,9 +3,9 @@ TITLE Mod file for component: Component(id=LeakConductance type=ionChannelHH) COMMENT This NEURON file has been generated by org.neuroml.export (see https://github.com/NeuroML/org.neuroml.export) - org.neuroml.export v1.10.1 - org.neuroml.model v1.10.1 - jLEMS v0.11.1 + org.neuroml.export v1.11.0 + org.neuroml.model v1.11.0 + jLEMS v0.12.0 ENDCOMMENT diff --git a/examples/NML2_SingleCompHHCell.nml b/examples/NML2_SingleCompHHCell.nml index e25e859d..225aa8ab 100644 --- a/examples/NML2_SingleCompHHCell.nml +++ b/examples/NML2_SingleCompHHCell.nml @@ -1,19 +1,19 @@ - - - - - + + + + - - + + @@ -33,7 +33,7 @@ - + @@ -61,4 +61,3 @@ - diff --git a/examples/NaConductance.channel.nml b/examples/NaConductance.channel.nml index adbac6cd..42d24501 100644 --- a/examples/NaConductance.channel.nml +++ b/examples/NaConductance.channel.nml @@ -1,7 +1,7 @@ - Channel file containing a single Channel description @@ -9,20 +9,20 @@ HH Na Channel - + - + - A. L. Hodgkin and A. F. Huxley, A quantitative description of membrane current and + A. L. Hodgkin and A. F. Huxley, A quantitative description of membrane current and its application to conduction and excitation in nerve, J. Physiol., vol. 117, pp. 500-544, 1952. - + Na channels @@ -43,7 +43,7 @@ - + diff --git a/examples/NaConductance2.mod b/examples/NaConductance2.mod index 85a08e59..7343424f 100644 --- a/examples/NaConductance2.mod +++ b/examples/NaConductance2.mod @@ -1,7 +1,7 @@ COMMENT ************************************************** - File generated by: neuroConstruct v1.2.3 + File generated by: neuroConstruct v1.2.3 ************************************************** @@ -34,165 +34,165 @@ UNITS { } - + NEURON { - + SUFFIX NaConductance2 USEION na READ ena WRITE ina VALENCE 1 ? reversal potential of ion is read, outgoing current is written - - + + RANGE gmax, gion - + RANGE minf, mtau - + RANGE hinf, htau - + } -PARAMETER { - +PARAMETER { + gmax = 0.12 (S/cm2) ? default value, should be overwritten when conductance placed on cell - + } ASSIGNED { - + v (mV) - + celsius (degC) - + ? Reversal potential of na ena (mV) ? The outward flow of ion: na calculated by rate equations... ina (mA/cm2) - - + + gion (S/cm2) minf mtau (ms) hinf htau (ms) - + } -BREAKPOINT { - +BREAKPOINT { + SOLVE states METHOD cnexp - - gion = gmax*((m)^3)*((h)^1) + + gion = gmax*((m)^3)*((h)^1) ina = gion*(v - ena) - + } INITIAL { - + ena = 50 - + rates(v) m = minf - + h = hinf - - - + + + } - + STATE { m h - + } DERIVATIVE states { rates(v) m' = (minf - m)/mtau h' = (hinf - h)/htau - + } -PROCEDURE rates(v(mV)) { - +PROCEDURE rates(v(mV)) { + ? Note: not all of these may be used, depending on the form of rate equations LOCAL alpha, beta, tau, inf, gamma, zeta, temp_adj_m, A_alpha_m, B_alpha_m, Vhalf_alpha_m, A_beta_m, B_beta_m, Vhalf_beta_m, temp_adj_h, A_alpha_h, B_alpha_h, Vhalf_alpha_h, A_beta_h, B_beta_h, Vhalf_beta_h - + TABLE minf, mtau,hinf, htau DEPEND celsius FROM -100 TO 100 WITH 400 - - + + UNITSOFF temp_adj_m = 1 temp_adj_h = 1 - - - - - + + + + + ? *** Adding rate equations for gate: m *** - + ? Found a parameterised form of rate equation for alpha, using expression: A*((v-Vhalf)/B) / (1 - exp(-((v-Vhalf)/B))) A_alpha_m = 1 B_alpha_m = 10 - Vhalf_alpha_m = -40 + Vhalf_alpha_m = -40 alpha = A_alpha_m * vtrap((v - Vhalf_alpha_m), B_alpha_m) - - + + ? Found a parameterised form of rate equation for beta, using expression: A*exp((v-Vhalf)/B) A_beta_m = 4 B_beta_m = -18 - Vhalf_beta_m = -65 + Vhalf_beta_m = -65 beta = A_beta_m * exp((v - Vhalf_beta_m) / B_beta_m) - + mtau = 1/(temp_adj_m*(alpha + beta)) minf = alpha/(alpha + beta) - - - + + + ? *** Finished rate equations for gate: m *** - - - - - - + + + + + + ? *** Adding rate equations for gate: h *** - + ? Found a parameterised form of rate equation for alpha, using expression: A*exp((v-Vhalf)/B) A_alpha_h = 0.07 B_alpha_h = -20 - Vhalf_alpha_h = -65 + Vhalf_alpha_h = -65 alpha = A_alpha_h * exp((v - Vhalf_alpha_h) / B_alpha_h) - - + + ? Found a parameterised form of rate equation for beta, using expression: A / (1 + exp((v-Vhalf)/B)) A_beta_h = 1 B_beta_h = -10 - Vhalf_beta_h = -35 + Vhalf_beta_h = -35 beta = A_beta_h / (exp((v - Vhalf_beta_h) / B_beta_h) + 1) - + htau = 1/(temp_adj_h*(alpha + beta)) hinf = alpha/(alpha + beta) - - - + + + ? *** Finished rate equations for gate: h *** - - + + } @@ -208,5 +208,3 @@ FUNCTION vtrap(VminV0, B) { } UNITSON - - diff --git a/examples/analyseNaMod.sh b/examples/analyseNaMod.sh index c862fcb5..12428dcf 100755 --- a/examples/analyseNaMod.sh +++ b/examples/analyseNaMod.sh @@ -1,5 +1,5 @@ pynml-modchananalysis -stepV 5 NaConductance2 -dt 0.01 -temperature 22 # Uses https://github.com/NeuralEnsemble/neuroConstruct/blob/master/nCplot.sh -ncpl -b NaConductance2.m.tau.dat NaConductance2.h.tau.dat test/mtau_NaConductance.dat test/htau_NaConductance.dat & +ncpl -b NaConductance2.m.tau.dat NaConductance2.h.tau.dat test/mtau_NaConductance.dat test/htau_NaConductance.dat & ncpl -b NaConductance2.m.inf.dat NaConductance2.h.inf.dat test/minf_NaConductance.dat test/hinf_NaConductance.dat & diff --git a/examples/command_execute_tests.py b/examples/command_execute_tests.py new file mode 100644 index 00000000..253b8937 --- /dev/null +++ b/examples/command_execute_tests.py @@ -0,0 +1,17 @@ +from pyneuroml import pynml + +run_dir = '.' + +commands = ['pwd', 'ls -alt testss'] + +for command in commands: + + print("\n====================\n") + + returncode, output = pynml.execute_command_in_dir(command, run_dir, prefix="Output [%s] > "%command, verbose=True) + + print(' ---- Return code from execute_command_in_dir: %s; output: \n%s\n--------------------------'%(returncode, output)) + + success = pynml.execute_command_in_dir_with_realtime_output(command, run_dir, prefix="Output [%s]: "%command, verbose=False) + + print(' ---- Success of execute_command_in_dir_with_realtime_output: %s'%success) diff --git a/examples/test.hoc b/examples/test.hoc index 97b1ef87..60d6b280 100644 --- a/examples/test.hoc +++ b/examples/test.hoc @@ -37,5 +37,3 @@ mainDendSec { forall insert pas forall psection() - - diff --git a/examples/test_data/Ca_pyr.channel.nml b/examples/test_data/Ca_pyr.channel.nml index abc098e6..e732923e 100644 --- a/examples/test_data/Ca_pyr.channel.nml +++ b/examples/test_data/Ca_pyr.channel.nml @@ -6,11 +6,11 @@ NeuroML file containing a single Calcium Channel description, from the Hippocampal CA3 neuron model presented in Traub et al., 1991. - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + Ca channels @@ -39,7 +39,7 @@ - + diff --git a/examples/test_data/EGL-36.channel.nml b/examples/test_data/EGL-36.channel.nml index 06684229..e3c07937 100644 --- a/examples/test_data/EGL-36.channel.nml +++ b/examples/test_data/EGL-36.channel.nml @@ -1,6 +1,6 @@ - + @@ -12,7 +12,7 @@ - diff --git a/examples/test_data/HHCellNetwork.net.nml b/examples/test_data/HHCellNetwork.net.nml index 94ac0a9e..604054a1 100644 --- a/examples/test_data/HHCellNetwork.net.nml +++ b/examples/test_data/HHCellNetwork.net.nml @@ -2,11 +2,11 @@ Network of 1 cell with Hodgkin Huxley cell and 2 input currents - + @@ -18,4 +18,3 @@ - diff --git a/examples/test_data/Kahp_pyr.channel.nml b/examples/test_data/Kahp_pyr.channel.nml index 5b214c90..8cabba46 100644 --- a/examples/test_data/Kahp_pyr.channel.nml +++ b/examples/test_data/Kahp_pyr.channel.nml @@ -6,11 +6,11 @@ NeuroML file containing a single Calcium-dependent Potassium Channel description, from the Hippocampal CA3 neuron model presented in Traub et al., 1991. - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + K channels @@ -34,7 +34,7 @@ - + diff --git a/examples/test_data/Kdr_bask.channel.nml b/examples/test_data/Kdr_bask.channel.nml index dcee4730..557ab64c 100644 --- a/examples/test_data/Kdr_bask.channel.nml +++ b/examples/test_data/Kdr_bask.channel.nml @@ -6,11 +6,11 @@ NeuroML file containing a single Potassium Channel description, from the book Neuronal Networks of the Hippocampus, Traub and Miles 1991 - + - + Traub, R. D., & Miles, R. (1991). Neuronal Networks of the Hippocampus. Cambridge University Press. @@ -18,7 +18,7 @@ - + K channels @@ -34,7 +34,7 @@ - + diff --git a/examples/test_data/Kdr_pyr.channel.nml b/examples/test_data/Kdr_pyr.channel.nml index f89ac54c..2d8d1be9 100644 --- a/examples/test_data/Kdr_pyr.channel.nml +++ b/examples/test_data/Kdr_pyr.channel.nml @@ -6,11 +6,11 @@ NeuroML file containing a single Potassium Channel description, from the Hippocampal CA3 neuron model presented in Traub et al., 1991. - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + K channels @@ -34,7 +34,7 @@ - + diff --git a/examples/test_data/LEMS_HH_Simulation.xml b/examples/test_data/LEMS_HH_Simulation.xml index 75ca8718..3ffb943c 100644 --- a/examples/test_data/LEMS_HH_Simulation.xml +++ b/examples/test_data/LEMS_HH_Simulation.xml @@ -3,8 +3,8 @@ @@ -23,19 +23,19 @@ - + - + - - - - + + + + - \ No newline at end of file + diff --git a/examples/test_data/LeakConductance_bask.channel.nml b/examples/test_data/LeakConductance_bask.channel.nml index b5d5b563..c3560079 100644 --- a/examples/test_data/LeakConductance_bask.channel.nml +++ b/examples/test_data/LeakConductance_bask.channel.nml @@ -6,7 +6,7 @@ Passive conductance for basket cell - + diff --git a/examples/test_data/LeakConductance_pyr.channel.nml b/examples/test_data/LeakConductance_pyr.channel.nml index 843dcca8..4d36edd3 100644 --- a/examples/test_data/LeakConductance_pyr.channel.nml +++ b/examples/test_data/LeakConductance_pyr.channel.nml @@ -6,7 +6,7 @@ Passive conductance for pyramidal cell - + diff --git a/examples/test_data/NML2_FullCell.nml b/examples/test_data/NML2_FullCell.nml index fffc74f5..4ab6a84c 100644 --- a/examples/test_data/NML2_FullCell.nml +++ b/examples/test_data/NML2_FullCell.nml @@ -5,19 +5,19 @@ xmlns:xi="http://www.w3.org/2001/XInclude" xsi:schemaLocation="http://www.neuroml.org/schema/neuroml2 ../Schemas/NeuroML2/NeuroML_v2beta4.xsd" id="NML2_FullCell"> - + - + - + - + A Simple Spiking cell for testing purposes @@ -54,7 +54,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -81,7 +81,7 @@ - + diff --git a/examples/test_data/NML2_SimpleIonChannel.nml b/examples/test_data/NML2_SimpleIonChannel.nml index 83864f42..a7cfcaa0 100644 --- a/examples/test_data/NML2_SimpleIonChannel.nml +++ b/examples/test_data/NML2_SimpleIonChannel.nml @@ -3,10 +3,10 @@ + id="NML2_SimpleIonChannel"> - + diff --git a/examples/test_data/Na_bask.channel.nml b/examples/test_data/Na_bask.channel.nml index 932d4155..11ab3a65 100644 --- a/examples/test_data/Na_bask.channel.nml +++ b/examples/test_data/Na_bask.channel.nml @@ -6,11 +6,11 @@ NeuroML file containing a single Sodium Channel description, from the book Neuronal Networks of the Hippocampus, Traub and Miles 1991 - + - + Traub, R. D., & Miles, R. (1991). Neuronal Networks of the Hippocampus. Cambridge University Press. @@ -18,7 +18,7 @@ - + Na channels @@ -39,7 +39,7 @@ - + diff --git a/examples/test_data/Na_pyr.channel.nml b/examples/test_data/Na_pyr.channel.nml index 7702bed8..5e1d251c 100644 --- a/examples/test_data/Na_pyr.channel.nml +++ b/examples/test_data/Na_pyr.channel.nml @@ -6,11 +6,11 @@ NeuroML file containing a single Sodium Channel description, from the Hippocampal CA3 neuron model presented in Traub et al., 1991. - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + Na channels @@ -39,7 +39,7 @@ - + diff --git a/examples/test_data/Purk2M9s.nml b/examples/test_data/Purk2M9s.nml index 511ab43e..ecf4d680 100644 --- a/examples/test_data/Purk2M9s.nml +++ b/examples/test_data/Purk2M9s.nml @@ -20825,10 +20825,10 @@ - + - + diff --git a/examples/test_data/TwoCell.net.nml b/examples/test_data/TwoCell.net.nml index 5b597dfc..695ef328 100644 --- a/examples/test_data/TwoCell.net.nml +++ b/examples/test_data/TwoCell.net.nml @@ -48,7 +48,7 @@ Cell Group: baskets contains 1 cells - + diff --git a/examples/test_data/bask.cell.nml b/examples/test_data/bask.cell.nml index b82ab581..74d0f895 100644 --- a/examples/test_data/bask.cell.nml +++ b/examples/test_data/bask.cell.nml @@ -26,7 +26,7 @@ @@ -34,7 +34,7 @@ @@ -55,7 +55,7 @@ - + @@ -63,13 +63,13 @@ - + - + - + - + @@ -88,5 +88,5 @@ - + diff --git a/examples/test_data/ca1/LEMS_SimTestOLMChannels.xml b/examples/test_data/ca1/LEMS_SimTestOLMChannels.xml index 83b6f6a4..94206351 100644 --- a/examples/test_data/ca1/LEMS_SimTestOLMChannels.xml +++ b/examples/test_data/ca1/LEMS_SimTestOLMChannels.xml @@ -1,11 +1,11 @@ - - - + @@ -13,7 +13,7 @@ - + @@ -21,9 +21,9 @@ - + - + @@ -58,7 +58,7 @@ - + @@ -69,146 +69,146 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/examples/test_data/ca1/channels/HCNolm.channel.nml b/examples/test_data/ca1/channels/HCNolm.channel.nml index 8e6ccbc6..e197dd6e 100755 --- a/examples/test_data/ca1/channels/HCNolm.channel.nml +++ b/examples/test_data/ca1/channels/HCNolm.channel.nml @@ -4,21 +4,21 @@ NeuroML file containing a single ion channel - + Hyperpolarization-activated, CN-gated h channel description (from Saraga 2003, Lawrence 2006 and Cutsuridis 2010) - + - + - - + + - + diff --git a/examples/test_data/ca1/channels/Kdrfast.channel.nml b/examples/test_data/ca1/channels/Kdrfast.channel.nml index ac0133b8..57d73176 100755 --- a/examples/test_data/ca1/channels/Kdrfast.channel.nml +++ b/examples/test_data/ca1/channels/Kdrfast.channel.nml @@ -4,30 +4,30 @@ NeuroML file containing a single ion channel - + Fast delayed rectifier K+ channel description (from Yuen and Durand 1991, modeled by Aradi and Holmes 1999, modified by Marianne Bezaire) - + - + - - + + - + - + - - + + - + - + diff --git a/examples/test_data/ca1/channels/KvAolm.channel.nml b/examples/test_data/ca1/channels/KvAolm.channel.nml index b8d00ad5..530dad0b 100755 --- a/examples/test_data/ca1/channels/KvAolm.channel.nml +++ b/examples/test_data/ca1/channels/KvAolm.channel.nml @@ -1,35 +1,35 @@ - + NeuroML file containing a single ion channel - + A-type K+ channel description (from Zhang and McBain 1995, Martina 1998, Warman 1994 - modeled by Saraga 2003, Cutsuridis 2010) - + - + - + - - + + - + - + @@ -38,5 +38,5 @@ - + diff --git a/examples/test_data/ca1/channels/Nav.channel.nml b/examples/test_data/ca1/channels/Nav.channel.nml index 227eb3b7..22c3c65e 100755 --- a/examples/test_data/ca1/channels/Nav.channel.nml +++ b/examples/test_data/ca1/channels/Nav.channel.nml @@ -4,37 +4,37 @@ NeuroML file containing a single ion channel - + Na+ channel description (modeled by Yuen and Durand 1991, modified by Aradi and Holmes 1999) - + - - + + - + - - + + - + - - + + - + - + - - - + + + - + - + diff --git a/examples/test_data/ca1/channels/leak_chan.channel.nml b/examples/test_data/ca1/channels/leak_chan.channel.nml index f831bbed..a8bd6748 100755 --- a/examples/test_data/ca1/channels/leak_chan.channel.nml +++ b/examples/test_data/ca1/channels/leak_chan.channel.nml @@ -4,5 +4,5 @@ NeuroML file containing a single passive Channel description - + diff --git a/examples/test_data/hhcell.cell.nml b/examples/test_data/hhcell.cell.nml index 2d5930ea..d39424ef 100644 --- a/examples/test_data/hhcell.cell.nml +++ b/examples/test_data/hhcell.cell.nml @@ -2,7 +2,7 @@ @@ -28,7 +28,7 @@ - + @@ -49,4 +49,3 @@ - diff --git a/examples/test_data/kChan.channel.nml b/examples/test_data/kChan.channel.nml index 5c81c9e5..976791e7 100644 --- a/examples/test_data/kChan.channel.nml +++ b/examples/test_data/kChan.channel.nml @@ -2,21 +2,20 @@ - + Single ion channel in NeuroML2 format: standard Potassium channel from the Hodgkin Huxley model - + - diff --git a/examples/test_data/naChan.channel.nml b/examples/test_data/naChan.channel.nml index 15713a92..3e1dfac2 100644 --- a/examples/test_data/naChan.channel.nml +++ b/examples/test_data/naChan.channel.nml @@ -2,12 +2,12 @@ - + - + Single ion channel in NeuroML2 format: standard Sodium channel from the Hodgkin Huxley model @@ -24,4 +24,3 @@ - diff --git a/examples/test_data/passiveChan.channel.nml b/examples/test_data/passiveChan.channel.nml index b203d59c..07a21ad8 100644 --- a/examples/test_data/passiveChan.channel.nml +++ b/examples/test_data/passiveChan.channel.nml @@ -5,12 +5,11 @@ xsi:schemaLocation="http://www.neuroml.org/schema/neuroml2 https://raw.githubusercontent.com/NeuroML/NeuroML2/master/Schemas/NeuroML2/NeuroML_v2beta3.xsd" id="passiveChan"> - + - + Single ion channel in NeuroML2 format: passive channel providing a leak conductance - + - diff --git a/examples/test_data/pyr_4_sym.cell.nml b/examples/test_data/pyr_4_sym.cell.nml index dda62784..381e1d92 100644 --- a/examples/test_data/pyr_4_sym.cell.nml +++ b/examples/test_data/pyr_4_sym.cell.nml @@ -74,7 +74,7 @@ @@ -82,7 +82,7 @@ @@ -90,7 +90,7 @@ @@ -98,7 +98,7 @@ @@ -106,7 +106,7 @@ @@ -114,7 +114,7 @@ @@ -122,7 +122,7 @@ @@ -130,7 +130,7 @@ @@ -138,7 +138,7 @@ @@ -203,7 +203,7 @@ - + @@ -211,17 +211,17 @@ - + - + - + - + - + - + @@ -242,5 +242,5 @@ - + diff --git a/examples/test_data/xppaut/fhn.ode b/examples/test_data/xppaut/fhn.ode index ea89bb51..0407a203 100755 --- a/examples/test_data/xppaut/fhn.ode +++ b/examples/test_data/xppaut/fhn.ode @@ -1,4 +1,4 @@ -# Forced Fitzhugh-Nagumo fhn.ode +# Forced Fitzhugh-Nagumo fhn.ode dv/dt = f(v)-w+s(t)+I_0 dw/dt = eps*(v-gamma*w) f(v)=v*(1-v)*(v-a) diff --git a/examples/test_data/xppaut/nca.ode b/examples/test_data/xppaut/nca.ode index f43e003f..1fbe8cb9 100644 --- a/examples/test_data/xppaut/nca.ode +++ b/examples/test_data/xppaut/nca.ode @@ -8,7 +8,7 @@ number thetam=-30.0,sigmam=9.5,sigmah=-7.0,sigman=10.0,sigmaz=5.0 number VCa=120 number thetar=-20.0,sigmar=10.0,thetac=-30,sigmac=7 number pwrc=1,pwrq=4 -# +# p gNa=35.0,gKdr=6.0,gL=0.05,Iapp=1.0 p gA=1.4,gNaP=0.2,gZ=1.0 p thetaz=-39.0,tauZs=75.0 @@ -44,7 +44,7 @@ IA=gA*Ainfs^3*bbs*(VVs-VK) Iz=gZ*zzs*(VVs-VK) ICa=gCa*rrs^2*(VVs-VCa) IKC=gKCa*mKCa*ccs*(VVs-VK) -IAHP=gKAHP*qqs*(VVs-VK) +IAHP=gKAHP*qqs*(VVs-VK) # VVs(0)=-71.962 hhs(0)=0.979199 diff --git a/examples/tune/Ca_pyr.channel.nml b/examples/tune/Ca_pyr.channel.nml index 141db360..acf2b34f 100644 --- a/examples/tune/Ca_pyr.channel.nml +++ b/examples/tune/Ca_pyr.channel.nml @@ -6,11 +6,11 @@ - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + Ca channels @@ -39,7 +39,7 @@ - + diff --git a/examples/tune/Kahp_pyr.channel.nml b/examples/tune/Kahp_pyr.channel.nml index 9f05401e..40f952be 100644 --- a/examples/tune/Kahp_pyr.channel.nml +++ b/examples/tune/Kahp_pyr.channel.nml @@ -6,11 +6,11 @@ - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + K channels @@ -34,7 +34,7 @@ - + diff --git a/examples/tune/Kdr_pyr.channel.nml b/examples/tune/Kdr_pyr.channel.nml index 5b8b95be..e13fbdd2 100644 --- a/examples/tune/Kdr_pyr.channel.nml +++ b/examples/tune/Kdr_pyr.channel.nml @@ -6,11 +6,11 @@ - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + K channels @@ -34,7 +34,7 @@ - + diff --git a/examples/tune/LEMS_OnePyr.xml b/examples/tune/LEMS_OnePyr.xml index 096e3375..3abf118f 100644 --- a/examples/tune/LEMS_OnePyr.xml +++ b/examples/tune/LEMS_OnePyr.xml @@ -8,7 +8,7 @@ - + @@ -24,74 +24,74 @@ - - - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + diff --git a/examples/tune/LeakConductance_pyr.channel.nml b/examples/tune/LeakConductance_pyr.channel.nml index 2b8f6db2..1908990f 100644 --- a/examples/tune/LeakConductance_pyr.channel.nml +++ b/examples/tune/LeakConductance_pyr.channel.nml @@ -7,7 +7,7 @@ Simple example of a leak/passive conductance. Note: for GENESIS cells with a single leak conductance, it is better to use the Rm and Em variables for a passive current. - + diff --git a/examples/tune/Na_pyr.channel.nml b/examples/tune/Na_pyr.channel.nml index 584b6d16..c1259258 100644 --- a/examples/tune/Na_pyr.channel.nml +++ b/examples/tune/Na_pyr.channel.nml @@ -6,11 +6,11 @@ - + - + Traub, R. D., Wong, R. K., Miles, R., and Michelson, H. (1991). A model of a CA3 hippocampal pyramidal neuron incorporating voltage-clamp data on intrinsic conductances. Journal of neurophysiology, 66(2), 635-50. @@ -18,7 +18,7 @@ - + Na channels @@ -39,7 +39,7 @@ - + diff --git a/examples/tune/OnePyr.net.nml b/examples/tune/OnePyr.net.nml index fbedeb7b..aa610c63 100644 --- a/examples/tune/OnePyr.net.nml +++ b/examples/tune/OnePyr.net.nml @@ -24,10 +24,10 @@ Cell Group: baskets contains 1 cells - + - + diff --git a/examples/tune/README.md b/examples/tune/README.md index 4324626b..c1cf4a77 100644 --- a/examples/tune/README.md +++ b/examples/tune/README.md @@ -7,15 +7,13 @@ To run the single cell example, install NEURON: jnml LEMS_OnePyr.xml -neuron nrnivmodl nrngui LEMS_OnePyr_nrn.py - + or: python tunePyr.py - + To (re)tune the cell: python tunePyr.py -tune - -![pic](https://raw.githubusercontent.com/NeuroML/pyNeuroML/master/examples/tune/Selection_817.jpg) - +![pic](https://raw.githubusercontent.com/NeuroML/pyNeuroML/master/examples/tune/Selection_817.jpg) diff --git a/examples/tune/pyr_4_sym.cell.nml b/examples/tune/pyr_4_sym.cell.nml index dda62784..381e1d92 100644 --- a/examples/tune/pyr_4_sym.cell.nml +++ b/examples/tune/pyr_4_sym.cell.nml @@ -74,7 +74,7 @@ @@ -82,7 +82,7 @@ @@ -90,7 +90,7 @@ @@ -98,7 +98,7 @@ @@ -106,7 +106,7 @@ @@ -114,7 +114,7 @@ @@ -122,7 +122,7 @@ @@ -130,7 +130,7 @@ @@ -138,7 +138,7 @@ @@ -203,7 +203,7 @@ - + @@ -211,17 +211,17 @@ - + - + - + - + - + - + @@ -242,5 +242,5 @@ - + diff --git a/install_local_java.sh b/install_local_java.sh index 534563a4..a3e9ab22 100755 --- a/install_local_java.sh +++ b/install_local_java.sh @@ -1,7 +1,7 @@ -if [ ! -d "jdk1.8.0_112" ] ; +if [ ! -d "jdk1.8.0_112" ] ; -then +then wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u112-b15/jdk-8u112-linux-x64.tar.gz tar xvzf jdk-8u112-linux-x64.tar.gz @@ -13,4 +13,3 @@ export JAVA_HOME="`pwd`/jdk1.8.0_112" echo "Set JAVA_HOME to $JAVA_HOME" export PATH=$JAVA_HOME/bin:$PATH echo "Set PATH to $PATH" - diff --git a/man/man1/common.h2m b/man/man1/common.h2m index ddf51516..af0008da 100644 --- a/man/man1/common.h2m +++ b/man/man1/common.h2m @@ -11,6 +11,7 @@ .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP diff --git a/man/man1/pynml-archive.1 b/man/man1/pynml-archive.1 index 375576c6..e1883001 100644 --- a/man/man1/pynml-archive.1 +++ b/man/man1/pynml-archive.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-ARCHIVE "1" "July 2024" "pynml-archive v1.3.6" "User Commands" +.TH PYNML-ARCHIVE "1" "July 2025" "pynml-archive v1.3.22" "User Commands" .SH NAME -pynml-archive \- manual page for pynml-archive v1.3.6 +pynml-archive \- manual page for pynml-archive v1.3.22 .SH DESCRIPTION usage: pynml\-archive [\-h] [\-zipfileName ] .TP @@ -45,10 +45,11 @@ master file. .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-channelanalysis.1 b/man/man1/pynml-channelanalysis.1 index a2019837..d5a2e80e 100644 --- a/man/man1/pynml-channelanalysis.1 +++ b/man/man1/pynml-channelanalysis.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-CHANNELANALYSIS "1" "July 2024" "pynml-channelanalysis v1.3.6" "User Commands" +.TH PYNML-CHANNELANALYSIS "1" "July 2025" "pynml-channelanalysis v1.3.22" "User Commands" .SH NAME -pynml-channelanalysis \- manual page for pynml-channelanalysis v1.3.6 +pynml-channelanalysis \- manual page for pynml-channelanalysis v1.3.22 .SH DESCRIPTION usage: pynml\-channelanalysis [\-h] [\-v] [\-minV ] [\-maxV ] .TP @@ -105,10 +105,11 @@ plot current vs voltage for ion channel .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-channelml2nml.1 b/man/man1/pynml-channelml2nml.1 index db94ef3f..cbf1259b 100644 --- a/man/man1/pynml-channelml2nml.1 +++ b/man/man1/pynml-channelml2nml.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-CHANNELML2NML "1" "July 2024" "pynml-channelml2nml v1.3.6" "User Commands" +.TH PYNML-CHANNELML2NML "1" "July 2025" "pynml-channelml2nml v1.3.22" "User Commands" .SH NAME -pynml-channelml2nml \- manual page for pynml-channelml2nml v1.3.6 +pynml-channelml2nml \- manual page for pynml-channelml2nml v1.3.22 .SH DESCRIPTION usage: pynml\-channelml2nml [\-h] [\-xsltfile ] .TP @@ -36,10 +36,11 @@ Name of the outputfile file .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-modchananalysis.1 b/man/man1/pynml-modchananalysis.1 index 36ac288d..d486441b 100644 --- a/man/man1/pynml-modchananalysis.1 +++ b/man/man1/pynml-modchananalysis.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-MODCHANANALYSIS "1" "July 2024" "pynml-modchananalysis v1.3.6" "User Commands" +.TH PYNML-MODCHANANALYSIS "1" "July 2025" "pynml-modchananalysis v1.3.22" "User Commands" .SH NAME -pynml-modchananalysis \- manual page for pynml-modchananalysis v1.3.6 +pynml-modchananalysis \- manual page for pynml-modchananalysis v1.3.22 .SH DESCRIPTION usage: pynml\-modchananalysis [\-h] [\-v] [\-nogui] [\-savePlots] [\-minV ] .TP @@ -70,10 +70,11 @@ Name of the mod file containing the channel .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-plotchan.1 b/man/man1/pynml-plotchan.1 index df52326d..ce832057 100644 --- a/man/man1/pynml-plotchan.1 +++ b/man/man1/pynml-plotchan.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-PLOTCHAN "1" "July 2024" "pynml-plotchan v1.3.6" "User Commands" +.TH PYNML-PLOTCHAN "1" "July 2025" "pynml-plotchan v1.3.22" "User Commands" .SH NAME -pynml-plotchan \- manual page for pynml-plotchan v1.3.6 +pynml-plotchan \- manual page for pynml-plotchan v1.3.22 .SH DESCRIPTION usage: pynml\-plotchan [\-h] [\-noDistancePlots] [\-nogui] .IP @@ -36,10 +36,11 @@ Do not show plots as they are generated .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-plotmorph.1 b/man/man1/pynml-plotmorph.1 index 824326ab..ef9438df 100644 --- a/man/man1/pynml-plotmorph.1 +++ b/man/man1/pynml-plotmorph.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-PLOTMORPH "1" "July 2024" "pynml-plotmorph v1.3.6" "User Commands" +.TH PYNML-PLOTMORPH "1" "July 2025" "pynml-plotmorph v1.3.22" "User Commands" .SH NAME -pynml-plotmorph \- manual page for pynml-plotmorph v1.3.6 +pynml-plotmorph \- manual page for pynml-plotmorph v1.3.22 .SH DESCRIPTION usage: pynml\-plotmorph [\-h] [\-v] [\-nogui] [\-plane2d ] .TP @@ -10,14 +10,19 @@ usage: pynml\-plotmorph [\-h] [\-v] [\-nogui] [\-plane2d ] [\-theme ] [\-upright] [\-minWidth ] [\-interactive3d] -[\-saveToFile ] [\-square] - +[\-saveToFile ] +[\-saveMeshTo ] +[\-square] + .PP -A script which can generate plots of morphologies in NeuroML 2 +A script which can generate plots of morphologies in NeuroML 2. It can +generate plots of single cells (either detailed or point cells), and networks +that include these cells. It can also visualise single cell morphologies from +SWC files, although it will first convert these to NeuroML. .SS "positional arguments:" .TP - -Name of the NeuroML 2 file + +Name of the NeuroML 2 file/SWC cell file .SS "options:" .TP \fB\-h\fR, \fB\-\-help\fR @@ -58,6 +63,9 @@ Show interactive 3D plot \fB\-saveToFile\fR Name of the image file, for 2D plot .TP +\fB\-saveMeshTo\fR +Name of the file to save 3D mesh data to +.TP \fB\-square\fR Scale axes so that image is approximately square, for 2D plot @@ -74,10 +82,11 @@ Scale axes so that image is approximately square, for .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-plotspikes.1 b/man/man1/pynml-plotspikes.1 index 3f44d5fc..1707a87a 100644 --- a/man/man1/pynml-plotspikes.1 +++ b/man/man1/pynml-plotspikes.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-PLOTSPIKES "1" "July 2024" "pynml-plotspikes v1.3.6" "User Commands" +.TH PYNML-PLOTSPIKES "1" "July 2025" "pynml-plotspikes v1.3.22" "User Commands" .SH NAME -pynml-plotspikes \- manual page for pynml-plotspikes v1.3.6 +pynml-plotspikes \- manual page for pynml-plotspikes v1.3.22 .SH DESCRIPTION usage: pynml\-plotspikes [\-h] [\-format ] [\-offset] [\-rates] .TP @@ -58,10 +58,11 @@ Number of bins for rate histogram .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-plottimeseries.1 b/man/man1/pynml-plottimeseries.1 index d1f058d8..eb286ad4 100644 --- a/man/man1/pynml-plottimeseries.1 +++ b/man/man1/pynml-plottimeseries.1 @@ -1,10 +1,13 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-PLOTTIMESERIES "1" "July 2024" "pynml-plottimeseries v1.3.6" "User Commands" +.TH PYNML-PLOTTIMESERIES "1" "July 2025" "pynml-plottimeseries v1.3.22" "User Commands" .SH NAME -pynml-plottimeseries \- manual page for pynml-plottimeseries v1.3.6 +pynml-plottimeseries \- manual page for pynml-plottimeseries v1.3.22 .SH DESCRIPTION -usage: pynml\-plottimeseries [\-h] [\-offset] [\-saveToFile ] -.IP +usage: pynml\-plottimeseries [\-h] [\-columns [ ...]] +.TP +[\-labels] [\-offset] +[\-saveToFile ] + [ ...] .PP A script to plot time series data from data files or LEMS files @@ -18,8 +21,14 @@ series from \fB\-h\fR, \fB\-\-help\fR show this help message and exit .TP +\fB\-columns\fR [ ...] +column indices to plot if data files are provided +.TP +\fB\-labels\fR +Label plots +.TP \fB\-offset\fR -Toggle whether plots are overlaid or offset +Offset plots .TP \fB\-saveToFile\fR Name of the image file to save plot to @@ -36,10 +45,11 @@ Name of the image file to save plot to .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-povray.1 b/man/man1/pynml-povray.1 index 9b5ba017..f2cb7617 100644 --- a/man/man1/pynml-povray.1 +++ b/man/man1/pynml-povray.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-POVRAY "1" "July 2024" "pynml-povray v1.3.6" "User Commands" +.TH PYNML-POVRAY "1" "July 2025" "pynml-povray v1.3.22" "User Commands" .SH NAME -pynml-povray \- manual page for pynml-povray v1.3.6 +pynml-povray \- manual page for pynml-povray v1.3.22 .SH DESCRIPTION usage: pynml\-povray [\-h] [\-split] [\-background ] [\-movie] .TP @@ -107,10 +107,11 @@ Show segment ids .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-sonata.1 b/man/man1/pynml-sonata.1 index eba2520a..bb5d3882 100644 --- a/man/man1/pynml-sonata.1 +++ b/man/man1/pynml-sonata.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-SONATA "1" "July 2024" "pynml-sonata v1.3.6" "User Commands" +.TH PYNML-SONATA "1" "July 2025" "pynml-sonata v1.3.22" "User Commands" .SH NAME -pynml-sonata \- manual page for pynml-sonata v1.3.6 +pynml-sonata \- manual page for pynml-sonata v1.3.22 .SH DESCRIPTION usage: pynml\-sonata [\-h] [\-h5] [\-jnml] [\-neuron] .IP @@ -45,10 +45,11 @@ jNeuroML_NEURON .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-summary.1 b/man/man1/pynml-summary.1 index 13cc0a2f..bc748e7a 100644 --- a/man/man1/pynml-summary.1 +++ b/man/man1/pynml-summary.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-SUMMARY "1" "July 2024" "pynml-summary v1.3.6" "User Commands" +.TH PYNML-SUMMARY "1" "July 2025" "pynml-summary v1.3.22" "User Commands" .SH NAME -pynml-summary \- manual page for pynml-summary v1.3.6 +pynml-summary \- manual page for pynml-summary v1.3.22 .SH DESCRIPTION Usage: .PP @@ -30,10 +30,11 @@ print this help text and exit .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-swc2nml.1 b/man/man1/pynml-swc2nml.1 new file mode 100644 index 00000000..89243440 --- /dev/null +++ b/man/man1/pynml-swc2nml.1 @@ -0,0 +1,45 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. +.TH PYNML-SWC2NML "1" "July 2025" "pynml-swc2nml v1.3.22" "User Commands" +.SH NAME +pynml-swc2nml \- manual page for pynml-swc2nml v1.3.22 +.SH DESCRIPTION +usage: pynml\-swc2nml [\-h] [\-neuromlFile ] [\-morphOnly] +.IP + +.PP +Convert provided SWC file to NeuroML2 +.SS "positional arguments:" +.TP + +Name of the input SWC file +.SS "options:" +.TP +\fB\-h\fR, \fB\-\-help\fR +show this help message and exit +.TP +\fB\-neuromlFile\fR +Name of the output NeuroML file +.TP +\fB\-morphOnly\fR +Export as standalone Morphology, not as a Cell +.SH "SEE-ALSO" +.BR pynml (1), +.BR pynml-archive (1), +.BR pynml-channelanalysis (1), +.BR pynml-channelml2nml (1), +.BR pynml-modchananalysis (1), +.BR pynml-plotchan (1), +.BR pynml-plotmorph (1), +.BR pynml-plotspikes (1), +.BR pynml-plottimeseries (1), +.BR pynml-povray (1), +.BR pynml-sonata (1), +.BR pynml-summary (1), +.BR pynml-swc2nml (1), +.BR pynml-tune (1), +.BR pynml-xpp (1), +.PP +Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. +.SH ENVIRONMENT +.PP +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-tune.1 b/man/man1/pynml-tune.1 index 862aac34..cad48807 100644 --- a/man/man1/pynml-tune.1 +++ b/man/man1/pynml-tune.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-TUNE "1" "July 2024" "pynml-tune v1.3.6" "User Commands" +.TH PYNML-TUNE "1" "July 2025" "pynml-tune v1.3.22" "User Commands" .SH NAME -pynml-tune \- manual page for pynml-tune v1.3.6 +pynml-tune \- manual page for pynml-tune v1.3.22 .SH DESCRIPTION usage: pynml\-tune [\-h] [\-simTime ] [\-dt
] .IP @@ -143,10 +143,11 @@ as optimisation progresses? .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml-xpp.1 b/man/man1/pynml-xpp.1 index 44169cc7..a9e57cf9 100644 --- a/man/man1/pynml-xpp.1 +++ b/man/man1/pynml-xpp.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML-XPP "1" "July 2024" "pynml-xpp v1.3.6" "User Commands" +.TH PYNML-XPP "1" "July 2025" "pynml-xpp v1.3.22" "User Commands" .SH NAME -pynml-xpp \- manual page for pynml-xpp v1.3.6 +pynml-xpp \- manual page for pynml-xpp v1.3.22 .SH DESCRIPTION usage: pynml\-xpp [\-h] [\-xpp] [\-lems] [\-brian2] [\-run] [\-plot] .IP @@ -45,10 +45,11 @@ Plot saved variables .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/pynml.1 b/man/man1/pynml.1 index fddf2a1b..c116a207 100644 --- a/man/man1/pynml.1 +++ b/man/man1/pynml.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH PYNML "1" "July 2024" "pynml v1.3.6" "User Commands" +.TH PYNML "1" "July 2025" "pynml v1.3.22" "User Commands" .SH NAME -pynml \- manual page for pynml v1.3.6 +pynml \- manual page for pynml v1.3.22 .SH DESCRIPTION usage: pynml [\-h|\-\-help] [] .PP @@ -219,10 +219,11 @@ Load NeuroML file(s), and convert it to swc format .BR pynml-povray (1), .BR pynml-sonata (1), .BR pynml-summary (1), +.BR pynml-swc2nml (1), .BR pynml-tune (1), .BR pynml-xpp (1), .PP Please see https://docs.neuroml.org for complete documentation on the NeuroML standard and the software ecosystem. .SH ENVIRONMENT .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/man/man1/version.h2m b/man/man1/version.h2m index f338ef3f..d55be679 100644 --- a/man/man1/version.h2m +++ b/man/man1/version.h2m @@ -1,3 +1,3 @@ [environment] .PP -pyNeuroML v1.3.6 (libNeuroML v0.6.2, jNeuroML v0.13.2) +pyNeuroML v1.3.22 (libNeuroML v0.6.7, jNeuroML v0.14.0) diff --git a/pyneuroml/__init__.py b/pyneuroml/__init__.py index ce1ec3e0..5b7b9e1d 100644 --- a/pyneuroml/__init__.py +++ b/pyneuroml/__init__.py @@ -12,14 +12,23 @@ __version__ = importlib_metadata.version("pyNeuroML") -JNEUROML_VERSION = "0.13.3" +JNEUROML_VERSION = "0.14.0" -# Define a logger for the package -logging.basicConfig( - format="pyNeuroML >>> %(levelname)s - %(message)s", - level=logging.WARN, +logger = logging.getLogger(__name__) +logger.propagate = False +logger.setLevel(logging.INFO) + +ch = logging.StreamHandler() +# do not set level + +formatter = logging.Formatter( + "pyNeuroML >>> %(asctime)s - %(levelname)s - %(message)s", datefmt="%H:%M:%S" ) +ch.setFormatter(formatter) + +logger.addHandler(ch) + def print_v(msg): """Print message to console. diff --git a/pyneuroml/analysis/ChannelHelper.py b/pyneuroml/analysis/ChannelHelper.py index 0e086c2b..cac9d9d2 100644 --- a/pyneuroml/analysis/ChannelHelper.py +++ b/pyneuroml/analysis/ChannelHelper.py @@ -1,7 +1,7 @@ -from math import exp -from pyneuroml.pynml import get_value_in_si import logging +from math import exp +from pyneuroml.pynml import get_value_in_si logger = logging.getLogger(__name__) diff --git a/pyneuroml/analysis/ChannelInfo_TEMPLATE.html b/pyneuroml/analysis/ChannelInfo_TEMPLATE.html index c9e133e6..355af955 100644 --- a/pyneuroml/analysis/ChannelInfo_TEMPLATE.html +++ b/pyneuroml/analysis/ChannelInfo_TEMPLATE.html @@ -1,6 +1,6 @@ Channel information - +

${info}

@@ -20,7 +20,7 @@ ${channel.id} time course -#end## +#end##
diff --git a/pyneuroml/analysis/LEMS_Test_TEMPLATE.xml b/pyneuroml/analysis/LEMS_Test_TEMPLATE.xml index 5609ec96..14299f99 100644 --- a/pyneuroml/analysis/LEMS_Test_TEMPLATE.xml +++ b/pyneuroml/analysis/LEMS_Test_TEMPLATE.xml @@ -12,16 +12,16 @@ #foreach ($inc in $includes)## #end - + - - + + - + @@ -45,23 +45,23 @@ - - + + - + - + - + @@ -77,14 +77,14 @@ - + #foreach ($tv in $target_voltages)## -#end## - +#end## + #set( $duration_2 = 2 * $duration ) #set( $max_target_voltage_2 = 2 * $max_target_voltage - $min_target_voltage) @@ -92,13 +92,13 @@ - + - + #foreach ($tv in $target_voltages)## -#end## - +#end## + @@ -109,54 +109,54 @@ #set( $dt = 0.000025 * $duration * $scale_dt ) - + #foreach ($tv in $target_voltages)## -#end## +#end## #foreach ($tv in $target_voltages)## -#end## +#end## - + #foreach ($tv in $target_voltages)## -#end## +#end## #foreach ($g in $gates)## - + -#end## +#end## #foreach ($g in $gates)## - + - + -#end## +#end## #if ($iv_curve)## #foreach ($tv in $target_voltages)## - + -#end## -#end## +#end## +#end## - + diff --git a/pyneuroml/analysis/__init__.py b/pyneuroml/analysis/__init__.py index 880a8308..4b968694 100644 --- a/pyneuroml/analysis/__init__.py +++ b/pyneuroml/analysis/__init__.py @@ -1,25 +1,23 @@ +import logging import math import os -import logging import typing +from typing import Optional + +import neuroml as nml import numpy as np from pyneuroml import pynml -from pyneuroml.lems.LEMSSimulation import LEMSSimulation from pyneuroml.lems import generate_lems_file_for_neuroml -from pyneuroml.utils.plot import get_next_hex_color +from pyneuroml.lems.LEMSSimulation import LEMSSimulation from pyneuroml.plot import generate_plot -import neuroml as nml - -from typing import Optional - +from pyneuroml.utils.plot import get_next_hex_color logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) try: - from pyelectro.analysis import max_min - from pyelectro.analysis import mean_spike_frequency + from pyelectro.analysis import max_min, mean_spike_frequency except ImportError: logger.warning("Please install optional dependencies to use analysis features:") logger.warning("pip install pyneuroml[analysis]") @@ -516,8 +514,8 @@ def analyse_spiketime_vs_dt( save_figure_to=None, num_of_last_spikes=None, ): - from pyelectro.analysis import max_min import numpy as np + from pyelectro.analysis import max_min all_results = {} diff --git a/pyneuroml/annotations.py b/pyneuroml/annotations.py index 6bb36725..760a1583 100644 --- a/pyneuroml/annotations.py +++ b/pyneuroml/annotations.py @@ -119,6 +119,19 @@ def __init__(self): "modified_dates": DCTERMS.modified, } + self.foaf_supported_attributes = [ + "name", + "homepage", + "account", + "fundedBy", + "email", + "mbox", + "weblog", + "thumbnail", + "pubications", + "orcid", + ] + def create_annotation( self, subject: str, @@ -214,10 +227,14 @@ def create_annotation( See: https://rdflib.readthedocs.io/en/stable/plugin_serializers.html + Note that for xml formats, the xml is finally parsed through + lxml.etree to ensure compatibility with the rest of the + NeuroML/LEMS tool chain. + :type serialization_format: str :param xml_header: toggle inclusion of xml header if serializing in xml format :type xml_header: bool - :param indent: number of spaces to use to indent the annotation block + :param indent: number of spaces to use to indent the annotation block for xml :type indent: int :param description: a longer description :type description: str @@ -358,10 +375,6 @@ def create_annotation( annotation = self.doc.serialize(format=serialization_format) - # indent - if indent > 0: - annotation = textwrap.indent(annotation, " " * indent) - # xml issues if "xml" in serialization_format: # replace rdf:_1 etc with rdf:li @@ -375,14 +388,38 @@ def create_annotation( annotation = rdfbnode_pattern.sub("", annotation) # remove xml header, not used when embedding into other NeuroML files - if xml_header is False: - annotation = annotation[annotation.find(">") + 1 :] + # etree doesn't like it either for unicode strings + annotation = annotation[annotation.find(">") + 1 :] + + # put all the namespaces on one line + # jlems doesn't like multi-line tags + # https://github.com/LEMS/jLEMS/issues/127 + annotation_etree = etree.fromstring(annotation) + + annotation_str = ( + etree.tostring( + annotation_etree, pretty_print=True, xml_declaration=xml_header + ) + ).decode("utf-8") + + if write_to_file: + with open(write_to_file, "w") as f: + print(annotation_str, file=f) + + # indent + if indent > 0: + annotation_str = textwrap.indent(annotation_str, " " * indent) + + return annotation_str + + else: + annotation = self.doc.serialize(format=serialization_format) - if write_to_file: - with open(write_to_file, "w") as f: - print(annotation, file=f) + if write_to_file: + with open(write_to_file, "w") as f: + print(annotation, file=f) - return annotation + return annotation def _add_element( self, @@ -497,14 +534,22 @@ def _add_humans( # other fields for idf, label in info.items(): + if label not in self.foaf_supported_attributes: + logger.warning( + f"Not a supported FOAF attribute, Skipping {idf}: {label}." + ) + logger.warning( + f"Only {self.foaf_supported_attributes} FOAF attributes are currently supported by NeuroML/LEMS" + ) + continue + if label == "orcid": foaf_type = ORCID.id + elif label == "email": + foaf_type = getattr(FOAF, "mbox", None) else: foaf_type = getattr(FOAF, label, None) - if foaf_type is None: - logger.info("Not a FOAF attribute, using DC.identifier") - foaf_type = DC.identifier self.doc.add((top_node, foaf_type, _URIRef_or_Literal(idf))) elif annotation_style == "miriam": # top level node: creator/contributor etc. @@ -520,14 +565,22 @@ def _add_humans( # individual nodes for details self.doc.add((ref, FOAF.name, Literal(name))) for idf, label in info.items(): + if label not in self.foaf_supported_attributes: + logger.warning( + f"Not a supported FOAF attribute, Skipping {idf}: {label}." + ) + logger.warning( + f"Only {self.foaf_supported_attributes} FOAF attributes are currently supported by NeuroML/LEMS" + ) + continue + if label == "orcid": foaf_type = ORCID.id + elif label == "email": + foaf_type = getattr(FOAF, "mbox", None) else: foaf_type = getattr(FOAF, label, None) - if foaf_type is None: - logger.info("Not a FOAF attribute, using DC.identifier") - foaf_type = DC.identifier self.doc.add((ref, foaf_type, _URIRef_or_Literal(idf))) def extract_annotations( @@ -555,6 +608,9 @@ def extract_annotations( obj_id = parent.attrib["id"] except KeyError: obj_id = "" + + print(a) + annotations[obj_id] = self.parse_rdf(a) logger.info("Annotations in %s: " % (nml2_file)) diff --git a/pyneuroml/archive/__init__.py b/pyneuroml/archive/__init__.py index cc04007d..d34bb48a 100644 --- a/pyneuroml/archive/__init__.py +++ b/pyneuroml/archive/__init__.py @@ -8,16 +8,16 @@ import argparse import logging -import os import pathlib import shutil import typing from zipfile import ZipFile -from pyneuroml.utils import get_model_file_list -from pyneuroml.utils.cli import build_namespace -from pyneuroml.runners import run_jneuroml -from pyneuroml.sedml import validate_sedml_files +import pyneuroml.runners as pynmlr +import pyneuroml.sedml as pynmls +import pyneuroml.utils as pynmlu +import pyneuroml.utils.cli as pynmluc +from pyneuroml.utils.misc import chdir logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -85,10 +85,10 @@ def main(args=None): def cli(a: typing.Optional[typing.Any] = None, **kwargs: str): """Main cli caller method""" - a = build_namespace(DEFAULTS, a, **kwargs) + a = pynmluc.build_namespace(DEFAULTS, a, **kwargs) rootfile = a.rootfile - zipfile_extension = None + zipfile_extension = ".neux.zip" # first generate SED-ML file # use .omex as extension @@ -96,13 +96,13 @@ def cli(a: typing.Optional[typing.Any] = None, **kwargs: str): a.rootfile.startswith("LEMS") and a.rootfile.endswith(".xml") ) and a.sedml is True: logger.debug("Generating SED-ML file from LEMS file") - run_jneuroml("", a.rootfile, "-sedml") + pynmlr.run_jneuroml("", a.rootfile, "-sedml") rootfile = a.rootfile.replace(".xml", ".sedml") - zipfile_extension = ".omex" + zipfile_extension = ".omex.zip" # validate the generated file - validate_sedml_files([rootfile]) + pynmls.validate_sedml_files([rootfile]) # if explicitly given, use that if a.zipfile_extension is not None: @@ -119,7 +119,7 @@ def cli(a: typing.Optional[typing.Any] = None, **kwargs: str): def create_combine_archive( rootfile: str, zipfile_name: typing.Optional[str] = None, - zipfile_extension=".neux", + zipfile_extension=".neux.zip", filelist: typing.List[str] = [], extra_files: typing.List[str] = [], ): @@ -169,21 +169,19 @@ def create_combine_archive( logger.info(f"No zipfile name provided. Using {rootfile}") zipfile_name = rootfile - lems_def_dir = None - if len(filelist) == 0: - lems_def_dir = get_model_file_list(rootfile, filelist, rootdir, lems_def_dir) - - create_combine_archive_manifest(rootfile, filelist + extra_files, rootdir) - filelist.append("manifest.xml") - # change to directory of rootfile - thispath = os.getcwd() - os.chdir(rootdir) + with chdir(rootdir): + lems_def_dir = None + if len(filelist) == 0: + lems_def_dir = pynmlu.get_model_file_list( + rootfile, filelist, rootdir, lems_def_dir + ) + create_combine_archive_manifest(rootfile, filelist + extra_files, rootdir) + filelist.append("manifest.xml") - with ZipFile(zipfile_name + zipfile_extension, "w") as archive: - for f in filelist + extra_files: - archive.write(f) - os.chdir(thispath) + with ZipFile(zipfile_name + zipfile_extension, "w") as archive: + for f in filelist + extra_files: + archive.write(f) if lems_def_dir is not None: logger.info(f"Removing LEMS definitions directory {lems_def_dir}") diff --git a/pyneuroml/channelml/ChannelML2NeuroML2beta.xsl b/pyneuroml/channelml/ChannelML2NeuroML2beta.xsl index b8124ed2..ab38ec9a 100644 --- a/pyneuroml/channelml/ChannelML2NeuroML2beta.xsl +++ b/pyneuroml/channelml/ChannelML2NeuroML2beta.xsl @@ -4,17 +4,17 @@ This file is used to convert post v1.7.3 ChannelML files to the latest NeuroML 2 format. - Funding for this work has been received from the Medical Research Council and the + Funding for this work has been received from the Medical Research Council and the Wellcome Trust. This file was initially developed as part of the neuroConstruct project - + Author: Padraig Gleeson Copyright 2012 University College London - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -909,7 +909,7 @@ - + @@ -922,7 +922,7 @@ \n", segGrpsForSections, nseg) sprint(segGrpsForSections, "%s \n", segGrpsForSections) - + } for i = 1, n3d() - 1 { @@ -294,7 +294,7 @@ proc xmlwrite() { local proximalid, pointcount, segmentcount, sectioncount, i, j pointcount += 1 segmentcount += 1 } - + sprint(segGrpsForSections, "%s \n\n", segGrpsForSections) } @@ -406,7 +406,7 @@ proc xmlwrite() { local proximalid, pointcount, segmentcount, sectioncount, i, j // biophysics element for THIS cell. Only include if level > 1 if (nml2_level > 1) { // i.e. "Level 2" of NeuroML or greater - + xmlwrite_biophysics(file_out) } @@ -421,7 +421,7 @@ proc xmlwrite() { local proximalid, pointcount, segmentcount, sectioncount, i, j cellnml2file.close() } - + cellindex = cellindex +1 } @@ -429,20 +429,20 @@ proc xmlwrite() { local proximalid, pointcount, segmentcount, sectioncount, i, j sprint(network, "%s\n \n", network) mainnml2file.printf("%s \n", network) - assoc_cell_number(0, mainnml2file) + assoc_cell_number(0, mainnml2file) artcell(mainnml2file) } -// Takes arguments: +// Takes arguments: // $o1 file_out File object to write to // proc xmlwrite_biophysics() { file_out = $o1 - + cellnml2file.printf("\n \n\n \n") cellnml2file.printf("\n \n\n") @@ -474,11 +474,11 @@ proc xmlwrite_biophysics() { for dparm.parmiter(dpelm) { for l=0, dpelm.parms.count - 1 { print " - l ", l, " dparm ", dparm.name, " dpelm ", dpelm, ", value ", dpelm.parms.object(l).value - - + + if (hoc_sf_.substr(dmech.name, "_ion") > 0) { - strdef paramNameToUse + strdef paramNameToUse paramNameToUse = dparm.name strdef groupName sprint(groupName, "%s", dpelm.parms.object(l).location) @@ -501,18 +501,18 @@ proc xmlwrite_biophysics() { print "Assuming the one and only value for ek is: ", erev_K, "mV" } } else { - - strdef paramNameToUse + + strdef paramNameToUse paramNameToUse = dparm.name value = dpelm.parms.object(l).value if (hoc_sf_.substr(paramNameToUse, "_")>=0) { hoc_sf_.left(paramNameToUse, hoc_sf_.substr(paramNameToUse, "_")) } - + print " Initial parameter name: [", paramNameToUse, "], value: ", value - + if (strcmp(paramNameToUse, "e") == 0) { - + {p.set_erev_for_mechanism(dmech.name, value)} {print p.get_erev_for_mechanism(dmech.name)} } @@ -521,9 +521,9 @@ proc xmlwrite_biophysics() { } } - + } - + for i=0, cellref.secanal.dmlist.count - 1 { dmech = cellref.secanal.dmlist.object(i) @@ -535,12 +535,12 @@ proc xmlwrite_biophysics() { if (strcmp(dmech.name,"capacitance") != 0 && strcmp(dmech.name,"Ra") != 0 && hoc_sf_.substr(dmech.name, "_ion") == -1) { - - found_erev = 0 + + found_erev = 0 print "---------------------------------------------" print "Handling mechanism: ", dmech.name - strdef passiveAttr + strdef passiveAttr passiveAttr = "" // If mech name is built in passive conductance in NEURON if (strcmp(dmech.name,"pas") == 0) { @@ -552,7 +552,7 @@ proc xmlwrite_biophysics() { // Not used in nml2 /////passiveAttr = " passive_conductance=\"true\"" } - + for j=0, dmech.location.subset.size()-1 { secref = cellref.secanal.all.object(dmech.location.subset.x(j)) // printsec(cellnml2file, secref) @@ -561,15 +561,15 @@ proc xmlwrite_biophysics() { //print dparm for dparm.parmiter(dpelm) { //print dpelm - - + + for l=0, dpelm.parms.count - 1 { - strdef paramNameToUse + strdef paramNameToUse paramNameToUse = dparm.name print " Initial parameter name: ", paramNameToUse - strdef comment + strdef comment comment = "" // strip suffix @@ -590,7 +590,7 @@ proc xmlwrite_biophysics() { sprint(comment, "", paramNameToUse) } else if (hoc_sf_.substr(paramNameToUse, "g")==0 && hoc_sf_.substr(paramNameToUse, "bar")>=1) { sprint(comment, "", paramNameToUse) - paramNameToUse = "condDensity" + paramNameToUse = "condDensity" } else if (strcmp(paramNameToUse,"gl") == 0) { paramNameToUse = "condDensity" sprint(comment, "", paramNameToUse) @@ -608,7 +608,7 @@ proc xmlwrite_biophysics() { } else if (hoc_sf_.substr(paramNameToUse, "g")==0) { sprint(comment, "", paramNameToUse) paramNameToUse = "condDensity" - } + } print " Checking param: ",paramNameToUse, " in ", dmech.name if (strcmp(paramNameToUse,"e") == 0) { found_erev = 1 @@ -619,7 +619,7 @@ proc xmlwrite_biophysics() { factor = 1 - strdef units + strdef units units = "???" if (hoc_sf_.substr(paramNameToUse,"condDensity") >= 0) { @@ -629,14 +629,14 @@ proc xmlwrite_biophysics() { if (strcmp(paramNameToUse,"e") == 0) { paramNameToUse = "erev" units = "mV" - } - + } + if (strcmp(paramNameToUse, "condDensity")==0) { - + cellnml2file.printf(" =0) { cellnml2file.printf(" erev=\"%fmV\" ", erev_Na) } else if (hoc_sf_.substr(dmech.name,"K")>=0) { @@ -645,10 +645,10 @@ proc xmlwrite_biophysics() { value = p.get_erev_for_mechanism(dmech.name) cellnml2file.printf(" erev=\"%fmV\" ", value) } - + cellnml2file.printf("/>\n\n") - - + + } else if (strcmp(paramNameToUse, "e")==0) { print "Rev pot handled elsewhere..." } else if (strcmp(paramNameToUse, "erev")==0) { @@ -658,11 +658,11 @@ proc xmlwrite_biophysics() { //quit() } } - - + + } } - + } } @@ -679,7 +679,7 @@ proc xmlwrite_biophysics() { print "---------------------------------------------" print "Handling mechanism: ", dmech.name - strdef units + strdef units units = "uF_per_cm2" cellnml2file.printf(" \n\n") - } + } } cellnml2file.printf(" \n\n \n\n") @@ -705,7 +705,7 @@ proc xmlwrite_biophysics() { print "---------------------------------------------" print "Handling mechanism: ", dmech.name - strdef units + strdef units units = "kohm_cm" cellnml2file.printf(" \n\n") - } + } } //////////// ion_xmlwrite(cellnml2file) - cellnml2file.printf(" \n\n \n\n") + cellnml2file.printf(" \n\n \n\n") print "---------------------------------------------" @@ -732,7 +732,7 @@ proc xmlwrite_biophysics() { proc artcell() {local i,j,l file_out = $o1 for i=0, mview.acview.alist.count-1 { - dmech = mview.acview.alist.object(i) + dmech = mview.acview.alist.object(i) file_out.printf(" \n", dmech.name) @@ -770,7 +770,7 @@ proc printparmval() { comment1 = $s6 ref = $s7 units = $s8 - + print " -- Generating parameter, type: ", param_obj.type(), " param: ", param, ", val: ", param_obj.value, ", scale: ", scale_factor, ", comm: [", comment1, "], ref: ", ref, ", units: ", units // 1 is ModelViewParmVal, 2 is ModelViewParmVec if (param_obj.type() == 1) { @@ -783,10 +783,10 @@ proc printparmval() { if (hoc_sf_.len(param)>0) { // only incl if param is set => condDensity etc. not cap - strdef newParamName + strdef newParamName newParamName = param - file_out.printf(" %s = \"%g %s\"", newParamName, param_obj.value * scale_factor, units) + file_out.printf(" %s = \"%g %s\"", newParamName, param_obj.value * scale_factor, units) } else { file_out.printf(" value=\"%g %s\" %s", param_obj.value * scale_factor, units, comment1) // specCapacitance, etc. @@ -806,7 +806,7 @@ proc printparmval() { if (hoc_sf_.substr(groupName,"[")>=0 && hoc_sf_.substr(groupName,"]")>=0) { hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"]")) - strdef index + strdef index index = groupName hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"[")) hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1) @@ -835,7 +835,7 @@ proc printparmval() { if (hoc_sf_.substr(groupName,"[")>=0 && hoc_sf_.substr(groupName,"]")>=0) { hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"]")) - strdef index + strdef index index = groupName hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"[")) hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1) @@ -894,8 +894,8 @@ objref temp_secref proc printsec() { file_out = $o1 temp_secref = $o2 - - temp_secref.sec { + + temp_secref.sec { file_out.printf("
\n", secname()) } } @@ -905,7 +905,7 @@ objref temp_param_obj proc printvecvals() {local i file_out = $o1 temp_param_obj = $o2 - + temp_param_obj.location.realcell.all.object(temp_param_obj.location.isec).sec { file_out.printf(" \n", secname()) ///file_out.printf("
\n", secname()) @@ -920,7 +920,7 @@ proc printvecvals() {local i proc ion_xmlwrite() { file_out = $o1 - + for mview.dparm.mechs(tobj) { if (hoc_sf_.head(tobj.name, "_ion", tstr) != -1) { file_out.printf(" \n", tstr, ion_charge(tobj.name)) diff --git a/pyneuroml/neuron/utils.hoc b/pyneuroml/neuron/utils.hoc index 8a94eec4..6d87b19c 100755 --- a/pyneuroml/neuron/utils.hoc +++ b/pyneuroml/neuron/utils.hoc @@ -541,4 +541,3 @@ proc createTestReport() { print "------------------------------------------------------------------------------" } - diff --git a/pyneuroml/nsgr.py b/pyneuroml/nsgr.py index 73238730..55db1a91 100644 --- a/pyneuroml/nsgr.py +++ b/pyneuroml/nsgr.py @@ -14,6 +14,7 @@ from zipfile import ZipFile from pyneuroml.runners import generate_sim_scripts_in_folder +from pyneuroml.utils.misc import chdir logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) @@ -126,8 +127,6 @@ def run_on_nsg( # NSG requires that the top level directory exist nsg_dir = pathlib.Path(zipfile_name.replace(".zip", "")) - cwd = pathlib.Path.cwd() - tdir = generate_sim_scripts_in_folder( engine=engine, lems_file_name=lems_file_name, @@ -139,44 +138,43 @@ def run_on_nsg( logger.info("Generating zip file") runner_file = "" - os.chdir(str(tdir)) - generated_files = os.listdir(nsg_dir) - - print(f"Generated files are {generated_files}") - - with ZipFile(zipfile_name, "w") as archive: - for f in generated_files: - if engine == "jneuroml_neuron": - if f.endswith("_nrn.py"): - runner_file = f - elif engine == "jneuroml_netpyne": - if f.endswith("_netpyne.py"): - runner_file = f - fpath = pathlib.Path(f) - moved_path = nsg_dir / fpath - archive.write(str(moved_path)) - - logger.debug("Printing testParam.properties") - nsg_sim_config_dict["filename_"] = runner_file - logger.debug(f"NSG sim config is: {nsg_sim_config_dict}") - - with open("testParam.properties", "w") as file: - for key, val in nsg_sim_config_dict.items(): - print(f"{key}={val}", file=file) - - logger.debug("Printing testInput.properties") - with open("testInput.properties", "w") as file: - print(f"infile_=@./{zipfile_name}", file=file) - - print(f"{zipfile_name} generated") - # uses argv, where the first argument is the script itself, so we must pass - # something as the 0th index of the list - if not dry_run: - if nsgr_submit(["", ".", "validate"]) == 0: - print("Attempting to submit to NSGR") - return nsgr_submit(["", ".", "run"]) - else: - print("Dry run mode enabled. Not submitting to NSG.") - - os.chdir(str(cwd)) + with chdir(str(tdir)): + generated_files = os.listdir(nsg_dir) + + print(f"Generated files are {generated_files}") + + with ZipFile(zipfile_name, "w") as archive: + for f in generated_files: + if engine == "jneuroml_neuron": + if f.endswith("_nrn.py"): + runner_file = f + elif engine == "jneuroml_netpyne": + if f.endswith("_netpyne.py"): + runner_file = f + fpath = pathlib.Path(f) + moved_path = nsg_dir / fpath + archive.write(str(moved_path)) + + logger.debug("Printing testParam.properties") + nsg_sim_config_dict["filename_"] = runner_file + logger.debug(f"NSG sim config is: {nsg_sim_config_dict}") + + with open("testParam.properties", "w") as file: + for key, val in nsg_sim_config_dict.items(): + print(f"{key}={val}", file=file) + + logger.debug("Printing testInput.properties") + with open("testInput.properties", "w") as file: + print(f"infile_=@./{zipfile_name}", file=file) + + print(f"{zipfile_name} generated") + # uses argv, where the first argument is the script itself, so we must pass + # something as the 0th index of the list + if not dry_run: + if nsgr_submit(["", ".", "validate"]) == 0: + print("Attempting to submit to NSGR") + return nsgr_submit(["", ".", "run"]) + else: + print("Dry run mode enabled. Not submitting to NSG.") + return tdir diff --git a/pyneuroml/plot/Plot.py b/pyneuroml/plot/Plot.py index 25bac5b8..43facdfe 100644 --- a/pyneuroml/plot/Plot.py +++ b/pyneuroml/plot/Plot.py @@ -140,6 +140,8 @@ def generate_plot( :type legend_position: str :param show_plot_already: if plot should be shown when created (default: True) + Otherwise, the plots are not shown and you must call pyplot.show() + explicitly to show them. Should not be used with `close_plot`. :type show_plot_already: boolean :param animate: if plot should be animated (default: False) :type animate: boolean @@ -207,7 +209,7 @@ def generate_plot( f"values to plot ({len(xvalues)}) and markersizes ({len(markersizes)}) must have the same length" ) - logger.info("Generating plot: %s" % (title)) + logger.info("Generating plot" + (f": {title}" if title else "")) from matplotlib import pyplot as plt from matplotlib import rcParams @@ -380,15 +382,11 @@ def update(frame): ) pbar.finish(dirty=False) - logger.info("Saved animation to %s" % (save_figure_to)) + logger.info(f"Saved animation to {os.path.abspath(save_figure_to)}") else: if save_figure_to: - logger.info( - "Saving image to %s of plot: %s" - % (os.path.abspath(save_figure_to), title) - ) plt.savefig(save_figure_to, bbox_inches="tight") - logger.info("Saved image to %s of plot: %s" % (save_figure_to, title)) + logger.info(f"Saved image to {os.path.abspath(save_figure_to)}") if show_plot_already: if interactive_legend is True and legend_box is not None: diff --git a/pyneuroml/plot/PlotMorphology.py b/pyneuroml/plot/PlotMorphology.py index c036a039..543c7e37 100644 --- a/pyneuroml/plot/PlotMorphology.py +++ b/pyneuroml/plot/PlotMorphology.py @@ -12,6 +12,7 @@ import os import random import sys +import textwrap import typing from typing import Optional @@ -20,8 +21,10 @@ from matplotlib import pyplot as plt from neuroml import Cell, Morphology, NeuroMLDocument, SegmentGroup from neuroml.neuro_lex_ids import neuro_lex_ids +from neuroml.utils import fix_external_morphs_biophys_in_cell from pyneuroml.pynml import read_neuroml2_file +from pyneuroml.swc.ExportNML import convert_swc_to_neuroml from pyneuroml.utils import extract_position_info from pyneuroml.utils.cli import build_namespace from pyneuroml.utils.plot import ( @@ -45,14 +48,25 @@ def process_args(): Parse command-line arguments. """ parser = argparse.ArgumentParser( - description=("A script which can generate plots of morphologies in NeuroML 2") + description=( + textwrap.dedent( + """ + A script which can generate plots of morphologies in NeuroML 2. + It can generate plots of single cells (either detailed or point + cells), and networks that include these cells. + + It can also visualise single cell morphologies from SWC files, + although it will first convert these to NeuroML. + """ + ) + ) ) parser.add_argument( "nmlFile", type=str, - metavar="", - help="Name of the NeuroML 2 file", + metavar="", + help="Name of the NeuroML 2 file/SWC cell file", ) parser.add_argument( @@ -131,6 +145,14 @@ def process_args(): help="Name of the image file, for 2D plot", ) + parser.add_argument( + "-saveMeshTo", + type=str, + metavar="", + default=None, + help="Name of the file to save 3D mesh data to", + ) + parser.add_argument( "-square", action="store_true", @@ -169,6 +191,7 @@ def plot_from_console(a: typing.Optional[typing.Any] = None, **kwargs: str): plot_spec={"point_fraction": a.point_fraction}, upright=a.upright, axes_pos=a.show_axes, + save_mesh_to=a.save_mesh_to, ) else: plot_2D( @@ -205,7 +228,8 @@ def plot_2D( If a file with a network containing multiple cells is provided, it will plot all the cells. For detailed neuroml.Cell types, it will plot their complete morphology. For point neurons, we only plot the points (locations) - where they are. + where they are. For single cell SWC files, it will first convert them to + NeuroML and then plot them. This method uses matplotlib. @@ -213,9 +237,11 @@ def plot_2D( The hightlight_spec parameter - :param nml_file: path to NeuroML cell file, or a NeuroMLDocument object - :type nml_file: str or :py:class:`neuroml.NeuroMLDocument` or - :py:class:`neuroml.Cell` + :param nml_file: path to NeuroML cell file or single cell SWC file or + :py:class:`neuroml.NeuroMLDocument` or :py:class:`neuroml.Cell` + or :py:class:`neuroml.Morphology` object + :type nml_file: str or neuroml.NeuroMLDocument or neuroml.Cell or + neuroml.Morphology :param plane2d: what plane to plot (xy/yx/yz/zy/zx/xz) :type plane2d: str :param min_width: minimum width for segments (useful for visualising very @@ -307,6 +333,14 @@ def plot_2D( # TODO: check if this is required: must for MultiscaleISN if nml_file.endswith(".h5"): nml_model = read_neuroml2_file(nml_file) + elif nml_file.endswith(".swc"): + nml_model_doc = convert_swc_to_neuroml( + nml_file, + neuroml_file=None, + standalone_morphology=False, + unbranched_segment_groups=False, + ) + nml_model = nml_model_doc.cells[0] else: nml_model = read_neuroml2_file( nml_file, @@ -314,37 +348,75 @@ def plot_2D( check_validity_pre_include=False, verbose=False, optimized=True, + fix_external_morphs_biophys=False, ) + # If it's a model that refers to external files for cells, and + # other bits, only load ones that we need for visualization load_minimal_morphplottable__model(nml_model, nml_file) - # note that from this point, the model object is not necessarily valid, - # because we've removed lots of bits. + # Note that from this point, the model object is not necessarily valid, + # because we've removed lots of bits that are not required for + # visualization. + + # call manually so we can only load morphology, not biophysics + fix_external_morphs_biophys_in_cell( + nml_model, load_morphology=True, load_biophysical_properties=False + ) else: nml_model = nml_file # if it isn't a NeuroMLDocument, create one if isinstance(nml_model, Cell): - logger.info("Got a cell") + logger.debug("Got a cell") + if nml_model.morphology is None: + if nml_model.morphology_attr is None: + logger.error( + "Neither morphology nor a reference to an external morphology are included in the Cell. Cannot plot." + ) + return + else: + logger.error( + "An external morphology is has been reference in the cell but I do not have the whole document to load it. Please pass the NeuroMLDocument or filename to the function instead." + ) + return + plottable_nml_model = NeuroMLDocument(id="newdoc") plottable_nml_model.add(nml_model) - logger.info(f"plottable cell model is: {plottable_nml_model.cells[0]}") + logger.debug(f"plottable cell model is: {plottable_nml_model.cells[0]}") if title is None: title = f"{plottable_nml_model.cells[0].id}" # if it's only a cell, add it to an empty cell in a document elif isinstance(nml_model, Morphology): - logger.info("Received morph, adding to a dummy cell") + logger.debug("Received morph, adding to a dummy cell") plottable_nml_model = NeuroMLDocument(id="newdoc") nml_cell = plottable_nml_model.add( Cell, id=nml_model.id, morphology=nml_model, validate=False ) plottable_nml_model.add(nml_cell) - logger.info(f"plottable cell model is: {plottable_nml_model.cells[0]}") + logger.debug(f"plottable cell model is: {plottable_nml_model.cells[0]}") if title is None: title = f"{plottable_nml_model.cells[0].id}" + # if it's a document, figure out if it's a cell or morphology elif isinstance(nml_model, NeuroMLDocument): - plottable_nml_model = nml_model - if title is None: - title = f"{plottable_nml_model.id}" + logger.debug("Received document, checking for cells/morphologies") + if len(nml_model.cells) > 0: + logger.debug("Received document with cells") + plottable_nml_model = fix_external_morphs_biophys_in_cell( + nml_model, overwrite=False + ) + elif len(nml_model.morphology) > 0: + logger.debug("Received document with morphologies, adding to dummy cells") + plottable_nml_model = NeuroMLDocument(id="newdoc") + for m in nml_model.morphology: + plottable_nml_model.add(Cell, id=m.id, morphology=m, validate=False) + logger.debug(f"plottable cell model is: {plottable_nml_model.cells[0]}") + # use title from original model document + title = nml_model.id + else: + plottable_nml_model = nml_model + + if title is None: + title = f"{plottable_nml_model.id}" ( cell_id_vs_cell, @@ -411,7 +483,7 @@ def plot_2D( radius = pop_id_vs_radii[pop_id] if pop_id in pop_id_vs_radii else 10 color = pop_id_vs_color[pop_id] if pop_id in pop_id_vs_color else None - if cell is None: + if cell is None or not isinstance(cell, Cell): plot_2D_point_cells( offset=pos, plane2d=plane2d, @@ -618,6 +690,13 @@ def plot_2D_cell_morphology( "No cell provided. If you would like to plot a network of point neurons, consider using `plot_2D_point_cells` instead" ) + if cell.morphology is None: + logger.error("Cell does not contain a morphology. Cannot visualise.") + logger.error( + "If the cell is referencing an external morphology, please use the `plot_2D` function and pass the complete document and we will try to load the morphology." + ) + return + if highlight_spec is None: highlight_spec = {} logging.debug("highlight_spec is " + str(highlight_spec)) @@ -1036,6 +1115,18 @@ def plot_2D_schematic( :type close_plot: bool """ + if cell is None: + raise ValueError( + "No cell provided. If you would like to plot a network of point neurons, consider using `plot_2D_point_cells` instead" + ) + + if cell.morphology is None: + logger.error("Cell does not contain a morphology. Cannot visualise.") + logger.error( + "If the cell is referencing an external morphology, please use the `plot_2D` function and pass the complete document and we will try to load the morphology." + ) + return + if title == "": title = f"2D schematic of segment groups from {cell.id}" diff --git a/pyneuroml/plot/PlotMorphologyVispy.py b/pyneuroml/plot/PlotMorphologyVispy.py index d026dc78..bff4346b 100644 --- a/pyneuroml/plot/PlotMorphologyVispy.py +++ b/pyneuroml/plot/PlotMorphologyVispy.py @@ -12,16 +12,28 @@ import logging import math import random -import typing -from typing import Optional +import time +from functools import lru_cache +from typing import Any, Dict, List, Optional, Tuple, TypedDict, Union import numpy import progressbar -from neuroml import Cell, Morphology, NeuroMLDocument, SegmentGroup +from frozendict import frozendict +from matplotlib.colors import to_rgb +from neuroml import ( + Cell, + Morphology, + NeuroMLDocument, + Point3DWithDiam, + Segment, + SegmentGroup, +) from neuroml.neuro_lex_ids import neuro_lex_ids +from neuroml.utils import fix_external_morphs_biophys_in_cell from scipy.spatial.transform import Rotation from pyneuroml.pynml import read_neuroml2_file +from pyneuroml.swc.ExportNML import convert_swc_to_neuroml from pyneuroml.utils import extract_position_info, make_cell_upright from pyneuroml.utils.plot import ( DEFAULTS, @@ -30,6 +42,18 @@ load_minimal_morphplottable__model, ) +# define special type for plot_spec dictionary +PlotSpec = TypedDict( + "PlotSpec", + { + "point_fraction": float, + "point_cells": List[str], + "schematic_cells": List[str], + "constant_cells": List[str], + "detailed_cells": List[str], + }, +) + logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -37,10 +61,14 @@ try: from vispy import app, scene, use + from vispy.color import get_color_dict, get_color_names from vispy.geometry.generation import create_sphere from vispy.geometry.meshdata import MeshData - from vispy.scene.visuals import InstancedMesh + from vispy.io.mesh import write_mesh + from vispy.scene.visuals import Mesh + from vispy.scene.widgets.viewbox import ViewBox from vispy.util.transforms import rotate + from vispy.visuals.filters import FacePickingFilter, ShadingFilter if app.Application.is_interactive(app): pynml_in_jupyter = True @@ -58,14 +86,12 @@ } PYNEUROML_VISPY_THEME = "light" -MAX_MESH_PRECISION = 3 - def add_text_to_vispy_3D_plot( current_canvas: scene.SceneCanvas, - xv: typing.List[float], - yv: typing.List[float], - zv: typing.List[float], + xv: List[float], + yv: List[float], + zv: List[float], color: str, text: str, ): @@ -105,17 +131,17 @@ def add_text_to_vispy_3D_plot( def create_new_vispy_canvas( - view_min: typing.Optional[typing.List[float]] = None, - view_max: typing.Optional[typing.List[float]] = None, + view_min: Optional[List[float]] = None, + view_max: Optional[List[float]] = None, title: str = "", - axes_pos: typing.Optional[ - typing.Union[typing.List[float], typing.List[int], str] + axes_pos: Optional[ + Union[Tuple[float, float, float], Tuple[int, int, int], str] ] = None, axes_length: float = 100, axes_width: int = 2, theme=PYNEUROML_VISPY_THEME, - view_center: typing.Optional[typing.List[float]] = None, -): + view_center: Optional[List[float]] = None, +) -> Tuple[scene.SceneCanvas, ViewBox]: """Create a new vispy scene canvas with a view and optional axes lines Reference: https://vispy.org/gallery/scene/axes_plot.html @@ -137,7 +163,7 @@ def create_new_vispy_canvas( - "origin": automatically added at origin - "bottom left": automatically added at bottom left - :type axes_pos: [float, float, float] or [int, int, int] or None or str + :type axes_pos: (float, float, float) or (int, int, int) or None or str :param axes_length: length of axes :type axes_length: float :param axes_width: width of axes lines @@ -181,7 +207,10 @@ def create_new_vispy_canvas( cam_index = 1 view.camera = cams[cam_index] - calc_axes_pos = None # type: typing.Optional[typing.Union[typing.List[float], typing.List[int]]] + calc_axes_pos: Optional[Union[Tuple[float, float, float], Tuple[int, int, int]]] = ( + None + ) + if view_min is not None and view_max is not None: x_width = abs(view_min[0] - view_max[0]) y_width = abs(view_min[1] - view_max[1]) @@ -231,9 +260,9 @@ def create_new_vispy_canvas( except ValueError: z_bit = view_min[0] - calc_axes_pos = [x_bit, view_min[1], z_bit] + calc_axes_pos = (x_bit, view_min[1], z_bit) elif axes_pos == "origin": - calc_axes_pos = [0.0, 0.0, 0.0] + calc_axes_pos = (0.0, 0.0, 0.0) else: raise ValueError(f"Invalid value for axes_pos: {axes_pos}") # if it's either None, or a point @@ -309,22 +338,20 @@ def vispy_on_key_press(event): def plot_interactive_3D( - nml_file: typing.Union[str, Cell, Morphology, NeuroMLDocument], + nml_file: Union[str, Cell, Morphology, NeuroMLDocument], min_width: float = DEFAULTS["minWidth"], verbose: bool = False, - plot_type: str = "constant", - axes_pos: typing.Optional[ - typing.Union[typing.List[float], typing.List[int], str] + plot_type: str = "detailed", + axes_pos: Optional[ + Union[Tuple[float, float, float], Tuple[int, int, int], str] ] = None, - title: typing.Optional[str] = None, + title: Optional[str] = None, theme: str = "light", nogui: bool = False, - plot_spec: typing.Optional[ - typing.Dict[str, typing.Union[str, typing.List[int], float]] - ] = None, - highlight_spec: typing.Optional[typing.Dict[typing.Any, typing.Any]] = None, - precision: typing.Tuple[int, int] = (4, 200), + plot_spec: Optional[PlotSpec] = None, + highlight_spec: Optional[Dict[Any, Any]] = None, upright: bool = False, + save_mesh_to: Optional[str] = None, ): """Plot interactive plots in 3D using Vispy @@ -338,10 +365,15 @@ def plot_interactive_3D( QT_QPA_PLATFORM=wayland-egl .. versionadded:: 1.1.12 - The hightlight_spec parameter + The highlight_spec parameter + If a file with a network containing multiple cells is provided, it will + plot all the cells. For detailed neuroml.Cell types, it will plot their + complete morphology. For point neurons, we only plot the points (locations) + where they are as spheres. For single cell SWC files, it will first convert + them to NeuroML and then plot them. - :param nml_file: path to NeuroML cell file or + :param nml_file: path to NeuroML cell file or single cell SWC file or :py:class:`neuroml.NeuroMLDocument` or :py:class:`neuroml.Cell` or :py:class:`neuroml.Morphology` object :type nml_file: str or neuroml.NeuroMLDocument or neuroml.Cell or @@ -355,7 +387,8 @@ def plot_interactive_3D( - "detailed": show detailed morphology taking into account each segment's width - - "constant": show morphology, but use constant line widths + - "constant": show morphology, but use "min_width" for line widths; the + soma is made thicker to make it easy to see - "schematic": only plot each unbranched segment group as a straight line, not following each segment - "point": show all cells as points @@ -373,7 +406,7 @@ def plot_interactive_3D( - "origin": automatically added at origin - "bottom left": automatically added at bottom left - :type axes_pos: [float, float, float] or [int, int, int] or None or str + :type axes_pos: (float, float, float) or (int, int, int) or None or str :param title: title of plot :type title: str :param theme: theme to use (light/dark) @@ -390,23 +423,27 @@ def plot_interactive_3D( - points_cells: list of cell ids to plot as point cells - schematic_cells: list of cell ids to plot as schematics - constant_cells: list of cell ids to plot as constant widths + - detailed_cells: list of cell ids to plot in full detail - The last three lists override the point_fraction setting. If a cell id - is not included in the spec here, it will follow the plot_type provided + The lists override the point_fraction setting. If a cell id is not + included in the spec here, it will follow the plot_type provided before. :type plot_spec: dict :param highlight_spec: dictionary that allows passing some specifications to allow highlighting of particular elements. Only used when plotting multi-compartmental cells for marking segments on them - ("plot_type" is either "constant" or "detailed") + ("plot_type" is "detailed", since for "constant" `min_width` is always + used.) Each key in the dictionary will be of the cell id and the values will - be more dictionaries, with the segment id as key and the following keys - in it: + be a "cell_color" or more dictionaries, with the segment id as key and + the following keys in it: - - marker_color: color of the marker - - marker_size: [diameter 1, diameter 2] (in case of sphere, the first value - is used) + - marker_color: color of the marker (str) + - marker_size: (diameter 1, diameter 2) (tuple) (in case of sphere, the + first value is used) + - marker_type: "sphere" (str) (otherwise the default shape of the + segment is used, which could either be a sphere or a cylinder) E.g.: @@ -414,25 +451,24 @@ def plot_interactive_3D( { "cell id1": { + "cell_color": "red", # string "seg id1": { - "marker_color": "blue", - "marker_size": [0.1, 0.1] + "marker_color": "blue", # string + "marker_size": (0.1, 0.1), # tuple + "marker_type": "sphere" # string } } } + + The `cell_color` can be one of: + + - valid color options of :py:func:`plot_3D_cell_morphology` for a "detailed" plot_type + - valid color options of :py:func:`plot_3D_schematic` for a "schematic" plot_type + + Please see the function docstrings for more information. + :type highlight_spec: dict - :param precision: tuple containing two values: (number of decimal places, - maximum number of meshes). The first is used to group segments into - meshes to create instances. More precision means fewer segments will be - grouped into meshes---this may increase detail, but will reduce - performance. The second argument is used to limit the total number of - meshes. The function will keep reducing precision until the number of - meshes is fewer than the value provided here. - - If you have a good GPU, you can increase both these values to get more - detailed visualizations - :type precision: (int, int) :param upright: bool only applicable for single cells: Makes cells "upright" (along Y axis) by calculating its PCA, rotating it so it is along the Y axis, and transforming cell co-ordinates to align along the rotated first principal @@ -441,6 +477,8 @@ def plot_interactive_3D( "upwards" instead of "downwards" in most cases. Note that the original cell object is unchanged, this is for visualization purposes only. :type upright: bool + :param save_mesh_to: name of file to save mesh object to + :type save_mesh_to: str or None :throws ValueError: if `plot_type` is not one of "detailed", "constant", "schematic", or "point" @@ -455,6 +493,25 @@ def plot_interactive_3D( if highlight_spec is None: highlight_spec = {} + # convert axes_pos from list to tuple, it needs to be hashable for + # functions that use caching + if axes_pos: + if isinstance(axes_pos, list): + axes_pos = tuple(axes_pos) + + if plot_type != "detailed" and len(highlight_spec.items()) > 0: + if plot_type == "constant": + logger.warning( + "Plot type is 'constant', `marker_size` in `highlight_spec` will be ignored and provided `min_width` used" + ) + elif plot_type == "schematic" or plot_type == "point": + logger.warning( + f"Plot type is '{plot_type}', `highlight_spec` will be ignored" + ) + logger.warning( + "Please use `plot_type='detailed' if you also want to use `marker_size`" + ) + if verbose: logger.info(f"Visualising {nml_file}") @@ -464,44 +521,101 @@ def plot_interactive_3D( # TODO: check if this is required: must for MultiscaleISN if nml_file.endswith(".h5"): nml_model = read_neuroml2_file(nml_file) + elif nml_file.endswith(".swc"): + nml_model_doc = convert_swc_to_neuroml( + nml_file, + neuroml_file=None, + standalone_morphology=False, + unbranched_segment_groups=False, + ) + nml_model = nml_model_doc.cells[0] else: + # do not fix external morphs here, we do it later below nml_model = read_neuroml2_file( nml_file, include_includes=False, check_validity_pre_include=False, verbose=False, optimized=True, + fix_external_morphs_biophys=False, ) + # If it's a model that refers to external files for cells, and + # other bits, only load ones that we need for visualization load_minimal_morphplottable__model(nml_model, nml_file) - # note that from this point, the model object is not necessarily valid, - # because we've removed lots of bits. + # Note that from this point, the model object is not necessarily valid, + # because we've removed lots of bits that are not required for + # visualization. + + # call manually so we can only load morphology, not biophysics + fix_external_morphs_biophys_in_cell( + nml_model, load_morphology=True, load_biophysical_properties=False + ) else: nml_model = nml_file # if it isn't a NeuroMLDocument, create one if isinstance(nml_model, Cell): logger.debug("Got a cell") + if nml_model.morphology is None: + if nml_model.morphology_attr is None: + logger.error( + "Neither morphology nor a reference to an external morphology are included in the Cell. Cannot plot." + ) + return + else: + logger.error( + "An external morphology is has been reference in the cell but I do not have the whole document to load it. Please pass the NeuroMLDocument or filename to the function instead." + ) + return + plottable_nml_model = NeuroMLDocument(id="newdoc") plottable_nml_model.add(nml_model) logger.debug(f"plottable cell model is: {plottable_nml_model.cells[0]}") if title is None: title = f"{plottable_nml_model.cells[0].id}" - # if it's only a cell, add it to an empty cell in a document + # if it's only a morphology, add it to an empty cell in a document elif isinstance(nml_model, Morphology): logger.debug("Received morph, adding to a dummy cell") plottable_nml_model = NeuroMLDocument(id="newdoc") - nml_cell = plottable_nml_model.add( + plottable_nml_model.add( Cell, id=nml_model.id, morphology=nml_model, validate=False ) - plottable_nml_model.add(nml_cell) logger.debug(f"plottable cell model is: {plottable_nml_model.cells[0]}") if title is None: title = f"{plottable_nml_model.cells[0].id}" + + # if it's a document, figure out if it's a cell or morphology elif isinstance(nml_model, NeuroMLDocument): - plottable_nml_model = nml_model - if title is None: - title = f"{plottable_nml_model.id}" + logger.debug("Received document, checking for cells/morphologies") + if len(nml_model.cells) > 0: + logger.debug("Received document with cells") + plottable_nml_model = fix_external_morphs_biophys_in_cell( + nml_model, + overwrite=False, + load_morphology=True, + load_biophysical_properties=False, + ) + elif len(nml_model.morphology) > 0: + logger.debug("Received document with morphologies, adding to dummy cells") + plottable_nml_model = NeuroMLDocument(id="newdoc") + for m in nml_model.morphology: + plottable_nml_model.add(Cell, id=m.id, morphology=m, validate=False) + logger.debug(f"plottable cell model is: {plottable_nml_model.cells[0]}") + # use title from original model document + title = nml_model.id + # other networks + else: + plottable_nml_model = nml_model + + logger.debug(plottable_nml_model.info(show_contents=True)) + + # what did we get? + else: + raise ValueError(f"Could not process argument: {nml_model}") + + if title is None: + title = f"{plottable_nml_model.id}" ( cell_id_vs_cell, @@ -519,20 +633,11 @@ def plot_interactive_3D( # calculate total cells and segments to be plotted total_cells = 0 - total_segments = 0 for pop_id, cell in pop_id_vs_cell.items(): total_cells += len(positions[pop_id]) - try: - total_segments += len(positions[pop_id]) * len(cell.morphology.segments) - except AttributeError: - total_segments += len(positions[pop_id]) - logger.debug( - f"Visualising {total_segments} segments in {total_cells} cells in {len(pop_id_vs_cell)} populations" - ) - logger.debug( - f"Grouping into mesh instances by diameters at {precision[0]} decimal places" - ) + logger.info("Processing %s cells" % total_cells) + # not used later, clear up del cell_id_vs_cell @@ -569,7 +674,7 @@ def plot_interactive_3D( else: cell = list(pop_id_vs_cell.values())[0] - if cell is not None: + if cell is not None and isinstance(cell, Cell): view_min, view_max = get_cell_bound_box(cell) else: logger.debug("Got a point cell") @@ -589,7 +694,7 @@ def plot_interactive_3D( current_canvas, current_view = create_new_vispy_canvas( view_min, view_max, - title, + title if title else "", axes_pos=axes_pos, theme=theme, view_center=view_center, @@ -600,10 +705,10 @@ def plot_interactive_3D( ) # process plot_spec - point_cells = [] - schematic_cells = [] - constant_cells = [] - detailed_cells = [] + point_cells: List[str] = [] + schematic_cells: List[str] = [] + constant_cells: List[str] = [] + detailed_cells: List[str] = [] if plot_spec is not None: try: point_cells = plot_spec["point_cells"] @@ -622,8 +727,7 @@ def plot_interactive_3D( except KeyError: pass - meshdata = {} # type: typing.Dict[typing.Any, typing.Any] - logger.info("Processing %s cells" % total_cells) + meshdata = [] # type: List[Any] # do not show this pbar in jupyter notebooks if not pynml_in_jupyter: @@ -661,23 +765,47 @@ def plot_interactive_3D( while pos_pop: cell_index, pos = pos_pop.popitem() radius = pop_id_vs_radii[pop_id] if pop_id in pop_id_vs_radii else 10 - color = ( - pop_id_vs_color[pop_id] - if pop_id in pop_id_vs_color - else get_next_hex_color() - ) + + # use color if specified in property + try: + color = pop_id_vs_color[pop_id] + except KeyError: + # if single cell only, use default groups + if total_cells == 1: + logger.debug("Only one detailed cell, using default color groups") + color = "default groups" + # if multiple cells, use different colors for each cell + else: + color = random.choice(get_color_names()) + + # if hightlight spec has a color for the cell, use that + try: + color = highlight_spec[cell.id]["cell_color"] + # no key for this cell + except KeyError: + pass + # point cell + except AttributeError: + pass try: logging.debug(f"Plotting {cell.id}") except AttributeError: logging.debug(f"Plotting a point cell at {pos}") - if cell is None: - key = (f"{radius:.1f}", f"{radius:.1f}", f"{radius:.1f}") - try: - meshdata[key].append((None, None, color, pos)) - except KeyError: - meshdata[key] = [(None, None, color, pos)] + # a point cell component type + if cell is None or not isinstance(cell, Cell): + meshdata.append( + ( + f"{radius:.1f}", + f"{radius:.1f}", + f"{radius:.1f}", + None, + None, + color, + pos, + ) + ) else: if ( plot_type == "point" @@ -691,17 +819,31 @@ def plot_interactive_3D( pos[1] + soma_x_y_z.y, pos[2] + soma_x_y_z.z, ] - key = (f"{radius:.1f}", f"{radius:.1f}", f"{radius:.1f}") - try: - meshdata[key].append((None, None, color, pos1)) - except KeyError: - meshdata[key] = [(None, None, color, pos1)] - logger.debug(f"meshdata added: {key}: {meshdata[key]}") + meshdata.append( + ( + f"{radius:.1f}", + f"{radius:.1f}", + f"{radius:.1f}", + None, + None, + color, + pos1, + ) + ) + logger.debug(f"meshdata added: {meshdata[-1]}") elif plot_type == "schematic" or cell.id in schematic_cells: logger.debug(f"Cell for 3d schematic is: {cell.id}") - plot_3D_schematic( - offset=pos, + # Pass no offset (pos) here to take advantage of the + # lru_cache. The offset is not really used in anyway other + # than to create the meshdata. So we can add it to the + # mesdata after. This means that the plot_3D_cell_morphology + # function will not be run if the same cell object is + # passed to it, a common usecase for networks where there + # are populations of the same cell. Instead, the cache will + # be used. + new_meshdata = plot_3D_schematic( + offset=None, cell=cell, segment_groups=None, color=color, @@ -710,10 +852,13 @@ def plot_interactive_3D( current_view=current_view, axes_pos=axes_pos, nogui=True, - meshdata=meshdata, - mesh_precision=precision[0], + meshdata=None, upright=upright, + save_mesh_to=None, ) + assert new_meshdata is not None + mesh_data_with_offset = [(*x, pos) for x in new_meshdata] + meshdata.extend(mesh_data_with_offset) elif ( plot_type == "detailed" or cell.id in detailed_cells @@ -727,8 +872,16 @@ def plot_interactive_3D( except KeyError: pass - plot_3D_cell_morphology( - offset=pos, + # Pass no offset (pos) here to take advantage of the + # lru_cache. The offset is not really used in anyway other + # than to create the meshdata. So we can add it to the + # mesdata after. This means that the plot_3D_cell_morphology + # function will not be run if the same cell object is + # passed to it, a common usecase for networks where there + # are populations of the same cell. Instead, the cache will + # be used. + new_meshdata = plot_3D_cell_morphology( + offset=None, cell=cell, color=color, plot_type=plot_type, @@ -738,44 +891,26 @@ def plot_interactive_3D( axes_pos=axes_pos, min_width=min_width, nogui=True, - meshdata=meshdata, - mesh_precision=precision[0], - highlight_spec=cell_highlight_spec, + meshdata=None, + highlight_spec=frozendict(cell_highlight_spec), upright=upright, + save_mesh_to=None, ) - - # if too many meshes, reduce precision and retry, recursively - if (len(meshdata.keys()) > precision[1]) and (precision[0] > 0): - precision = (precision[0] - 1, precision[1]) - if pbar is not None: - pbar.finish(dirty=True) - - logger.info( - f"More meshes than threshold ({len(meshdata.keys())}/{precision[1]}), reducing precision to {precision[0]} and re-calculating." - ) - plot_interactive_3D( - nml_file=plottable_nml_model, - min_width=min_width, - verbose=verbose, - plot_type=plot_type, - axes_pos=axes_pos, - title=title, - theme=theme, - nogui=nogui, - plot_spec=plot_spec, - precision=precision, - highlight_spec=highlight_spec, - upright=upright, - ) - # break the recursion, don't plot in the calling method - return + assert new_meshdata is not None + mesh_data_with_offset = [(*x, pos) for x in new_meshdata] + meshdata.extend(mesh_data_with_offset) pbar_ctr += 1 if not nogui: if pbar is not None: pbar.finish() - create_instanced_meshes(meshdata, plot_type, current_view, min_width) + create_mesh( + meshdata, + current_view, + save_mesh_to=save_mesh_to, + current_canvas=current_canvas, + ) if pynml_in_jupyter: display(current_canvas) else: @@ -783,48 +918,49 @@ def plot_interactive_3D( app.run() +@lru_cache(maxsize=100) def plot_3D_cell_morphology( - offset: typing.List[float] = [0, 0, 0], + offset: Optional[Tuple[float, float, float]] = (0.0, 0.0, 0.0), cell: Optional[Cell] = None, - color: typing.Optional[str] = None, + color: Optional[str] = None, title: str = "", verbose: bool = False, current_canvas: Optional[scene.SceneCanvas] = None, current_view: Optional[scene.ViewBox] = None, min_width: float = DEFAULTS["minWidth"], - axis_min_max: typing.List = [float("inf"), -1 * float("inf")], - axes_pos: typing.Optional[ - typing.Union[typing.List[float], typing.List[int], str] + axis_min_max: Tuple = (float("inf"), -1 * float("inf")), + axes_pos: Optional[ + Union[Tuple[float, float, float], Tuple[int, int, int], str] ] = None, - nogui: bool = True, - plot_type: str = "constant", + nogui: bool = False, + plot_type: str = "detailed", theme: str = "light", - meshdata: typing.Optional[typing.Dict[typing.Any, typing.Any]] = None, - mesh_precision: int = 2, - highlight_spec: typing.Optional[typing.Dict[typing.Any, typing.Any]] = None, + meshdata: Optional[List[Any]] = None, + highlight_spec: Optional[Union[Dict, frozendict]] = None, upright: bool = False, -): + save_mesh_to: Optional[str] = None, +) -> Optional[List[Any]]: """Plot the detailed 3D morphology of a cell using vispy. https://vispy.org/ .. versionadded:: 1.0.0 .. versionadded:: 1.1.12 - The hightlight_spec parameter + The highlight_spec parameter .. seealso:: - :py:func:`plot_2D` + :py:func:`plot_interactive_3D` general function for plotting - :py:func:`plot_2D_schematic` + :py:func:`plot_3D_schematic` for plotting only segmeng groups with their labels - :py:func:`plot_2D_point_cells` - for plotting point cells - :param offset: offset for cell - :type offset: [float, float] + Note that this is only used in creating the meshdata. If set to None, + this is ommitted from the meshdata, and the mesh creator will set it to + origin. + :type offset: (float, float, float) or None :param cell: cell to plot :type cell: neuroml.Cell :param color: color to use for segments, with some special values: @@ -851,7 +987,7 @@ def plot_3D_cell_morphology( - "origin": automatically added at origin - "bottom left": automatically added at bottom left - :type axes_pos: [float, float, float] or [int, int, int] or None or str + :type axes_pos: (float, float, float) or None or str :param title: title of plot :type title: str :param verbose: show extra information (default: False) @@ -866,10 +1002,9 @@ def plot_3D_cell_morphology( :param plot_type: type of plot, one of: - "detailed": show detailed morphology taking into account each segment's - width. This is not performant, because a new line is required for - each segment. To only be used for cells with small numbers of - segments - - "constant": show morphology, but use constant line widths + width. + - "constant": show morphology, but use min_width for line widths; the + soma is made 5 times thicker to make it easier to see. This is only applicable for neuroml.Cell cells (ones with some morphology) @@ -877,22 +1012,20 @@ def plot_3D_cell_morphology( :type plot_type: str :param theme: theme to use (dark/light) :type theme: str - :param meshdata: dictionary used to store mesh related data for vispy + :param meshdata: list used to store mesh related data for vispy visualisation - :type meshdata: dict - :param mesh_precision: what decimal places to use to group meshes into - instances: more precision means more detail (meshes), means less - performance - :type mesh_precision: int + :type meshdata: list :param highlight_spec: dictionary that allows passing some specifications to allow highlighting of particular elements. Mostly only helpful for marking segments on multi-compartmental cells. In the main dictionary are more dictionaries, one for each segment id which will be the key: - - marker_color: color of the marker - - marker_size: [diameter 1, diameter 2] (in case of sphere, the first value + - marker_color: color of the marker (str) + - marker_size: (diameter 1, diameter 2) (tuple) (in case of sphere, the first value is used) + - marker_type: "sphere" (str) (otherwise the default shape of the segment is + used, which could either be a sphere or a cylinder) :type highlight_spec: dict :param upright: bool only applicable for single cells: Makes cells "upright" @@ -903,6 +1036,9 @@ def plot_3D_cell_morphology( "upwards" instead of "downwards" in most cases. Note that the original cell object is unchanged, this is for visualization purposes only. :type upright: bool + :param save_mesh_to: name of file to save mesh object to + :type save_mesh_to: str or None + :returns: meshdata :raises: ValueError if `cell` is None """ @@ -911,6 +1047,13 @@ def plot_3D_cell_morphology( "No cell provided. If you would like to plot a network of point neurons, consider using `plot_2D_point_cells` instead" ) + if cell.morphology is None: + logger.error("Cell does not contain a morphology. Cannot visualise.") + logger.error( + "If the cell is referencing an external morphology, please use the `plot_interactive_3D` function and pass the complete document and we will try to load the morphology." + ) + return None + if highlight_spec is None: highlight_spec = {} logging.debug("highlight_spec is " + str(highlight_spec)) @@ -962,20 +1105,35 @@ def plot_3D_cell_morphology( color_dict[s.id] = c if meshdata is None: - meshdata = {} + meshdata = [] for seg in cell.morphology.segments: p = cell.get_actual_proximal(seg.id) d = seg.distal length = cell.get_segment_length(seg.id) - # round up to precision - r1 = round(p.diameter / 2, mesh_precision) - r2 = round(d.diameter / 2, mesh_precision) + r1 = p.diameter / 2 + r2 = d.diameter / 2 + + # ensure larger than provided minimum width + if r1 < min_width: + r1 = min_width + if r2 < min_width: + r2 = min_width + + # if plot is a constant type, fix the widths + if plot_type == "constant": + r1 = min_width + r2 = min_width + # let soma be thicker so that it can be easily made out + if seg.id in soma_segs: + r1 = r1 * 5 + r2 = r2 * 5 segment_spec = { "marker_size": None, "marker_color": None, + "marker_type": None, } try: segment_spec.update(highlight_spec[str(seg.id)]) @@ -992,21 +1150,15 @@ def plot_3D_cell_morphology( logger.debug("segment_spec for " + str(seg.id) + " is" + str(segment_spec)) if segment_spec["marker_size"] is not None: - if not isinstance(segment_spec["marker_size"], list): - raise RuntimeError("The marker size must be a list") - r1 = round(float(segment_spec["marker_size"][0]) / 2, mesh_precision) - r2 = round(float(segment_spec["marker_size"][1]) / 2, mesh_precision) - - key = ( - f"{r1:.{mesh_precision}f}", - f"{r2:.{mesh_precision}f}", - f"{round(length, mesh_precision):.{mesh_precision}f}", - ) + if not isinstance(segment_spec["marker_size"], (tuple)): + raise RuntimeError("The marker size must be a tuple") + r1 = float(segment_spec["marker_size"][0]) / 2 + r2 = float(segment_spec["marker_size"][1]) / 2 seg_color = "white" if color is None: seg_color = get_next_hex_color() - elif color == "Groups": + elif isinstance(color, str) and color.lower() == "groups": try: seg_color = color_dict[seg.id] except KeyError: @@ -1017,7 +1169,7 @@ def plot_3D_cell_morphology( seg_color = "red" elif seg.id in dend_segs: seg_color = "blue" - elif color == "Default Groups": + elif isinstance(color, str) and color.lower() == "default groups": if seg.id in soma_segs: seg_color = "green" elif seg.id in axon_segs: @@ -1030,14 +1182,23 @@ def plot_3D_cell_morphology( if segment_spec["marker_color"] is not None: seg_color = segment_spec["marker_color"] - try: - meshdata[key].append((p, d, seg_color, offset)) - except KeyError: - meshdata[key] = [(p, d, seg_color, offset)] - logger.debug(f"meshdata added: {key}: {(p, d, seg_color, offset)}") + if offset is not None: + meshdata.append( + (f"{r1}", f"{r2}", f"{length}", p, d, seg_color, seg.id, cell, offset) + ) + else: + meshdata.append( + (f"{r1}", f"{r2}", f"{length}", p, d, seg_color, seg.id, cell) + ) + logger.debug(f"meshdata added: {meshdata[-1]}") if not nogui: - create_instanced_meshes(meshdata, plot_type, current_view, min_width) + create_mesh( + meshdata, + current_view, + save_mesh_to=save_mesh_to, + current_canvas=current_canvas, + ) if pynml_in_jupyter: display(current_canvas) else: @@ -1046,160 +1207,27 @@ def plot_3D_cell_morphology( return meshdata -def create_instanced_meshes(meshdata, plot_type, current_view, min_width): - """Internal function to plot instanced meshes from mesh data. - - It is more efficient to collect all the segments that require the same - cylindrical mesh and to create instanced meshes for them. - - See: https://vispy.org/api/vispy.scene.visuals.html#vispy.scene.visuals.InstancedMesh - - :param meshdata: meshdata to plot: dictionary with: - key: (r1, r2, length) - value: [(prox, dist, color, offset)] - :param plot_type: type of plot - :type plot_type: str - :param current_view: vispy viewbox to use - :type current_view: ViewBox - :param min_width: minimum width of tubes - :type min_width: float - """ - total_mesh_instances = 0 - for d, i in meshdata.items(): - total_mesh_instances += len(i) - logger.debug( - f"Visualising {len(meshdata.keys())} meshes with {total_mesh_instances} instances" - ) - - pbar = progressbar.ProgressBar( - max_value=total_mesh_instances, - widgets=[progressbar.SimpleProgress(), progressbar.Bar(), progressbar.Timer()], - redirect_stdout=True, - ) - progress_ctr = 0 - for d, i in meshdata.items(): - r1 = float(d[0]) - r2 = float(d[1]) - length = float(d[2]) - - # actual plotting bits - if plot_type == "constant": - r1 = min_width - r2 = min_width - - if r1 < min_width: - r1 = min_width - if r2 < min_width: - r2 = min_width - - seg_mesh = None - # 1: for points, we set the prox/dist to None since they only have - # positions. - # 2: single compartment cells with r1, r2, and length 0 - # Note: we can't check if r1 == r2 == length because there - # may be cylinders with such a set of parameters - - if r1 == r2 and ((i[0][0] is None and i[0][1] is None) or (length == 0.0)): - seg_mesh = create_sphere(9, 9, radius=r1) - logger.debug(f"Created spherical mesh template with radius {r1}") - else: - rows = 2 + int(length / 2) - seg_mesh = create_cylindrical_mesh( - rows=rows, cols=9, radius=[r1, r2], length=length, closed=True - ) - logger.debug( - f"Created cylinderical mesh template with radii {r1}, {r2}, {length}" - ) - - instance_positions = [] - instance_transforms = [] - instance_colors = [] - - # if in a notebook, only update once per mesh, but not per mesh - # instance - if pynml_in_jupyter: - pbar.update(progress_ctr) - - for num, im in enumerate(i): - # if not in a notebook, update for each mesh instance - if not pynml_in_jupyter: - pbar.update(progress_ctr) - - progress_ctr += 1 - prox = im[0] - dist = im[1] - color = im[2] - offset = im[3] - - # points, spherical meshes - if prox is not None and dist is not None: - orig_vec = [0, 0, length] - dir_vector = [dist.x - prox.x, dist.y - prox.y, dist.z - prox.z] - k = numpy.cross(orig_vec, dir_vector) - mag_k = numpy.linalg.norm(k) - - if mag_k != 0.0: - k = k / mag_k - theta = math.acos( - numpy.dot(orig_vec, dir_vector) - / (numpy.linalg.norm(orig_vec) * numpy.linalg.norm(dir_vector)) - ) - logger.debug(f"k is {k}, theta is {theta}") - rot_matrix = rotate(math.degrees(theta), k).T - rot_obj = Rotation.from_matrix(rot_matrix[:3, :3]) - else: - logger.debug("k is [0..], using zeros for rotation matrix") - rot_matrix = numpy.zeros((3, 3)) - rot_obj = Rotation.from_matrix(rot_matrix) - - instance_positions.append( - [offset[0] + prox.x, offset[1] + prox.y, offset[2] + prox.z] - ) - else: - instance_positions.append(offset) - rot_matrix = numpy.zeros((3, 3)) - rot_obj = Rotation.from_matrix(rot_matrix) - - instance_transforms.append(rot_obj.as_matrix()) - instance_colors.append(color) - - assert len(instance_positions) == len(instance_transforms) - logger.debug( - f"Instanced: positions: {instance_positions}, transforms: {instance_transforms}" - ) - - mesh = InstancedMesh( - meshdata=seg_mesh, - instance_positions=instance_positions, - instance_transforms=instance_transforms, - instance_colors=instance_colors, - parent=current_view.scene, - ) - # TODO: add a shading filter for light? - assert mesh is not None - pbar.finish() - - +@lru_cache(maxsize=100) def plot_3D_schematic( cell: Cell, - segment_groups: typing.Optional[typing.List[SegmentGroup]], - offset: typing.List[float] = [0, 0, 0], + segment_groups: Optional[List[SegmentGroup]] = None, + offset: Optional[Tuple[float, float, float]] = (0.0, 0.0, 0.0), labels: bool = False, - width: float = 5.0, + width: float = 1.0, verbose: bool = False, nogui: bool = False, title: str = "", current_canvas: Optional[scene.SceneCanvas] = None, current_view: Optional[scene.ViewBox] = None, - axes_pos: typing.Optional[ - typing.Union[typing.List[float], typing.List[int], str] + axes_pos: Optional[ + Union[Tuple[float, float, float], Tuple[int, int, int], str] ] = None, theme: str = "light", - color: typing.Optional[str] = "Cell", - meshdata: typing.Optional[typing.Dict[typing.Any, typing.Any]] = None, - mesh_precision: int = 2, + color: Optional[str] = "Cell", + meshdata: Optional[List[Any]] = None, upright: bool = False, -) -> None: + save_mesh_to: Optional[str] = None, +) -> Optional[List[Any]]: """Plot a 3D schematic of the provided segment groups using vispy. layer.. @@ -1223,10 +1251,13 @@ def plot_3D_schematic( for plotting cells with detailed morphologies :param offset: offset for cell - :type offset: [float, float, float] + Note that this is only used in creating the meshdata. If set to None, + this is ommitted from the meshdata, and the mesh creator will set it to + origin. + :type offset: (float, float, float) or None :param cell: cell to plot :type cell: neuroml.Cell - :param segment_groups: list of unbranched segment groups to plot + :param segment_groups: list of unbranched segment groups to plot, all if None :type segment_groups: list(SegmentGroup) :param labels: toggle labelling of segment groups :type labels: bool @@ -1252,17 +1283,20 @@ def plot_3D_schematic( - "origin": automatically added at origin - "bottom left": automatically added at bottom left - :type axes_pos: [float, float, float] or [int, int, int] or None or str + :type axes_pos: (float, float, float) or (int, int, int) or None or str :param theme: theme to use (light/dark) :type theme: str :param color: color to use for segment groups with some special values: - if None, each unbranched segment group is given a unique color, - - if "Cell", each cell is given a unique color + - if "Cell", the whole cell is given one color - if "Default Groups", each cell is given unique colors for all axons, dendrites, and soma segments :type color: str + :param meshdata: dictionary used to store mesh related data for vispy + visualisation + :type meshdata: dict :param upright: bool only applicable for single cells: Makes cells "upright" (along Y axis) by calculating its PCA, rotating it so it is along the Y axis, and transforming cell co-ordinates to align along the rotated first principal @@ -1271,10 +1305,20 @@ def plot_3D_schematic( "upwards" instead of "downwards" in most cases. Note that the original cell object is unchanged, this is for visualization purposes only. :type upright: bool + :param save_mesh_to: name of file to save mesh object to + :type save_mesh_to: str or None + :returns: meshdata """ if title == "": title = f"3D schematic of segment groups from {cell.id}" + if cell.morphology is None: + logger.error("Cell does not contain a morphology. Cannot visualise.") + logger.error( + "If the cell is referencing an external morphology, please use the `plot_interactive_3D` function and pass the complete document and we will try to load the morphology." + ) + return None + view_center = None if upright: cell = make_cell_upright(cell) @@ -1321,7 +1365,7 @@ def plot_3D_schematic( cell_color_dendrites = get_next_hex_color() if meshdata is None: - meshdata = {} + meshdata = [] for sgid, segs in ord_segs.items(): sgobj = cell.get_segment_group(sgid) @@ -1331,28 +1375,27 @@ def plot_3D_schematic( ) # get proximal and distal points - first_seg = segs[0] # type: Segment - last_seg = segs[-1] # type: Segment - first_prox = cell.get_actual_proximal(first_seg.id) # type: Point3DWithDiam - last_dist = last_seg.distal # type: Point3DWithDiam + first_seg: Segment = segs[0] + last_seg: Segment = segs[-1] + first_prox: Point3DWithDiam = cell.get_actual_proximal(first_seg.id) + last_dist: Point3DWithDiam = last_seg.distal length = math.dist( (first_prox.x, first_prox.y, first_prox.z), (last_dist.x, last_dist.y, last_dist.z), ) - key = ( - f"{round(first_prox.diameter/2, mesh_precision):.{mesh_precision}f}", - f"{round(last_dist.diameter/2, mesh_precision):.{mesh_precision}f}", - f"{round(length, mesh_precision):.{mesh_precision}f}", - ) + seg_width = width + + if first_seg.id in soma_segs and last_seg.id in soma_segs: + seg_width = width * 5 branch_color = color if color is None: branch_color = get_next_hex_color() - elif color == "Cell": + elif isinstance(color, str) and color.lower() == "cell": branch_color = cell_color_soma - elif color == "Default Groups": + elif isinstance(color, str) and color.lower() == "default groups": if first_seg.id in soma_segs: branch_color = cell_color_soma elif first_seg.id in axon_segs: @@ -1364,23 +1407,130 @@ def plot_3D_schematic( else: branch_color = color - try: - meshdata[key].append((first_prox, last_dist, branch_color, offset)) - except KeyError: - meshdata[key] = [(first_prox, last_dist, branch_color, offset)] + if offset is not None: + meshdata.append( + ( + seg_width, + seg_width, + f"{length}", + first_prox, + last_dist, + branch_color, + offset, + ) + ) + else: + meshdata.append( + ( + seg_width, + seg_width, + f"{length}", + first_prox, + last_dist, + branch_color, + ) + ) if not nogui: - create_instanced_meshes(meshdata, "Detailed", current_view, width) + create_mesh( + meshdata, + current_view, + save_mesh_to=save_mesh_to, + current_canvas=current_canvas, + ) if pynml_in_jupyter: display(current_canvas) else: + current_canvas.show() app.run() + return meshdata + +@lru_cache(maxsize=10000) +def create_spherical_mesh( + rows=10, + cols=10, + depth=10, + radius=1.0, + offset=True, + subdivisions=3, + method="latitude", +): + """Wrapper around vispy.geometry.create_sphere to allow the use of a cache""" + return create_sphere( + rows=rows, + cols=cols, + depth=depth, + radius=radius, + offset=offset, + subdivisions=subdivisions, + method=method, + ) + + +@lru_cache(maxsize=100) +def compute_faces_of_cylindrical_mesh(rows: int, cols: int, closed: bool): + """Compute faces for cylindrical meshes + + Since we tend to use a constant set of rows and cols, this function should + be called repeatedly with the same values, and thus benefits from caching. + + :param rows: number of rows in mesh + :type rows: int + :param cols: number of cols in mesh + :type cols: int + :param closed: toggle whether mesh is closed or open + :type closed: bool + :returns: numpy array with faces (triplets of vertex indices) + + """ + faces = numpy.empty((rows * cols * 2, 3), dtype=numpy.uint32) + rowtemplate1 = ( + (numpy.arange(cols).reshape(cols, 1) + numpy.array([[0, 1, 0]])) % cols + ) + numpy.array([[0, 0, cols]]) + logger.debug(f"Template1 is: {rowtemplate1}") + rowtemplate2 = ( + (numpy.arange(cols).reshape(cols, 1) + numpy.array([[0, 1, 1]])) % cols + ) + numpy.array([[cols, 0, cols]]) + # logger.debug(f"Template2 is: {rowtemplate2}") + + for row in range(rows): + start = row * cols * 2 + faces[start : start + cols] = rowtemplate1 + row * cols + faces[start + cols : start + (cols * 2)] = rowtemplate2 + row * cols + + num_verts = (rows + 1) * cols + # used below: + # index of center of first cap = num_verts + # index of center of second cap = num_verts + 1 + + # add extra faces to cover the caps + if closed is True: + cap1 = numpy.arange(cols).reshape(cols, 1) + cap1 = numpy.concatenate( + (numpy.full((cols, 1), num_verts), cap1, numpy.roll(cap1, 1)), axis=1 + ) + logger.debug(f"cap1 is {cap1}") + + cap2 = numpy.arange(rows * cols, (rows + 1) * cols).reshape(cols, 1) + cap2 = numpy.concatenate( + (numpy.full((cols, 1), num_verts + 1), cap2, numpy.roll(cap2, 1)), axis=1 + ) + logger.debug(f"cap2 is {cap2}") + + faces = numpy.append(faces, cap1, axis=0) + faces = numpy.append(faces, cap2, axis=0) + + logger.debug(f"Faces are: {faces}") + return faces + + +@lru_cache(maxsize=10000) def create_cylindrical_mesh( rows: int, cols: int, - radius: typing.Union[float, typing.List[float]] = [1.0, 1.0], + radius: Union[float, Tuple[float, float]] = (1.0, 1.0), length: float = 1.0, closed: bool = True, ): @@ -1392,7 +1542,7 @@ def create_cylindrical_mesh( :param cols: number of columns :type cols: int :param radius: float or pair of floats for the two radii of the cylinder - :type radius: float or [float, float][] + :type radius: float or (float, float) :param length: length of cylinder :type length: float :param closed: whether the cylinder should be closed @@ -1403,7 +1553,7 @@ def create_cylindrical_mesh( """ verts = numpy.empty((rows + 1, cols, 3), dtype=numpy.float32) if isinstance(radius, int) or isinstance(radius, float): - radius = [radius, radius] # convert to list + radius = (radius, radius) # convert to tuple # compute theta values th = numpy.linspace(2 * numpy.pi, 0, cols).reshape(1, cols) @@ -1424,39 +1574,312 @@ def create_cylindrical_mesh( # add extra points for center of two circular planes that form the caps if closed is True: - verts = numpy.append(verts, [[0.0, 0.0, 0.0], [0.0, 0.0, 1.0]], axis=0) + verts = numpy.append(verts, [[0.0, 0.0, 0.0], [0.0, 0.0, length]], axis=0) logger.debug(f"Verts are: {verts}") - # compute faces - faces = numpy.empty((rows * cols * 2, 3), dtype=numpy.uint32) - rowtemplate1 = ( - (numpy.arange(cols).reshape(cols, 1) + numpy.array([[0, 1, 0]])) % cols - ) + numpy.array([[0, 0, cols]]) - logger.debug(f"Template1 is: {rowtemplate1}") + faces = compute_faces_of_cylindrical_mesh(rows, cols, closed) - rowtemplate2 = ( - (numpy.arange(cols).reshape(cols, 1) + numpy.array([[0, 1, 1]])) % cols - ) + numpy.array([[cols, 0, cols]]) - # logger.debug(f"Template2 is: {rowtemplate2}") + return MeshData(vertices=verts, faces=faces) - for row in range(rows): - start = row * cols * 2 - faces[start : start + cols] = rowtemplate1 + row * cols - faces[start + cols : start + (cols * 2)] = rowtemplate2 + row * cols - # add extra faces to cover the caps - if closed is True: - cap1 = (numpy.arange(cols).reshape(cols, 1) + numpy.array([[0, 0, 1]])) % cols - cap1[..., 0] = len(verts) - 2 - cap2 = (numpy.arange(cols).reshape(cols, 1) + numpy.array([[0, 0, 1]])) % cols - cap2[..., 0] = len(verts) - 1 +def create_mesh( + meshdata: List[ + Tuple[ + float, + float, + float, + Point3DWithDiam, + Point3DWithDiam, + Union[str, Tuple[float, float, float]], + int, + Cell, + Optional[Tuple[float, float, float]], + ] + ], + current_view: ViewBox, + save_mesh_to: Optional[str], + current_canvas: scene.SceneCanvas, +): + """Internal function to create a mesh from the mesh data - logger.debug(f"cap1 is {cap1}") - logger.debug(f"cap2 is {cap2}") + See: https://vispy.org/api/vispy.scene.visuals.html#vispy.scene.visuals.Mesh - faces = numpy.append(faces, cap1, axis=0) - faces = numpy.append(faces, cap2, axis=0) + :param meshdata: meshdata to plot: list with: + [(r1, r2, length, prox, dist, color, seg id, cell object offset)] + :type meshdata: list of tuples + :param current_view: vispy viewbox to use + :type current_view: ViewBox + :param save_mesh_to: name of file to save mesh object to + :type save_mesh_to: str or None + :param scene: vispy scene object + :type scene: scene.SceneCanvas + """ + mesh_start = time.time() + total_mesh_instances = len(meshdata) + logger.info(f"Processing {total_mesh_instances} segments") - logger.debug(f"Faces are: {faces}") + pbar_interval = max(1, pow(10, (len(str(total_mesh_instances)) - 3))) - return MeshData(vertices=verts, faces=faces) + vispy_color_dict = get_color_dict() + + main_mesh_vertices = [] + num_vertices = 0 + main_mesh_faces = [] + main_mesh_colors = [] + # dictionary storing faces as keys and corresponding segment ids as values + faces_to_segment = {} + + pbar = progressbar.ProgressBar( + max_value=total_mesh_instances, + widgets=[progressbar.SimpleProgress(), progressbar.Bar(), progressbar.Timer()], + redirect_stdout=True, + ) + progress_ctr = 0 + for d in meshdata: + r1 = float(d[0]) + r2 = float(d[1]) + length = float(d[2]) + prox = d[3] + dist = d[4] + color = d[5] + if len(d) >= 8: + seg_id = d[6] + cell = d[7] + offset = d[8] + else: + seg_id = None + cell = None + offset = d[6] + if offset is None: + offset = (0.0, 0.0, 0.0) + + seg_mesh = None + # 1: for points, we set the prox/dist to None since they only have + # positions. + # 2: single compartment cells with r1, r2, and length 0 + # Note: we can't check if r1 == r2 == length because there + # may be cylinders with such a set of parameters + + if r1 == r2 and ((prox is None and dist is None) or (length == 0.0)): + seg_mesh = create_spherical_mesh(9, 9, radius=r1) + logger.debug(f"Created spherical mesh template with radius {r1}") + else: + rows = 2 + int(length / 2) + seg_mesh = create_cylindrical_mesh( + rows=rows, cols=9, radius=(r1, r2), length=length, closed=True + ) + logger.debug( + f"Created cylinderical mesh template with radii {r1}, {r2}, {length}" + ) + + logger.debug(f"Color is {color}") + if isinstance(color, str): + if color.startswith("#"): + color = to_rgb(color) + else: + try: + vispy_color_hash = vispy_color_dict[color.lower()] + color = to_rgb(vispy_color_hash) + except KeyError: + logger.warning(f"{color} is not recognised by vispy") + logger.warning( + "Valid colors can be seen using `vispy.color.get_color_names`, or you may use the hex notation" + ) + # get a new random color, and add it to dict so it's used + # everywhere in the mesh + new_color = random.choice(list(vispy_color_dict.keys())) + vispy_color_dict[color] = vispy_color_dict[new_color] + logger.warning(f"Using {new_color} instead") + color = to_rgb(vispy_color_dict[color]) + + # cylinders + if prox is not None and dist is not None: + orig_vec = [0, 0, length] + dir_vector = [dist.x - prox.x, dist.y - prox.y, dist.z - prox.z] + k = numpy.cross(orig_vec, dir_vector) + mag_k = numpy.linalg.norm(k) + + vertices = seg_mesh.get_vertices() + + if mag_k != 0.0: + k = k / mag_k + theta = math.acos( + numpy.dot(orig_vec, dir_vector) + / (numpy.linalg.norm(orig_vec) * numpy.linalg.norm(dir_vector)) + ) + logger.debug(f"k is {k}, theta is {theta}") + rot_matrix = rotate(math.degrees(theta), k).T + rot_obj = Rotation.from_matrix(rot_matrix[:3, :3]) + rotated_vertices = rot_obj.apply(vertices) + else: + logger.debug("k is [0..], skipping rotation") + rotated_vertices = vertices + + translator = numpy.array( + [offset[0] + prox.x, offset[1] + prox.y, offset[2] + prox.z] + ) + translated_vertices = rotated_vertices + translator + main_mesh_faces.append(seg_mesh.get_faces() + num_vertices) + # Faces to segments + if seg_id is not None: + for face in seg_mesh.get_faces() + num_vertices: + faces_to_segment[tuple(face)] = seg_id + + main_mesh_vertices.append(translated_vertices) + main_mesh_colors.append([[*color, 1]] * len(vertices)) + + num_vertices += len(vertices) + else: + # only translation here + translator = numpy.array([offset[0], offset[1], offset[2]]) + vertices = seg_mesh.get_vertices() + translated_vertices = vertices + translator + + main_mesh_faces.append(seg_mesh.get_faces() + num_vertices) + # Faces to segments + if seg_id is not None: + for face in seg_mesh.get_faces() + num_vertices: + faces_to_segment[tuple(face)] = seg_id + + main_mesh_vertices.append(translated_vertices) + main_mesh_colors.append([[*color, 1]] * len(vertices)) + + num_vertices += len(translated_vertices) + + if (progress_ctr % pbar_interval) == 0: + pbar.update(progress_ctr) + progress_ctr += 1 + + numpy_mesh_vertices = numpy.concatenate(main_mesh_vertices, axis=0) + numpy_mesh_faces = numpy.concatenate(main_mesh_faces, axis=0) + numpy_mesh_colors = numpy.concatenate(main_mesh_colors, axis=0) + face_colors = numpy.tile((0.5, 0.0, 0.5, 1.0), (len(numpy_mesh_faces), 1)) + + logger.debug(f"Vertices: {numpy_mesh_vertices.shape}") + logger.debug(f"Faces: {numpy_mesh_faces.shape}") + + mesh = Mesh( + vertices=numpy_mesh_vertices, + faces=numpy_mesh_faces, + parent=current_view.scene, + vertex_colors=numpy_mesh_colors, + face_colors=face_colors.copy(), + ) + mesh.interactive = True + + assert mesh is not None + pbar.finish() + mesh_end = time.time() + logger.debug(f"Mesh creation took {(mesh_end - mesh_start)}") + + # lighting + # light dir from the front right and above + # for vispy, y is up, z is to the right, and x is inwards + # so, go diagonally from bounds to get the light vector, not quite + # diagonally + cam = current_view.camera + cam_center = cam.center + logger.debug(f"Cam center is {cam_center}") + logger.debug(f"Cam lims are {cam._xlim}, {cam._ylim}, {cam._zlim}") + light_dir = ( + cam._xlim[1] - cam._xlim[0] / 2, + -1 * (cam._ylim[1] - cam._ylim[0] / 2), + -1 * (cam._zlim[1] - cam._zlim[0] / 2), + 0, + ) + logger.debug(f"Light dir is: {light_dir}") + shading_filter = ShadingFilter( + shading="flat", + shininess=10, + ambient_light=(1, 1, 1, 0.5), + specular_light=(1, 1, 1, 0.5), + light_dir=light_dir[:3], + ) + face_picking_filter = FacePickingFilter() + mesh.attach(shading_filter) + mesh.attach(face_picking_filter) + + def attach_headlight(current_view): + shading_filter.light_dir = light_dir[:3] + initial_light_dir = current_view.camera.transform.imap(light_dir) + + @current_view.scene.transform.changed.connect + def on_transform_change(event): + transform = current_view.camera.transform + shading_filter.light_dir = transform.map(initial_light_dir)[:3] + + # For handling mouse press + # currently identifies the segment and prints some information out to the + # terminal about it. + @current_canvas.events.mouse_press.connect + def on_mouse_press(event): + clicked_mesh = current_canvas.visual_at(event.pos) + if isinstance(clicked_mesh, Mesh) and seg_id is not None: + # adjust the event position for hidpi screens + render_size = tuple( + d * current_canvas.pixel_scale for d in current_canvas.size + ) + x_pos = event.pos[0] * current_canvas.pixel_scale + y_pos = render_size[1] - (event.pos[1] * current_canvas.pixel_scale) + + # render a small patch around the mouse cursor + restore_state = not face_picking_filter.enabled + face_picking_filter.enabled = True + mesh.update_gl_state(blend=False) + picking_render = current_canvas.render( + region=(x_pos - 1, y_pos - 1, 3, 3), + size=(3, 3), + bgcolor=(0, 0, 0, 0), + alpha=True, + ) + if restore_state: + face_picking_filter.enabled = False + mesh.update_gl_state(blend=not face_picking_filter.enabled) + + # unpack the face index from the color in the center pixel + face_idx = (picking_render.view(numpy.uint32) - 1)[1, 1, 0] + picked_face = tuple(mesh._meshdata._faces[face_idx]) + picked_seg_id = faces_to_segment[picked_face] + + logger.debug(f"face id is: {face_idx}") + logger.debug(f"face is: {picked_face}") + logger.debug(f"corresponding segment is: {picked_seg_id}") + + clicked_on_seg(picked_seg_id, cell) + + attach_headlight(current_view) + + if save_mesh_to is not None: + if not save_mesh_to.endswith((".obj", ".gz")): + logger.info( + f"Vispy requires mesh file to end in '.obj' or '.gz', appending '.obj' to {save_mesh_to}" + ) + save_mesh_to += ".obj" + + logger.info(f"Saving mesh to {save_mesh_to}") + write_mesh( + fname=save_mesh_to, + vertices=mesh.mesh_data.get_vertices(), + faces=mesh.mesh_data.get_faces(), + normals=None, + texcoords=None, + overwrite=False, + ) + + +def clicked_on_seg(seg_id: int, cell: Cell): + """ + Callback function called when a segment is clicked on. + + Prints information about the segment. + + Based on Vispy examples: + https://vispy.org/gallery/scene/face_picking.html#sphx-glr-gallery-scene-face-picking-py + + :param seg_id: id of segment + :type seg_id: int + :param cell: cell object that segment belongs to + :type cell: Cell + """ + print(f"Clicked on: Cell: {cell.id}; segment: {seg_id}.") + print(f"Segment info: {cell.get_segment_location_info(seg_id)}") diff --git a/pyneuroml/plot/PlotSpikes.py b/pyneuroml/plot/PlotSpikes.py index 4723d959..af99487a 100644 --- a/pyneuroml/plot/PlotSpikes.py +++ b/pyneuroml/plot/PlotSpikes.py @@ -18,7 +18,7 @@ import matplotlib.pyplot as plt import numpy as np -import pyneuroml.lems as pynmll +import pyneuroml.utils.simdata as pynmls from pyneuroml.plot import generate_plot from pyneuroml.utils.cli import build_namespace @@ -480,7 +480,7 @@ def plot_spikes_from_lems_file( :type lems_file_name: str :param base_dir: Directory where the LEMS file resides. Defaults to the current directory. :type base_dir: str - :param show_plots_already: Whether to show the plots immediately after they are generated. Defaults to True. + :param show_plots_already: Whether to show the plots :type show_plots_already: bool :param save_spike_plot_to: Path to save the spike plot to. If `None`, the plot will not be saved. Defaults to `None`. :type save_spike_plot_to: Optional[str] @@ -493,31 +493,38 @@ def plot_spikes_from_lems_file( :return: None :rtype: None """ - event_data = pynmll.load_sim_data_from_lems_file( + all_events: Dict[str, Dict] = pynmls.load_sim_data_from_lems_file( lems_file_name, get_events=True, get_traces=False ) - spike_data = [] # type: List[Dict] - for select, times in event_data.items(): - new_dict = {"name": select} - new_dict["times"] = times - # the plot_spikes function will add an offset for each data entry, so - # we set the ids to 0 here - new_dict["ids"] = [0] * len(times) - - spike_data.append(new_dict) - - logger.debug("Spike data is:") - logger.debug(spike_data) + if len(all_events) > 1: + show_each_plot_already = False + + for filename, event_data in all_events.items(): + spike_data = [] # type: List[Dict] + for select, times in event_data.items(): + new_dict = {"name": select} + new_dict["times"] = times + # the plot_spikes function will add an offset for each data entry, so + # we set the ids to 0 here + new_dict["ids"] = [0] * len(times) + + spike_data.append(new_dict) + + logger.debug("Spike data is:") + logger.debug(spike_data) + + plot_spikes( + spike_data, + show_plots_already=show_each_plot_already, + save_spike_plot_to=save_spike_plot_to, + rates=rates, + rate_window=rate_window, + rate_bins=rate_bins, + ) - plot_spikes( - spike_data, - show_plots_already=show_plots_already, - save_spike_plot_to=save_spike_plot_to, - rates=rates, - rate_window=rate_window, - rate_bins=rate_bins, - ) + if show_plots_already is True and show_each_plot_already is False: + plt.show() def main(args: Optional[argparse.Namespace] = None) -> None: diff --git a/pyneuroml/plot/PlotTimeSeries.py b/pyneuroml/plot/PlotTimeSeries.py index 9cae70e9..16c353b0 100644 --- a/pyneuroml/plot/PlotTimeSeries.py +++ b/pyneuroml/plot/PlotTimeSeries.py @@ -16,15 +16,19 @@ from matplotlib import pyplot as plt from matplotlib_scalebar.scalebar import ScaleBar -import pyneuroml.lems as pynmll import pyneuroml.plot.Plot as pynmlplt +import pyneuroml.utils.simdata as simd from pyneuroml.utils.cli import build_namespace logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) +logger.setLevel(logging.WARNING) -TIME_SERIES_PLOTTER_DEFAULTS = {"offset": False} +TIME_SERIES_PLOTTER_DEFAULTS = { + "offset": False, + "labels": False, + "singlePlot": False, +} def plot_time_series( @@ -33,7 +37,7 @@ def plot_time_series( typing.List[typing.Dict[typing.Any, typing.Any]], ], title: str = "", - offset: bool = True, + offset: bool = False, show_plot_already: bool = True, scalebar_location: typing.Optional[str] = None, scalebar_length: typing.Optional[float] = None, @@ -81,6 +85,11 @@ def plot_time_series( if isinstance(trace_data, dict): trace_data = [trace_data] + # if scalebar needs to be drawn, we need to wait until all plots are done + show_this_plot_already = ( + False if scalebar_location is not None else show_plot_already + ) + num_traces = 0 for td in trace_data: num_traces += len(td) @@ -88,10 +97,7 @@ def plot_time_series( xs = [] ys = [] - if labels is True: - labelvals = [] - else: - labelvals = None + labelvals: typing.List[str] = [] # calculate trace width miny = float(math.inf) @@ -143,13 +149,15 @@ def plot_time_series( else: show_yticklabels = True + # if a scalebar is to be set, we need to wait for it to be added before + # showing the plot ax = pynmlplt.generate_plot( xvalues=xs, yvalues=ys, title=title, - labels=labelvals, + labels=labelvals if labels is True else None, show_yticklabels=show_yticklabels, - show_plot_already=False, + show_plot_already=show_this_plot_already, **kwargs_generate_plot, ) @@ -168,14 +176,23 @@ def plot_time_series( ) print(f"Note: length of the scalebar is {scalebar_length} units") + + assert ax ax.add_artist(scalebar_) - if show_plot_already is True: - plt.show() + if show_plot_already is True: + plt.show() def plot_time_series_from_lems_file( - lems_file_name: str, base_dir: str = ".", title: str = "", **kwargs + lems_file_name: str, + base_dir: str = ".", + title: str = "", + labels: bool = True, + single_plot: bool = False, + show_plot_already: bool = True, + save_figure_to: typing.Optional[str] = None, + **kwargs, ) -> None: """Plot time series from a LEMS file. @@ -193,19 +210,40 @@ def plot_time_series_from_lems_file( :type lems_file_name: str :param base_dir: directory where LEMS file resides :type base_dir: str + :param labels: toggle whether plots should be labelled + :type labels: bool + :param show_plot_already: whether the generated plots should be shown: + useful if you want to only save the plots to files without showing them + :type show_plot_already: bool :param kwargs: other arguments passed to `plot_time_series` :returns: None """ - traces = pynmll.load_sim_data_from_lems_file( - lems_file_name, get_events=False, get_traces=True + # the user wants to see the plots + all_traces = simd.load_sim_data_from_lems_file( + lems_file_name, base_dir, get_events=False, get_traces=True + ) + assert all_traces + _plot_traces( + all_traces=all_traces, + title=title, + labels=labels, + single_plot=single_plot, + show_plot_already=show_plot_already, + save_figure_to=save_figure_to, + **kwargs, ) - - plot_time_series(traces, xaxis="Time (s)", **kwargs) def plot_time_series_from_data_files( - data_file_names: typing.Union[str, typing.List[str]], **kwargs + data_file_names: typing.Union[str, typing.List[str]], + title: str = "", + labels: bool = True, + columns: typing.Optional[typing.List[int]] = None, + single_plot: bool = False, + show_plot_already: bool = True, + save_figure_to: typing.Optional[str] = None, + **kwargs, ): """Plot time series from a data file. @@ -215,25 +253,110 @@ def plot_time_series_from_data_files( :param data_file_names: name/path to data file(s) :type data_file_names: str or list of strings + :param labels: toggle whether plots should be labelled + :type labels: bool + :param columns: column indices to plot + :type columns: list of ints: [1, 2, 3] + :param single_plot: whether all data should be plotted in one single plot + :type single_plot: bool + :param save_figure_to: file to save figure to + note that if there are multiple figures, this is ignored and the files + are named based on the input files + :type save_figure_to: str :param kwargs: other key word arguments that are passed to the `plot_time_series` function """ - all_traces = [] - if isinstance(data_file_names, str): - data_file_names = [data_file_names] + all_traces = simd.load_traces_from_data_file(data_file_names, columns) + assert all_traces + _plot_traces( + all_traces=all_traces, + title=title, + labels=labels, + single_plot=single_plot, + show_plot_already=show_plot_already, + save_figure_to=save_figure_to, + **kwargs, + ) - for f in data_file_names: - print(f"Processing: {f}") - traces = {} - data_array = numpy.loadtxt(f) - traces["t"] = data_array[:, 0] - num_cols = numpy.shape(data_array)[1] - for i in range(1, num_cols, 1): - traces[str(i)] = data_array[:, i] - all_traces.append(traces) - plot_time_series(all_traces, labels=False, **kwargs) +def _plot_traces( + all_traces: typing.Dict[str, typing.Dict], + title: str = "", + labels: bool = True, + offset: bool = False, + single_plot: bool = False, + show_plot_already: bool = False, + save_figure_to: typing.Optional[str] = None, + **kwargs, +) -> None: + """Worker function for plotting traces. + + :param all_traces: dict with traces + :param labels: toggle whether plots should be labelled + :type labels: bool + :param single_plot: whether all data should be plotted in one single plot + :type single_plot: bool + :param save_figure_to: file to save figure to + note that if there are multiple figures, this is ignored and the files + are named based on the input files + :type save_figure_to: str + :param show_plot_already: whether the generated plots should be shown: + useful if you want to only save the plots to files without showing them + :type show_plot_already: bool + :returns: None + + """ + show_plots = show_plot_already + if len(all_traces) > 1 and single_plot is False and save_figure_to: + # we will show all plots together at the end instead of one by one, + # which blocks on each plot + show_plot_already = False + + # let the user know + logger.warning( + "Ignoring 'save_figure_to': each plot will be saved in individual files of the form .png" + ) + + if not single_plot: + for f, traces in all_traces.items(): + if save_figure_to: + if len(all_traces) > 1: + file_name = f"{f}.png" + else: + file_name = save_figure_to + else: + file_name = None + + plot_time_series( + traces, + title=title, + labels=labels, + offset=offset, + show_plot_already=(show_plots and show_plot_already), + save_figure_to=file_name, + **kwargs, + ) + else: + # all traces in one single plot + flat_traces = {} + for f, traces in all_traces.items(): + flat_traces.update(traces) + + plot_time_series( + flat_traces, + title=title, + labels=labels, + offset=offset, + show_plot_already=(show_plots and show_plot_already), + save_figure_to=save_figure_to, + **kwargs, + ) + + # if the user wants to see the plots, but we delayed to show them all + # together + if show_plots and show_plot_already: + plt.show() def _process_time_series_plotter_args(): @@ -248,15 +371,34 @@ def _process_time_series_plotter_args(): "input_files", type=str, metavar="", - nargs="*", + nargs="+", help="a LEMS file (LEMS_..) or data files to plot time series from", ) + parser.add_argument( + "-columns", + type=int, + metavar="", + nargs="*", + help="column indices to plot if data files are provided", + ) + parser.add_argument( + "-labels", + action="store_true", + default=TIME_SERIES_PLOTTER_DEFAULTS["labels"], + help=("Label plots"), + ) parser.add_argument( "-offset", action="store_true", default=TIME_SERIES_PLOTTER_DEFAULTS["offset"], - help=("Toggle whether plots are overlaid or offset"), + help=("Offset plots"), + ) + parser.add_argument( + "-singlePlot", + action="store_true", + default=TIME_SERIES_PLOTTER_DEFAULTS["singlePlot"], + help=("For data files: whether they should be plotted in a single plot"), ) parser.add_argument( "-saveToFile", @@ -280,13 +422,17 @@ def _time_series_plotter_main(args=None): plot_time_series_from_lems_file( a.input_files[0], offset=a.offset, + labels=a.labels, bottom_left_spines_only=True, save_figure_to=a.save_to_file, ) else: plot_time_series_from_data_files( a.input_files, + columns=a.columns, offset=a.offset, + labels=a.labels, + single_plot=a.single_plot, bottom_left_spines_only=True, save_figure_to=a.save_to_file, ) diff --git a/pyneuroml/pynml.py b/pyneuroml/pynml.py index 6f660b0a..2ffab39f 100644 --- a/pyneuroml/pynml.py +++ b/pyneuroml/pynml.py @@ -567,7 +567,7 @@ def _evaluate_arguments(args): # Deal with the SBML validation option which doesn't call run_jneuroml if args.validate_sbml or args.validate_sbml_units: - file_types = ["sbml","xml"] + file_types = ["sbml", "xml"] try: from pyneuroml.sbml import validate_sbml_files except Exception: @@ -672,13 +672,13 @@ def _evaluate_arguments(args): # TODO: handle these better if args.sbml_import or args.sbml_import_units or args.vhdl: if args.sbml_import: - file_types = ["sbml"] + file_types = ["sbml", "xml"] pre_args = "-sbml-import" f = args.sbml_import[0] post_args = " ".join(args.sbml_import[1:]) confirm_file_type(f, file_types, sys_error=True) elif args.sbml_import_units: - file_types = ["sbml"] + file_types = ["sbml", "xml"] pre_args = "-smbl-import-units" f = args.sbml_import_units[0] post_args = " ".join(args.sbml_import_units[1:]) @@ -874,13 +874,13 @@ def _evaluate_arguments(args): exit(0) elif args.validate: - file_types = ["nml"] + file_types = ["nml", "xml"] pre_args = "-validate" exit_on_fail = True run_multi = True elif args.validatev1: - file_types = ["nml"] + file_types = ["nml", "xml"] pre_args = "-validatev1" exit_on_fail = True run_multi = True @@ -944,6 +944,12 @@ def reload_standard_dat_file(file_name: str) -> typing.Tuple[dict, list]: :type file_name: str :returns: tuple of (data, column names) """ + warnings.warn( + "This function will be removed in the future. Please prefer pyneuroml.utils.simdata.load_traces_from_data_file.", + FutureWarning, + stacklevel=2, + ) + with open(file_name) as dat_file: data = {} # type: dict indices = [] # type: list diff --git a/pyneuroml/runners.py b/pyneuroml/runners.py index 185394d5..a2240265 100644 --- a/pyneuroml/runners.py +++ b/pyneuroml/runners.py @@ -9,7 +9,6 @@ import inspect import logging -import math import os import pathlib import shlex @@ -24,12 +23,14 @@ from typing import Optional import ppft as pp -from lxml import etree +import pyneuroml.plot.PlotTimeSeries as pynmlt import pyneuroml.utils import pyneuroml.utils.misc +import pyneuroml.utils.simdata as pynmls from pyneuroml import DEFAULTS, __version__ from pyneuroml.errors import UNKNOWN_ERR +from pyneuroml.utils.misc import chdir logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -705,6 +706,7 @@ def run_jneuroml( report_jnml_output: bool = True, exit_on_fail: bool = False, return_string: bool = False, + output_prefix: str = " jNeuroML >> ", ) -> typing.Union[typing.Tuple[bool, str], bool]: """Run jnml with provided arguments. @@ -726,6 +728,8 @@ def run_jneuroml( :type exit_on_fail: bool :param return_string: toggle whether the output string should be returned :type return_string: bool + :param output_prefix: string to prefix the returned jNeuroML output with + :type output_prefix: str :returns: either a bool, or a Tuple (bool, str) depending on the value of return_string: True of jnml ran successfully, False if not; along with the @@ -756,7 +760,7 @@ def run_jneuroml( try: command = f'java -Xmx{max_memory} {pre_jar} -jar "{jar_path}" {pre_args} {target_file} {post_args}' retcode, output = execute_command_in_dir( - command, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " + command, exec_in_dir, verbose=verbose, prefix=output_prefix ) if retcode != 0: @@ -770,14 +774,11 @@ def run_jneuroml( return False if report_jnml_output: - logger.debug( + logger.info( "Successfully ran the following command using pyNeuroML v%s: \n %s" % (__version__, command) ) - logger.debug("Output:\n\n%s" % output) - - # except KeyboardInterrupt as e: - # raise e + logger.info("Output:\n\n%s" % output) except Exception as e: logger.error("*** Execution of jnml has failed! ***") @@ -905,7 +906,7 @@ def execute_command_in_dir_with_realtime_output( ) with p.stdout: for line in iter(p.stdout.readline, ""): - print("# %s" % line.strip()) + print(" %s %s" % (prefix, line.strip())) p.wait() # wait for the subprocess to exit print("####################################################################") @@ -922,8 +923,8 @@ def execute_command_in_dir_with_realtime_output( raise e if not p.returncode == 0: - logger.critical( - "*** Problem running command (return code: %s): \n %s" + logger.error( + "*** Problem running command (return code: %s): [%s]" % (p.returncode, command) ) @@ -993,13 +994,14 @@ def execute_command_in_dir( return return_string.decode("utf-8") except subprocess.CalledProcessError as e: - logger.critical("*** Problem running command: \n %s" % e) - logger.critical( - "%s%s" % (prefix, e.output.decode().replace("\n", "\n" + prefix)) - ) + logger.error("*** Problem running last command: %s" % e) + + print("####################################################################") + print("%s%s" % (prefix, e.output.decode().replace("\n", "\n" + prefix))) + print("####################################################################") return (e.returncode, e.output.decode()) except Exception as e: - logger.critical("*** Unknown problem running command: %s" % e) + logger.error("*** Unknown problem running command: %s" % e) return (-1, str(e)) @@ -1011,233 +1013,136 @@ def reload_saved_data( show_plot_already: bool = True, simulator: typing.Optional[str] = None, reload_events: bool = False, + reload_traces: bool = True, verbose: bool = DEFAULTS["v"], remove_dat_files_after_load: bool = False, -) -> typing.Union[dict, typing.Tuple[dict, dict]]: +) -> typing.Union[ + typing.Dict[str, typing.Dict], + typing.Tuple[typing.Dict[str, typing.Dict], typing.Dict[str, typing.Dict]], +]: """Reload data saved from previous LEMS simulation run. + It can also plot the traces from the data. Each "OutputFile" is plotted in + a separate plot. + + .. seealso:: + + the :py:mod:`pyneuroml.plot.PlotTimeSeries` module + Module for plotting time series + + the :py:mod:`pyneuroml.plot.simdata` module + Module for loading simulation data + :param lems_file_name: name of LEMS file that was used to generate the data :type lems_file_name: str :param base_dir: directory to run in :type base_dir: str :param t_run: time of run :type t_run: datetime - :param plot: toggle plotting + :param plot: toggle plotting of traces :type plot: bool :param show_plot_already: toggle if plots should be shown :type show_plot_already: bool :param simulator: simulator that was used to generate data :type simulator: str - :param reload_event: toggle whether events should be loaded - :type reload_event: bool - :param verbose: toggle verbose output - :type verbose: bool + :param reload_events: toggle whether events should be loaded + :type reload_events: bool + :param reload_traces: toggle whether traces should be loaded + :type reload_traces: bool :param remove_dat_files_after_load: toggle if data files should be deleted after they've been loaded :type remove_dat_files_after_load: bool + :returns: if both `get_events` and `get_traces` are selected, a tuple with + two dictionaries, one for traces, one for events, is returned: - TODO: remove unused vebose argument (needs checking to see if is being - used in other places) - """ - if not os.path.isfile(lems_file_name): - real_lems_file = os.path.realpath(os.path.join(base_dir, lems_file_name)) - else: - real_lems_file = os.path.realpath(lems_file_name) + .. code-block:: python - logger.debug( - "Reloading data specified in LEMS file: %s (%s), base_dir: %s, cwd: %s; plotting %s" - % (lems_file_name, real_lems_file, base_dir, os.getcwd(), show_plot_already) - ) + all_traces, all_events - # Could use pylems to parse all this... - traces = {} # type: dict - events = {} # type: dict - - if plot: - import matplotlib.pyplot as plt - - base_lems_file_path = os.path.dirname(os.path.realpath(lems_file_name)) - tree = etree.parse(real_lems_file) - - sim = tree.getroot().find("Simulation") - ns_prefix = "" - - possible_prefixes = ["{http://www.neuroml.org/lems/0.7.2}"] - if sim is None: - # print(tree.getroot().nsmap) - # print(tree.getroot().getchildren()) - for pre in possible_prefixes: - for comp in tree.getroot().findall(pre + "Component"): - if comp.attrib["type"] == "Simulation": - ns_prefix = pre - sim = comp - - if reload_events: - event_output_files = sim.findall(ns_prefix + "EventOutputFile") - for i, of in enumerate(event_output_files): - name = of.attrib["fileName"] - file_name = os.path.join(base_dir, name) - if not os.path.isfile(file_name): # If not relative to the LEMS file... - file_name = os.path.join(base_lems_file_path, name) - - # if not os.path.isfile(file_name): # If not relative to the LEMS file... - # file_name = os.path.join(os.getcwd(),name) - # ... try relative to cwd. - # if not os.path.isfile(file_name): # If not relative to the LEMS file... - # file_name = os.path.join(os.getcwd(),'NeuroML2','results',name) - # ... try relative to cwd in NeuroML2/results subdir. - if not os.path.isfile(file_name): # If not relative to the base dir... - raise OSError( - ("Could not find simulation output " "file %s" % file_name) - ) - format = of.attrib["format"] - logger.info( - "Loading saved events from %s (format: %s)" % (file_name, format) - ) - selections = {} - for col in of.findall(ns_prefix + "EventSelection"): - id = int(col.attrib["id"]) - select = col.attrib["select"] - events[select] = [] - selections[id] = select - - with open(file_name) as f: - for line in f: - values = line.split() - if format == "TIME_ID": - t = float(values[0]) - id = int(values[1]) - elif format == "ID_TIME": - id = int(values[0]) - t = float(values[1]) - logger.debug( - "Found a event in cell %s (%s) at t = %s" - % (id, selections[id], t) - ) - events[selections[id]].append(t) + Otherwise one dictionary for whichever was selected is returned. - if remove_dat_files_after_load: - logger.warning( - "Removing file %s after having loading its data!" % file_name - ) - os.remove(file_name) - - output_files = sim.findall(ns_prefix + "OutputFile") - n_output_files = len(output_files) - if plot: - rows = int(max(1, math.ceil(n_output_files / float(3)))) - columns = min(3, n_output_files) - fig, ax = plt.subplots( - rows, columns, sharex=True, figsize=(8 * columns, 4 * rows) - ) - if n_output_files > 1: - ax = ax.ravel() - - for i, of in enumerate(output_files): - traces["t"] = [] - name = of.attrib["fileName"] - file_name = os.path.join(base_dir, name) - - if not os.path.isfile(file_name): # If not relative to the LEMS file... - file_name = os.path.join(base_lems_file_path, name) - - if not os.path.isfile(file_name): # If not relative to the LEMS file... - file_name = os.path.join(os.getcwd(), name) - - # ... try relative to cwd. - if not os.path.isfile(file_name): # If not relative to the LEMS file... - file_name = os.path.join(os.getcwd(), "NeuroML2", "results", name) - # ... try relative to cwd in NeuroML2/results subdir. - if not os.path.isfile(file_name): # If not relative to the LEMS file... - raise OSError(("Could not find simulation output " "file %s" % file_name)) - t_file_mod = datetime.fromtimestamp(os.path.getmtime(file_name)) - if t_file_mod < t_run: - raise Exception( - "Expected output file %s has not been modified since " - "%s but the simulation was run later at %s." - % (file_name, t_file_mod, t_run) - ) + The events dictionary has the following format: - logger.debug( - "Loading saved data from %s%s" - % (file_name, " (%s)" % simulator if simulator else "") + .. code-block:: python + + { + '': { 'cell id': [] } + } + + The traces dictionary has the following format: + + .. code-block:: python + + { + 't': [], + 'col 1': [] + 'col 2': [] + } + + Each list has multiple dictionaries, one each for each output file in + the LEMS file. + + + .. seealso:: + + The :py:mod:`pyneuroml.utils.simdata` module for more utility functions + on loading simulation data. + + """ + if not reload_events and not reload_traces: + raise ValueError("At least one of reload_traces or reload_events must be True") + + all_traces: typing.Dict[str, typing.Dict] = {} + all_events: typing.Dict[str, typing.Dict] = {} + if reload_traces and not reload_events: + all_traces = pynmls.load_sim_data_from_lems_file( + lems_file_name=lems_file_name, + base_dir=base_dir, + get_events=False, + get_traces=True, + t_run=t_run, + remove_dat_files_after_load=remove_dat_files_after_load, + ) + elif reload_events and not reload_traces: + all_traces = pynmls.load_sim_data_from_lems_file( + lems_file_name=lems_file_name, + base_dir=base_dir, + get_events=True, + get_traces=False, + t_run=t_run, + remove_dat_files_after_load=remove_dat_files_after_load, + ) + else: + all_traces, all_events = pynmls.load_sim_data_from_lems_file( + lems_file_name=lems_file_name, + base_dir=base_dir, + get_events=True, + get_traces=True, + t_run=t_run, + remove_dat_files_after_load=remove_dat_files_after_load, ) - cols = [] - cols.append("t") - for col in of.findall(ns_prefix + "OutputColumn"): - quantity = col.attrib["quantity"] - traces[quantity] = [] - cols.append(quantity) - - with open(file_name) as f: - for line in f: - values = line.split() - for vi in range(len(values)): - traces[cols[vi]].append(float(values[vi])) - - if remove_dat_files_after_load: - logger.warning( - "Removing file %s after having loading its data!" % file_name - ) - os.remove(file_name) + flat_traces = {} + if all_traces: + for f, traces in all_traces.items(): + flat_traces.update(traces) if plot: - info = "Data loaded from %s%s" % ( - file_name, - " (%s)" % simulator if simulator else "", + pynmlt._plot_traces( + all_traces, show_plot_already=show_plot_already, single_plot=False ) - logger.warning("Reloading: %s" % info) - plt.get_current_fig_manager().set_window_title(info) - legend = False - for key in cols: - if n_output_files > 1: - ax_ = ax[i] - else: - ax_ = ax - ax_.set_xlabel("Time (ms)") - ax_.set_ylabel("(SI units...)") - ax_.xaxis.grid(True) - ax_.yaxis.grid(True) - - if key != "t": - ax_.plot(traces["t"], traces[key], label=key) - logger.debug("Adding trace for: %s, from: %s" % (key, file_name)) - ax_.used = True - legend = True - - if legend: - if n_output_files > 1: - ax_.legend( - loc="upper right", fancybox=True, shadow=True, ncol=4 - ) # ,bbox_to_anchor=(0.5, -0.05)) - else: - ax_.legend( - loc="upper center", - bbox_to_anchor=(0.5, -0.05), - fancybox=True, - shadow=True, - ncol=4, - ) - - # print(traces.keys()) - - if plot and show_plot_already: - if n_output_files > 1: - ax_ = ax - else: - ax_ = [ax] - for axi in ax_: - if not hasattr(axi, "used") or not axi.used: - axi.axis("off") - plt.tight_layout() - plt.show() - - if reload_events: - return traces, events - else: - return traces + flat_events = {} + if all_events: + for f, events in all_events.items(): + flat_events.update(events) + + if reload_events and reload_traces: + return flat_traces, flat_events + elif reload_traces and not reload_events: + return flat_traces + elif reload_events and not reload_traces: + return flat_events def generate_sim_scripts_in_folder( @@ -1313,95 +1218,91 @@ def generate_sim_scripts_in_folder( "Please only provide the name of the file here and use rootdir to provide the folder it lives in" ) - logger.debug("Getting list of model files") - model_file_list = [] # type: list - lems_def_dir = None - lems_def_dir = pyneuroml.utils.get_model_file_list( - lems_file_name, model_file_list, root_dir, lems_def_dir - ) - - root_dir = str(Path(root_dir).absolute()) - - logger.debug(f"Model file list is {model_file_list}") - - for model_file in model_file_list: - logger.debug(f"Copying: {root_dir}/{model_file} -> {tdir + '/' + model_file}") - # if model file has directory structures in it, recreate the dirs in - # the temporary directory - if len(model_file.split("/")) > 1: - # throw error if files in parent directories are referred to - if "../" in model_file: - raise ValueError( - """ - Cannot handle parent directories because we - cannot create these directories correctly in - the temporary location. Please re-organize - your code such that all included files are in - sub-directories of the root directory where the - main file resides. - """ - ) - - model_file_path = pathlib.Path(tdir + "/" + model_file) - parent = model_file_path.parent - parent.mkdir(parents=True, exist_ok=True) - shutil.copy(root_dir + "/" + model_file, tdir + "/" + model_file) - - if lems_def_dir is not None: - logger.info(f"Removing LEMS definitions directory {lems_def_dir}") - shutil.rmtree(lems_def_dir) - - cwd = Path.cwd() - os.chdir(tdir) - logger.info(f"Working in {tdir}") - start_time = time.time() - 1.0 - - if engine == "jneuroml_neuron": - run_lems_with( - engine, - lems_file_name=Path(lems_file_name).name, - compile_mods=False, - only_generate_scripts=True, - *engine_args, - **engine_kwargs, - ) - elif engine == "jneuroml_netpyne": - run_lems_with( - engine, - lems_file_name=Path(lems_file_name).name, - only_generate_scripts=True, - *engine_args, - **engine_kwargs, + # change to root_dir, so that we're in the directory where the lems file + # is + with chdir(root_dir): + logger.debug("Getting list of model files") + model_file_list = [] # type: list + lems_def_dir = None + lems_def_dir = pyneuroml.utils.get_model_file_list( + lems_file_name, model_file_list, root_dir, lems_def_dir ) - generated_files = pyneuroml.utils.get_files_generated_after( - start_time, ignore_suffixes=["xml", "nml"] - ) + logger.debug(f"Model file list is {model_file_list}") + + for model_file in model_file_list: + logger.debug(f"Copying: {model_file} -> {tdir}/{model_file}") + # if model file has directory structures in it, recreate the dirs in + # the temporary directory + if len(model_file.split("/")) > 1: + # throw error if files in parent directories are referred to + if "../" in model_file: + raise ValueError( + """ + Cannot handle parent directories because we + cannot create these directories correctly in + the temporary location. Please re-organize + your code such that all included files are in + sub-directories of the root directory where the + main file resides. + """ + ) - # For NetPyNE, the channels are converted to NEURON mod files, but the - # network and cells are imported from the nml files. - # So we include all the model files too. - if engine == "jneuroml_netpyne": - generated_files.extend(model_file_list) + model_file_path = pathlib.Path(tdir + "/" + model_file) + parent = model_file_path.parent + parent.mkdir(parents=True, exist_ok=True) + shutil.copy(model_file, tdir + "/" + model_file) + + if lems_def_dir is not None: + logger.info(f"Removing LEMS definitions directory {lems_def_dir}") + shutil.rmtree(lems_def_dir) + + with chdir(tdir): + logger.info(f"Working in {tdir}") + start_time = time.time() - 1.0 + + if engine == "jneuroml_neuron": + run_lems_with( + engine, + lems_file_name=Path(lems_file_name).name, + compile_mods=False, + only_generate_scripts=True, + *engine_args, + **engine_kwargs, + ) + elif engine == "jneuroml_netpyne": + run_lems_with( + engine, + lems_file_name=Path(lems_file_name).name, + only_generate_scripts=True, + *engine_args, + **engine_kwargs, + ) - logger.debug(f"Generated files are: {generated_files}") + generated_files = pyneuroml.utils.get_files_generated_after( + start_time, ignore_suffixes=["xml", "nml"] + ) - if generated_files_dir_name is None: - generated_files_dir_name = Path(tdir).name + "_generated" - logger.debug( - f"Creating directory and moving generated files to it: {generated_files_dir_name}" - ) + # For NetPyNE, the channels are converted to NEURON mod files, but the + # network and cells are imported from the nml files. + # So we include all the model files too. + if engine == "jneuroml_netpyne": + generated_files.extend(model_file_list) + + logger.debug(f"Generated files are: {generated_files}") - for f in generated_files: - fpath = pathlib.Path(f) - moved_path = generated_files_dir_name / fpath - # use os.renames because pathlib.Path.rename does not move - # recursively and so cannot move files within directories - os.renames(fpath, moved_path) + if generated_files_dir_name is None: + generated_files_dir_name = Path(tdir).name + "_generated" + logger.debug( + f"Creating directory and moving generated files to it: {generated_files_dir_name}" + ) - # return to original directory - # doesn't affect scripts much, but does affect our tests - os.chdir(str(cwd)) + for f in generated_files: + fpath = pathlib.Path(f) + moved_path = generated_files_dir_name / fpath + # use os.renames because pathlib.Path.rename does not move + # recursively and so cannot move files within directories + os.renames(fpath, moved_path) return tdir diff --git a/pyneuroml/sbml/__init__.py b/pyneuroml/sbml/__init__.py index d4dad9f5..29188efe 100644 --- a/pyneuroml/sbml/__init__.py +++ b/pyneuroml/sbml/__init__.py @@ -3,12 +3,10 @@ based on https://github.com/combine-org/combine-notebooks/blob/main/src/combine_notebooks/validation/validation_sbml.py """ -import os import errno -from typing import List - - import logging +import os +from typing import List logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) diff --git a/pyneuroml/sedml/__init__.py b/pyneuroml/sedml/__init__.py index d1061280..c351f671 100644 --- a/pyneuroml/sedml/__init__.py +++ b/pyneuroml/sedml/__init__.py @@ -3,11 +3,12 @@ based on example here https://github.com/SED-ML/libSEDML/blob/master/examples/python/echo_sedml.py """ -import os import errno -import libsedml +import os from typing import List +import libsedml + def check_file(file_name): """ diff --git a/pyneuroml/swc/ExportNML.py b/pyneuroml/swc/ExportNML.py new file mode 100644 index 00000000..3914b5f0 --- /dev/null +++ b/pyneuroml/swc/ExportNML.py @@ -0,0 +1,799 @@ +""" +Module for exporting NeuroML from SWC files. + +.. versionadded:: 1.3.9 + +Copyright 2024 NeuroML contributors +""" + +import argparse +import logging +import time +from typing import Dict, Optional, Set + +from neuroml import ( + Cell, + NeuroMLDocument, +) +from neuroml.utils import component_factory + +from pyneuroml.io import write_neuroml2_file +from pyneuroml.utils.cli import build_namespace + +from .LoadSWC import SWCGraph, SWCNode, load_swc + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + + +class NeuroMLWriter: + """ + A class to convert SWC graph data to NeuroML format. + + This class takes an SWC graph and converts it into a NeuroML representation, + handling different neuron segment types and creating appropriate segment groups. + """ + + def __init__(self, swc_graph: SWCGraph) -> None: + """ + Initialize the NeuroMLWriter with an SWC graph. + + :param swc_graph: The SWC graph to be converted to NeuroML. + :type swc_graph: SWCGraph + """ + logger.debug("Initializing NeuroMLWriter") + self.swc_graph = swc_graph + # all nodes + self.points = swc_graph.nodes + # soma nodes + self.soma_points = self.swc_graph.get_nodes_by_type(SWCNode.SOMA) + # segment group types + self.section_types = [ + "undefined", + "soma", + "axon", + "basal dendrite", + "apical dendrite", + ] + # TODO: use something better than UNKNOWN + self.morphology_origin = swc_graph.metadata.get("ORIGINAL_SOURCE", "Unknown") + # hold the cell object + self.cell: Optional[Cell] = None + # holds the NeuroML document object + self.nml_doc: Optional[NeuroMLDocument] = None + # dict, key is the index of a point, value is the corresponding segment + # id + self.point_indices_vs_seg_ids: Dict[int, int] = {} + # keeps track of the next segment id, incremented after a segment is + # processed + self.next_segment_id = 0 + # stores processed nodes + self.processed_nodes: Set[int] = set() + + # Set of points that are used to create segments during the processing + # of other points, for example, after a type change when the current + # point is used as the proximal and the next point is used as distal. + # The trees from these points do need to be parsed, but they are not + # used for creating segments again. + self.unprocessed_but_in_segment_nodes: Set[int] = set() + + # root segment id + self.root_segment_id = -1 + + logger.debug(f"NeuroMLWriter initialized with {len(self.points)} points") + + def __create_cell(self) -> Cell: + """ + Create a Cell object for the NeuroML representation. + + :return: The created Cell object. + :rtype: Cell + """ + logger.debug("Creating Cell object") + cell_name = self.__get_cell_name() + notes = f"Neuronal morphology exported from Python Based Converter. Original file: {self.morphology_origin}" + self.cell = component_factory("Cell", id=cell_name, notes=notes) + self.cell.setup_nml_cell( + default_groups=["all", "soma_group", "dendrite_group", "axon_group"] + ) + + # clear biophysical properties + self.cell.biophysical_properties = None + + logger.debug(f"Created Cell object with name: {cell_name}") + + assert self.cell + return self.cell + + def __get_cell_name(self) -> str: + """ + Generate a cell name based on the morphology origin. + + :return: The generated cell name. + :rtype: str + """ + logger.debug("Generating cell name") + cell_name = "cell1" + try: + cell_name = ( + self.morphology_origin.split("/")[-1] + .replace(".swc", "") + .replace(".", "_") + .replace("-", "_") + ) + if cell_name[0].isdigit(): + cell_name = "Cell_" + cell_name + except Exception as e: + logger.error(f"Error in generating cell name: {e}") + logger.debug(f"Generated cell name: {cell_name}") + return cell_name + + def __parse_tree( + self, + parent_point: SWCNode, + this_point: SWCNode, + ) -> None: + """ + Recursively parse the SWC tree to create NeuroML segments. + + :param parent_point: The parent point of the current point. + :type parent_point: SWCNode + :param this_point: The current point being processed. + :type this_point: SWCNode + """ + if ( + this_point.id in self.processed_nodes + and this_point.id not in self.unprocessed_but_in_segment_nodes + ): + logger.debug(f"Point {this_point.id} already processed, skipping") + return + + logger.debug(f"Parsing tree: Point {this_point.id}, Type {this_point.type}") + + # All soma points will be used for segment creation the first time a + # soma point is encountered, but they can all be roots of sub-trees so + # their trees do need to be parsed again below. + if this_point.type == SWCNode.SOMA: + self.__handle_soma(parent_point, this_point) + else: + # do not create a segment, but do parse the tree from this point + if this_point.id not in self.unprocessed_but_in_segment_nodes: + self.__create_segment(parent_point, this_point) + else: + logger.debug( + f"Point {this_point.id} processed as second point for a segment, skipping" + ) + + # mark point as processed + # only done here, not anywhere else + self.processed_nodes.add(this_point.id) + + for child_point in this_point.children: + if child_point.id not in self.processed_nodes: + self.__parse_tree(this_point, child_point) + + logger.debug(f"Processed nodes are: {self.processed_nodes}") + + def __handle_soma( + self, + parent_point: SWCNode, + this_point: SWCNode, + ) -> None: + """ + + Handle the creation of soma segments based on different soma + representation cases. This method implements the soma representation + guidelines as described in: + + "Soma format representation in NeuroMorpho.Org as of version 5.3". For + full details, see: + https://github.com/NeuroML/Cvapp-NeuroMorpho.org/blob/master/caseExamples/SomaFormat-NMOv5.3.pdf + + In summary, NeuroMorpho makes the following conversions to standardise + the SWC representation: + 1. Single contour (most common, ~80% of cases): + Converted to a three-point soma cylinder. + + 2. Soma absent (~8% of cases): + Not handled in this method (no changes made). + + 3. Multiple contours (~5% of cases): + Converted to a three-point soma cylinder, averaging all contour points. + + 4. Multiple cylinders (~4% of cases): + Kept as is, no conversion needed. + + 5. Single point (~3% of cases): + Converted to a three-point soma cylinder. + + This method handles the standardised NeuroMorpho SWC representation: + + + 1. Single point soma: a spherical segment is created + + 2. Three point soma: two segments with the "middle" point in the center + + 3. All other cases: multiple cylinders (as a cable) + + + Note that this function only marks the current point as "processed" + even if it does use other points to create the segments. This is + because even if other points are part of the soma segments, they may + still be the roots of subtrees where other segments are attached to + them. So, they still need to be parsed by :py:func:`__parse_tree` + recursively. + + :param parent_point: The parent point of the current soma point. + :type parent_point: SWCNode + :param this_point: The current soma point being processed. + :type this_point: SWCNode + """ + logger.debug(f"Handling soma point: {this_point.id}") + + assert self.cell + + if this_point.id in self.processed_nodes: + logger.debug(f"Soma point {this_point.id} already processed, skipping") + return + + if len(self.soma_points) == 1: + logger.debug("Processing single-point soma") + first_seg = self.cell.add_segment( + prox=[ + this_point.x, + this_point.y, + this_point.z, + 2 * this_point.radius, + ], + dist=[ + this_point.x, + this_point.y, + this_point.z, + 2 * this_point.radius, + ], + seg_id=self.next_segment_id, + name=f"soma_Seg_{self.next_segment_id}", + parent=None, + fraction_along=1.0, + use_convention=True, + reorder_segment_groups=False, + optimise_segment_groups=False, + seg_type="soma", + ) + self.root_segment_id = first_seg.id + self.point_indices_vs_seg_ids[this_point.id] = self.next_segment_id + self.next_segment_id += 1 + + elif len(self.soma_points) == 3: + if this_point.id == self.soma_points[0].id: + logger.debug("Processing 3-point soma: point 1") + middle_point = self.soma_points[1] + end_point = self.soma_points[2] + + first_seg = self.cell.add_segment( + prox=[ + middle_point.x, + middle_point.y, + middle_point.z, + 2 * middle_point.radius, + ], + dist=[ + this_point.x, + this_point.y, + this_point.z, + 2 * this_point.radius, + ], + seg_id=self.next_segment_id, + name=f"soma_Seg_{self.next_segment_id}", + parent=None, + fraction_along=1.0, + use_convention=True, + reorder_segment_groups=False, + optimise_segment_groups=False, + seg_type="soma", + ) + logger.debug( + f"First segment: {first_seg} ({first_seg.proximal} -> {first_seg.distal})" + ) + self.root_segment_id = first_seg.id + + self.point_indices_vs_seg_ids[this_point.id] = self.next_segment_id + self.point_indices_vs_seg_ids[middle_point.id] = self.next_segment_id + + self.next_segment_id += 1 + + second_seg = self.cell.add_segment( + prox=None, + dist=[ + end_point.x, + end_point.y, + end_point.z, + 2 * end_point.radius, + ], + seg_id=self.next_segment_id, + name=f"soma_Seg_{self.next_segment_id}", + parent=first_seg, + fraction_along=1.0, + use_convention=True, + reorder_segment_groups=False, + optimise_segment_groups=False, + seg_type="soma", + ) + logger.debug( + f"Second segment: {second_seg} ({second_seg.proximal} -> {second_seg.distal})" + ) + + self.point_indices_vs_seg_ids[end_point.id] = self.next_segment_id + + self.next_segment_id += 1 + + # ignore the other points when the method is called with them + # because they have already been used in segment creation + else: + logger.debug("Processing (ignoring) 3-point soma: point 2/3") + pass + + # all other cases + else: + logger.debug( + f"Processing multi-point soma with {len(self.soma_points)} points" + ) + + if this_point == self.soma_points[0]: + logger.debug("Processing multi-point soma") + + for i in range(len(self.soma_points) - 1): + segment = None + proximal_point = self.soma_points[i] + distal_point = self.soma_points[i + 1] + + # first point, no parent, so set a proximal + if i == 0: + first_point = proximal_point + prox = [ + first_point.x, + first_point.y, + first_point.z, + 2 * first_point.radius, + ] + + parent = None + + # record the first point + self.point_indices_vs_seg_ids[first_point.id] = ( + self.next_segment_id + ) + + # Not first point, don't set proximal at all, instead set + # the correct parent relationship + else: + prox = None + parent_id = distal_point.parent_id + parent_seg_id = self.point_indices_vs_seg_ids.get( + parent_id, None + ) + parent = self.cell.get_segment(parent_seg_id) + + distal = [ + distal_point.x, + distal_point.y, + distal_point.z, + 2 * distal_point.radius, + ] + + segment = self.cell.add_segment( + prox=prox, + dist=distal, + seg_id=self.next_segment_id, + name=f"soma_Seg_{self.next_segment_id}", + parent=parent, + fraction_along=1.0, + use_convention=True, + reorder_segment_groups=False, + optimise_segment_groups=False, + seg_type="soma", + ) + + if i == 0: + self.root_segment_id = segment.id + + self.point_indices_vs_seg_ids[distal_point.id] = ( + self.next_segment_id + ) + + self.next_segment_id += 1 + self.point_indices_vs_seg_ids[self.soma_points[-1].id] = ( + self.next_segment_id - 1 + ) + + else: + logger.debug( + f"Point {this_point} already processed as part of multi-point soma." + ) + pass + + logger.debug(f"Finished handling soma point: {this_point.id}") + + def __create_segment( + self, + parent_point: SWCNode, + this_point: SWCNode, + ) -> None: + """ + Create a NeuroML segment from an non-soma SWC point. Soma points are + handled by py:meth:`__handle_soma`. + + + Cases: + + #. somatic points are handled by py:func:`__handle_soma`. + + If there is no soma, we create the first segment as having both + proximal and distal points as the first points. + + This is to replicate CVApp behaviour (but the logic is unclear to me + at the time of writing this). + + #. if a point's parent is a soma point, but the point itself is not, we + do not create a new segment with the point as the distal point (under + the assumption that the distal of the previous point is the + proximal). Instead, in this case, the point becomes the proximal of + the new segment, and its first child becomes the distal point. + + This is because, it's quite possible for non-soma points to not be + connected to the soma, i.e., they can float at a distance. While + from a morphology perspective, this is incorrect, from a modelling + perspective, this is OK since by specifying the soma as a parent, we + continue to have the soma and the floating segment electrically + connected. + + + #. if the parent and child are of different types, but the parent is + not of a soma type, treat it like any other segment (below: 3) + + #. create new segment for all other cases with current point as distal + and the parent's distal assumed to be proximal (which does not need to + be specified) + + + :param parent_point: The parent point of the current point. + :type parent_point: SWCNode + :param this_point: The current point being processed. + :type this_point: SWCNode + """ + + # cell cannot be None at this point + assert self.cell + + # no point being processed here can be a soma + logger.debug( + f"Processing non-soma point segment: Point {this_point.id}, Type {this_point.type}, Parent {parent_point.id}" + ) + seg_id = self.next_segment_id + + # get the segment type + try: + segment_type = self.section_types[this_point.type] + except IndexError: + segment_type = f"type_{this_point.type}" + + # is first point: only possible, once if there's no soma at all, since + # this function only deals with non-soma points + is_first_point = parent_point == this_point + # is the point type changing? + is_type_change = this_point.type != parent_point.type + # is the parent a soma: special case + is_parent_soma = parent_point.type == SWCNode.SOMA + + if this_point.type >= 5: + logger.warning( + f"Point is of type: {SWCNode.TYPE_NAMES[this_point.type]}, treating as dendrite" + ) + seg_type = "dendrite" + else: + # "Apical Dendrite" -> "apical_dendrite" and so on + seg_type = SWCNode.TYPE_NAMES[this_point.type].lower().replace(" ", "_") + + # if it's in the standard groups, do not add to another group + if seg_type in ["axon", "dendrite", "soma"]: + group_id = None + else: + group_id = seg_type + + logger.debug(f"Adding segment of type {seg_type} to group: {group_id}") + + # Case 1 + # first point, but is non-soma + if is_first_point: + logger.debug(f"First point and non-soma: {this_point}") + self.cell.add_segment( + prox=[this_point.x, this_point.y, this_point.z, 2 * this_point.radius], + dist=[this_point.x, this_point.y, this_point.z, 2 * this_point.radius], + seg_id=seg_id, + name=f"{segment_type.replace(' ', '_')}_Seg_{seg_id}", + parent=None, + fraction_along=1.0, + use_convention=True, + reorder_segment_groups=False, + optimise_segment_groups=False, + seg_type="dendrite" if "dendrite" in seg_type else seg_type, + group_id=group_id, + ) + self.point_indices_vs_seg_ids[this_point.id] = seg_id + + else: + # Case 2 + # Parent is soma, but point is not + if is_parent_soma and is_type_change: + logger.debug(f"Type change and parent is soma: {this_point}") + + # there must be a second point, otherwise it should error + second_point = this_point.children[0] + + # parent segment + parent = None + if not is_first_point: + parent_seg_id = self.point_indices_vs_seg_ids.get( + parent_point.id, None + ) + + if parent_seg_id is not None: + parent = self.cell.get_segment(parent_seg_id) + else: + raise ValueError(f"Parent not found for {this_point}") + + self.cell.add_segment( + prox=[ + this_point.x, + this_point.y, + this_point.z, + 2 * this_point.radius, + ], + dist=[ + second_point.x, + second_point.y, + second_point.z, + 2 * second_point.radius, + ], + seg_id=seg_id, + name=f"{segment_type.replace(' ', '_')}_Seg_{seg_id}", + parent=parent, + fraction_along=1.0, + use_convention=True, + reorder_segment_groups=False, + optimise_segment_groups=False, + seg_type="dendrite" if "dendrite" in seg_type else seg_type, + group_id=group_id, + ) + + self.point_indices_vs_seg_ids[this_point.id] = seg_id + self.point_indices_vs_seg_ids[second_point.id] = seg_id + self.unprocessed_but_in_segment_nodes.add(second_point.id) + + # Cases 3, 4 + # All other cases ("normal" segment creation with parent as + # proximal and current point as distal) + else: + # segment parent id + parent_seg_id = self.point_indices_vs_seg_ids.get(parent_point.id, None) + + if parent_seg_id is not None: + parent = self.cell.get_segment(parent_seg_id) + else: + raise ValueError(f"Parent not found for {this_point}") + + self.cell.add_segment( + prox=None, + dist=[ + this_point.x, + this_point.y, + this_point.z, + 2 * this_point.radius, + ], + seg_id=seg_id, + name=f"{segment_type.replace(' ', '_')}_Seg_{seg_id}", + parent=parent, + fraction_along=1.0, + use_convention=True, + reorder_segment_groups=False, + optimise_segment_groups=False, + seg_type="dendrite" if "dendrite" in seg_type else seg_type, + group_id=group_id, + ) + self.point_indices_vs_seg_ids[this_point.id] = seg_id + + self.next_segment_id += 1 + + logger.debug(f"Created segment {seg_id} for point {this_point.id}") + + def generate_neuroml( + self, standalone_morphology: bool = True, unbranched_segment_groups: bool = True + ) -> NeuroMLDocument: + """Generate NeuroML representation. + + Main worker function + + :param standalone_morphology: export morphology as standalone object + (not as part of a Cell object) + :type standalone_morphology: bool + :param unbranched_segment_groups: toggle creation of unbranched segment groups + :type unbranched_segment_groups: bool + :returns: the NeuroML document + :rtype: NeuroMLDocument + """ + if self.nml_doc is not None: + return self.nml_doc + + start_time = time.time() + logger.info("Starting NeuroML generation") + if len(self.points) < 2: + ValueError("SWC has fewer than two points. Cannot convert.") + + logger.info(f"Total points: {len(self.points)}") + logger.debug(f"Total soma points: {len(self.soma_points)}") + + self.__create_cell() + assert self.cell + + start_point = self.swc_graph.root + assert start_point + + logger.debug(f"Start point: {start_point}") + + # create all the segments + self.__parse_tree(start_point, start_point) + + parse_time = time.time() + logger.info(f"Parsing SWC took {parse_time - start_time} seconds") + + if unbranched_segment_groups: + # create unbranched segment groups + if len(self.cell.morphology.segments) == 0: + logger.warning( + "No segments were created. Skipping segment group creation." + ) + return + + # if root segment id has not changed, we assume the first segment is + # the root + if self.root_segment_id == -1: + self.root_segment_id = 0 + + # Note that this adds a proximal point to the root segment of each + # unbranched segment group. If a proximal point is not specified, it + # will get one using `get_actual_proximal` and insert it into the + # segment. + self.cell.create_unbranched_segment_group_branches( + self.root_segment_id, + use_convention=True, + reorder_segment_groups=True, + optimise_segment_groups=True, + ) + + segment_group_time = time.time() + logger.info( + f"Creating unbranched segment groups took {segment_group_time - parse_time} seconds" + ) + else: + self.cell.reorder_segment_groups() + self.cell.optimise_segment_groups() + + self.nml_doc = NeuroMLDocument(id=self.cell.id) + + if standalone_morphology: + self.nml_doc.morphology.append(self.cell.morphology) + else: + self.nml_doc.cells.append(self.cell) + + end_time = time.time() + logger.debug("NeuroML generation completed") + logger.info(f"NeuroML generation took {end_time - start_time} seconds") + + return self.nml_doc + + def export_to_nml_file( + self, + filename: str, + standalone_morphology: bool = True, + unbranched_segment_groups: bool = True, + ) -> None: + """ + Export the NeuroML representation to a file. + + :param filename: The name of the file to export to. + :type filename: str + :param standalone_morphology: export morphology as standalone object + (not as part of a Cell object) + :type standalone_morphology: bool + :param unbranched_segment_groups: toggle creation of unbranched segment groups + :type unbranched_segment_groups: bool + """ + self.generate_neuroml(standalone_morphology) + assert self.nml_doc + assert self.cell + + write_neuroml2_file(self.nml_doc, filename, validate=True) + logger.info(f"NeuroML file exported to: {filename}") + + +def convert_swc_to_neuroml( + swc_file: str, + neuroml_file: Optional[str] = None, + standalone_morphology: bool = True, + unbranched_segment_groups: bool = True, +) -> NeuroMLDocument: + """Convert an SWC file to NeuroML. + + If `neuroml_file` is provided, will also write to file. + + :param swc_file: SWC input file + :type swc_file: str + :param neuroml_file: output NeuroML file (optional) + :type neuroml_file: str + :param standalone_morphology: export morphology as standalone object + (not as part of a Cell object) + :type standalone_morphology: bool + + :returns: NeuroML document + :rtype: NeuroMLDocument + """ + swc_graph = load_swc(swc_file) + writer = NeuroMLWriter(swc_graph) + if neuroml_file is not None: + writer.export_to_nml_file( + neuroml_file, standalone_morphology, unbranched_segment_groups + ) + return writer.generate_neuroml(standalone_morphology, unbranched_segment_groups) + + +def main(args=None): + "Main CLI runner method" + if args is None: + args = process_args() + + a = build_namespace(DEFAULTS={}, a=args) + logger.debug(a) + + if args.neuroml_file is None: + neuroml_file = args.swc_file.replace(".swc", ".cell.nml") + else: + neuroml_file = a.neuroml_file + + convert_swc_to_neuroml( + swc_file=a.swc_file, + neuroml_file=neuroml_file, + standalone_morphology=a.morph_only, + ) + + +def process_args(): + """ + Parse command-line arguments. + """ + parser = argparse.ArgumentParser( + description=("Convert provided SWC file to NeuroML2") + ) + + parser.add_argument( + "swcFile", + type=str, + metavar="", + help="Name of the input SWC file", + ) + + parser.add_argument( + "-neuromlFile", + type=str, + metavar="", + help="Name of the output NeuroML file", + required=False, + ) + + parser.add_argument( + "-morphOnly", + action="store_true", + help="Export as standalone Morphology, not as a Cell", + default=False, + ) + + return parser.parse_args() diff --git a/pyneuroml/swc/LoadSWC.py b/pyneuroml/swc/LoadSWC.py index 8f3df789..9ca608a3 100644 --- a/pyneuroml/swc/LoadSWC.py +++ b/pyneuroml/swc/LoadSWC.py @@ -1,15 +1,15 @@ """ Module for loading SWC files -.. versionadded:: 1.3.4 +.. versionadded:: 1.3.9 +Copyright 2024 NeuroML contributors """ import logging import re import typing -logging.basicConfig(level=logging.WARNING) logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -130,7 +130,6 @@ def add_node(self, node: SWCNode): :raises ValueError: If a node with the same ID already exists in the graph or if multiple root nodes are detected """ if any(existing_node.id == node.id for existing_node in self.nodes): - logger.error(f"Duplicate node ID: {node.id}") raise ValueError(f"Duplicate node ID: {node.id}") if node.parent_id == -1: @@ -295,10 +294,14 @@ def export_to_swc_file(self, filename: str) -> None: ) -def parse_header(line: str) -> typing.Optional[typing.Tuple[str, str]]: +def parse_header( + line_number: int, line: str +) -> typing.Optional[typing.Tuple[str, str]]: """ Parse a header line from an SWC file. + :param line_number: line number, for logging purposes + :type line_number: int :param line: A single line from the SWC file header :type line: str :return: A tuple containing the matched header field name and corresponding value (or None if no match) @@ -310,8 +313,10 @@ def parse_header(line: str) -> typing.Optional[typing.Tuple[str, str]]: match = re.match(rf"{field}\s+(.+)", line, re.IGNORECASE) if match: return field, match.group(1).strip() - else: - logger.warn(f"Line beginning with '#' does not match header format: {line}") + + logger.warning( + f"Ignoring line {line_number}: does not match header format: # {line}" + ) return None @@ -329,12 +334,16 @@ def load_swc(filename: str) -> SWCGraph: tree = SWCGraph() with open(filename, "r") as file: + point_line_count = 0 for line_number, line in enumerate(file, 1): line = line.strip() + logger.debug(f"Processing line {line_number}: '{line}'") + if not line: continue + if line.startswith("#"): - header = parse_header(line[1:].strip()) + header = parse_header(line_number, line[1:].strip()) if header: tree.add_metadata(header[0], header[1]) continue @@ -348,7 +357,21 @@ def load_swc(filename: str) -> SWCGraph: # the add_node bit throws errors if things don't work out as # expected node_id, type_id, x, y, z, radius, parent_id = parts + + if point_line_count == 0: + if parent_id != "-1": + raise ValueError( + f"First point in file must have parent '-1' (root). Got: {line}" + ) + node = SWCNode(node_id, type_id, x, y, z, radius, parent_id) tree.add_node(node) + point_line_count += 1 + + # add file name as new metadata if not included + if "ORIGINAL_SOURCE" not in tree.metadata.keys(): + tree.metadata["ORIGINAL_SOURCE"] = filename + + logger.info(f"Processed {point_line_count} SWC points in {line_number} lines") return tree diff --git a/pyneuroml/tune/NeuroMLController.py b/pyneuroml/tune/NeuroMLController.py index 19c60c8a..c94c2532 100644 --- a/pyneuroml/tune/NeuroMLController.py +++ b/pyneuroml/tune/NeuroMLController.py @@ -5,21 +5,20 @@ more information on controllers in Neurotune. """ -import os.path +import logging import os +import os.path +import pprint +import shutil import sys import time -import shutil -import logging -import pprint - +from collections import OrderedDict from io import StringIO -from collections import OrderedDict -import pyneuroml.pynml -from pyneuroml import print_v import neuroml +import pyneuroml.pynml +from pyneuroml import print_v logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) diff --git a/pyneuroml/tune/NeuroMLSimulation.py b/pyneuroml/tune/NeuroMLSimulation.py index c99f7184..27adfdff 100644 --- a/pyneuroml/tune/NeuroMLSimulation.py +++ b/pyneuroml/tune/NeuroMLSimulation.py @@ -1,11 +1,10 @@ +import logging import sys import time -import logging -from pyneuroml import pynml, print_v +from pyneuroml import print_v, pynml from pyneuroml.lems import generate_lems_file_for_neuroml - logger = logging.getLogger(__name__) diff --git a/pyneuroml/utils/__init__.py b/pyneuroml/utils/__init__.py index 56de6228..452eeea6 100644 --- a/pyneuroml/utils/__init__.py +++ b/pyneuroml/utils/__init__.py @@ -35,12 +35,6 @@ logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) -try: - import libsedml -except ModuleNotFoundError: - logger.warning("Please install optional dependencies to use SED-ML features:") - logger.warning("pip install pyneuroml[combine]") - MAX_COLOUR = (255, 0, 0) # type: typing.Tuple[int, int, int] MIN_COLOUR = (255, 255, 0) # type: typing.Tuple[int, int, int] @@ -72,6 +66,19 @@ def extract_position_info( - pop_id_vs_color: dict(pop id, colour property) - pop_id_vs_radii: dict(pop id, radius property) + A few notes about this utility function: + + - it expects cells to be "flattened" and complete, i.e., they should + contain their own morphologies and not refer to other "standalone" + morphology elements. You can use the + :py:func:`neuroml.utils.fix_external_morphs_biophys_in_cell` function in + the libNeuroML package to flatten cell models. + + - if the NeuroMLDocument contains cells, it will only process those and + ignore any standalone Morphology elements. Only if the document has no + cells will it attempt to process morphologies by placing them in dummy + cells and networks. + :param nml_model: NeuroML2 model to extract position information from :type nml_model: NeuroMLDocument :param verbose: toggle function verbosity @@ -90,15 +97,25 @@ def extract_position_info( cell_elements = [] popElements = [] - cell_elements.extend(nml_model.cells) - cell_elements.extend(nml_model.cell2_ca_poolses) - - # handle morphology elements by adding them into dummy cells - ctr = 1 - morph_elements.extend(nml_model.morphology) - for m in morph_elements: - cell_elements.append(neuroml.Cell(id=f"Dummy cell {ctr}", morphology=m)) - ctr += 1 + members = nml_model.info(show_contents=True, return_format="dict") + + for member, mdict in members.items(): + if "cell" in mdict["type"].lower(): + try: + cell_elements.extend(mdict["members"]) + except TypeError: + pass + # cell_elements.extend(nml_model.cell2_ca_poolses) + + # if there are no cells, look at morphologies + if len(cell_elements) == 0: + logger.info("No cells found, looking for morphologies.") + # handle morphology elements by adding them into dummy cells + ctr = 1 + morph_elements.extend(nml_model.morphology) + for m in morph_elements: + cell_elements.append(neuroml.Cell(id=f"Dummy cell {ctr}", morphology=m)) + ctr += 1 # if the model does not include a network, plot all the cells in the # model in new dummy populations @@ -648,74 +665,115 @@ def get_model_file_list( :returns: value of lems_def_dir so that the temporary directory can be cleaned up. strings are immuatable in Python so the variable cannot be modified in the function. - :raises ValueError: if a file that does not have ".xml" or ".nml" as extension is encountered + :raises ValueError: if a file that does not have a valid extension is + encountered (xml/nml/sedml) """ - logger.debug(f"Processing {rootfile}") + rootdirpath = pathlib.Path(rootdir) + rootfilepath = pathlib.Path(rootfile) - fullrootdir = pathlib.Path(rootdir).absolute() + # convert rootdir path to relative + if rootdirpath.is_absolute(): + rootdirpath_rel = rootdirpath.relative_to(pathlib.Path.cwd()) + else: + rootdirpath_rel = rootdirpath - # Only store path of file relative to the rootdir, if it's a descendent of - # rootdir - if rootfile.startswith(str(fullrootdir)): - relrootfile = rootfile.replace(str(fullrootdir), "") - if relrootfile.startswith("/"): - relrootfile = relrootfile[1:] + rootdirpath_abs = rootdirpath.absolute() + + # convert rootfile path to relative, relative to rootdir path + if rootfilepath.is_absolute(): + rootfilepath_rel = rootfilepath.relative_to(rootdirpath_abs) else: - relrootfile = rootfile + rootfilepath_rel = rootfilepath.relative_to(pathlib.Path("./")) + + # limit the rootfile to the name of the file only, move other bits to the + # rootdir path so that they can be correctly passed on to other recursively + # included files + if len(rootfilepath_rel.parts) > 1: + rootdirpath_rel = rootdirpath_rel / rootfilepath_rel.parent + + rootfile_name = pathlib.Path(rootfilepath.name) - if relrootfile in filelist: - logger.debug(f"Already processed {rootfile}. No op.") - return lems_def_dir + logger.debug(f"Processing {rootfile_name} in {rootdirpath_rel}") - logger.debug(f"Appending: {relrootfile}") - filelist.append(relrootfile) + fullrootfile_rel = str(rootdirpath_rel / rootfile_name) - if rootfile.endswith(".nml"): - if pathlib.Path(rootfile).is_absolute(): - rootdoc = read_neuroml2_file(rootfile) + if str(rootdirpath_rel) == ".": + if str(rootfile_name) in filelist: + logger.debug("Already processed. No op.") + return lems_def_dir + else: + logger.debug(f"Appending: {rootfile_name}") + filelist.append(str(rootfile_name)) + else: + if str(fullrootfile_rel) in filelist: + logger.debug("Already processed. No op.") + return lems_def_dir else: - rootdoc = read_neuroml2_file(rootdir + "/" + rootfile) + logger.debug(f"Appending: {fullrootfile_rel}") + filelist.append(str(fullrootfile_rel)) + + if str(rootfile_name).endswith(".nml"): + logger.info(f"Processing NML file: {fullrootfile_rel}") + rootdoc = read_neuroml2_file(fullrootfile_rel) logger.debug(f"Has includes: {rootdoc.includes}") + for inc in rootdoc.includes: + logger.debug(f"NML: Processing includes: {inc.href} in {str(rootdirpath)}") lems_def_dir = get_model_file_list( - inc.href, filelist, rootdir, lems_def_dir + inc.href, filelist, str(rootdirpath_rel), lems_def_dir ) - elif rootfile.endswith(".xml"): + elif str(rootfile_name).endswith(".xml"): + logger.info(f"Processing LEMS file: {fullrootfile_rel}") # extract the standard NeuroML2 LEMS definitions into a directory # so that the LEMS parser can find them if lems_def_dir is None: lems_def_dir = extract_lems_definition_files() - if pathlib.Path(rootfile).is_absolute(): - fullrootfilepath = rootfile - else: - fullrootfilepath = rootdir + "/" + rootfile - - model = Model(include_includes=True, fail_on_missing_includes=True) + model = Model(include_includes=True, fail_on_missing_includes=False) model.add_include_directory(lems_def_dir) - model.import_from_file(fullrootfilepath) + model.import_from_file(fullrootfile_rel) for inc in model.included_files: - incfile = pathlib.Path(inc).name - logger.debug(f"Processing include file {incfile} ({inc})") + # `inc` includes the complete path relative to the current + # directory, which may repeat information such as the "rootdirpath" + # that we're tracking outselves. So, we need to do some massaging + # here to get the path to inc relative to the rootdirpath_rel + # again + incfile_path = pathlib.Path(inc) + incfile = incfile_path.name + + if incfile_path.is_relative_to(rootdirpath_rel): + incfile_path_rel = incfile_path.relative_to(rootdirpath_rel) + else: + incfile_path_rel = incfile_path + + logger.debug(f"LEMS: Processing include file {incfile} ({inc})") if incfile in STANDARD_LEMS_FILES: logger.debug(f"Ignoring NeuroML2 standard LEMS file: {inc}") continue - lems_def_dir = get_model_file_list(inc, filelist, rootdir, lems_def_dir) + lems_def_dir = get_model_file_list( + str(incfile_path_rel), filelist, str(rootdirpath_rel), lems_def_dir + ) - elif rootfile.endswith(".sedml"): - if pathlib.Path(rootfile).is_absolute(): - rootdoc = libsedml.readSedMLFromFile(rootfile) - else: - rootdoc = libsedml.readSedMLFromFile(rootdir + "/" + rootfile) + elif str(rootfile_name).endswith(".sedml"): + try: + import libsedml + except ModuleNotFoundError: + logger.error("Please install optional dependencies to use SED-ML features:") + logger.error("pip install pyneuroml[combine]") + + logger.info(f"Processing SED-ML file: {fullrootfile_rel}") + rootdoc = libsedml.readSedMLFromFile(fullrootfile_rel) # there should only be one model assert rootdoc.getNumModels() == 1 model = rootdoc.getModel(0) - lems_file = model.getSource() - logger.debug(f"Got {lems_file} from SED-ML file {rootdoc}") - lems_def_dir = get_model_file_list(lems_file, filelist, rootdir, lems_def_dir) + sedml_file = model.getSource() + logger.debug(f"Got {sedml_file} from SED-ML file {rootdoc}") + lems_def_dir = get_model_file_list( + sedml_file, filelist, str(rootdirpath_rel), lems_def_dir + ) else: raise ValueError( diff --git a/pyneuroml/utils/cli.py b/pyneuroml/utils/cli.py index d853e9c7..88b64224 100644 --- a/pyneuroml/utils/cli.py +++ b/pyneuroml/utils/cli.py @@ -7,8 +7,8 @@ Copyright 2023 NeuroML contributors """ - import argparse + from . import convert_case diff --git a/pyneuroml/utils/components.py b/pyneuroml/utils/components.py new file mode 100644 index 00000000..64c73831 --- /dev/null +++ b/pyneuroml/utils/components.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +""" +Utilities for creation and inclusion of new Components in models. + +File: pyneuroml/utils/components.py + +Copyright 2024 NeuroML contributors +""" + +import logging +from typing import Optional + +from lems.model.component import Component +from lems.model.model import Model + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + + +def add_new_component( + component_id: str, + component_type: str, + component_filename: Optional[str] = None, + **kwargs, +) -> Component: + """Add a new component to a NeuroMLDocument. + + This will create a new component with the provided id, type, and keyword + arguments and export it to a separate XML file and add that file as an + includes to the provided NeuroMLDocument object. + + This is the suggested way of including new Components of new ComponentTypes + because it keeps them separate from the main model that is composed of + Components from the NeuroML schema---which can be validated. New + ComponentTypes and their Components can be used to extend NeuroML, but + since they are not yet included in the NeuroML standard, they cannot be + validated against the schema. + + .. versionadded:: 1.3.13 + + Example usage: + + .. code:: python + + # file name to save new component as + component_filename = "gaussian_input.xml" + add_new_component(component_id="gaussian_input", + component_type="noisyCurrentSource", + component_filename=component_filename, + mean="0.1nA", std="0.01nA", delay="500ms", + duration="1000ms") + # the component type + lems_includes.append("NoisyCurrentSource.xml") + # the component + lems_includes.append(component_filename) + + + the `lems_includes` list can be used when creating the LEMS Simulation + object. In this way, the whole simulation can be validated by LEMS (jLEMS), + and the NeuroML parts can be validated against the schema. + + :param component_id: id of new Component + :type component_id: str + :param component_type: name of ComponentType that this Component is an + instance of. This must be a valid ComponentType that has been included + in the model. This function will not check this. + :type component_type: str + :param component_filename: optional file name to store the XML export of + the component in + :type component_filename: str + :param **kwargs: parameters to pass to the Component + :returns: the Component Object, and the name of the XML file it was serialised in + :rtype: tuple(Component, str) + """ + newmodel = Model() + newcomp = Component(id_=component_id, type_=component_type, **kwargs) + newmodel.add_component(newcomp) + + if component_filename is None: + component_filename = f"component_{component_id}.xml" + + logger.info( + f"Saving component with id '{component_id}' and type '{component_type}' to {component_filename}" + ) + newmodel.export_to_file(component_filename) + + logger.info( + "Component file included in NeuroML document. Note that new components will not validate against the NeuroML schema." + ) + logger.info( + f"Please also remember to include {component_filename} in the LEMS simulation file" + ) + + return newcomp, component_filename diff --git a/pyneuroml/utils/info.py b/pyneuroml/utils/info.py index 927f1d7a..0619735a 100644 --- a/pyneuroml/utils/info.py +++ b/pyneuroml/utils/info.py @@ -12,8 +12,10 @@ import sys import textwrap import typing +from io import StringIO from neuroml import Cell, NeuroMLDocument + from pyneuroml.io import read_neuroml2_file from pyneuroml.utils.units import convert_to_units, get_value_in_si @@ -91,31 +93,78 @@ def summary( if nml2_doc is None: nml2_file_name = sys.argv[1] - nml2_doc = read_neuroml2_file(nml2_file_name, include_includes=verbose, fix_external_morphs_biophys=True) - - info = nml2_doc.summary(show_includes=False) - - if verbose: - cell_info_str = "" - for cell in nml2_doc.cells: - cell_info_str += cell_info(cell) + "*\n" - lines = info.split("\n") - info = "" - still_to_add = False - for line in lines: - if "Cell: " in line: - still_to_add = True - pass - elif "Network: " in line: - still_to_add = False - if len(cell_info_str) > 0: - info += "%s" % cell_info_str - info += "%s\n" % line - else: - if still_to_add and "******" in line: + nml2_doc = read_neuroml2_file( + nml2_file_name, include_includes=verbose, fix_external_morphs_biophys=True + ) + + info = "" + # network, show full + if len(nml2_doc.networks) > 0: + info = nml2_doc.summary(show_includes=False) + if verbose: + cell_info_str = "" + for cell in nml2_doc.cells: + cell_info_str += cell_info(cell) + "*\n" + lines = info.split("\n") + info = "" + still_to_add = False + for line in lines: + if "Cell: " in line: + still_to_add = True + pass + elif "Network: " in line: + still_to_add = False if len(cell_info_str) > 0: info += "%s" % cell_info_str - info += "%s\n" % line + info += "%s\n" % line + else: + if still_to_add and "******" in line: + if len(cell_info_str) > 0: + info += "%s" % cell_info_str + info += "%s\n" % line + else: + # not a full network + # cell file + if len(nml2_doc.cells) > 0: + for cell in nml2_doc.cells: + if verbose: + info += cell_info(cell) + "*\n" + else: + cell_info_buffer = StringIO() + cell.summary(string_buffer=cell_info_buffer) + info += cell_info_buffer.getvalue() + # other things, just use info + else: + nml2_doc_info = nml2_doc.info(show_contents=True, return_format="dict") + + doc_id = nml2_doc_info.pop("id", None) + try: + info += f"** Summary: id: {doc_id['members']} **\n\n" + except (KeyError, AttributeError): + info += f"** Summary: id: {nml2_file_name} **\n\n" + + notes = nml2_doc_info.pop("notes", None) + if notes: + try: + info += f"{notes['members']}\n\n" + except KeyError: + pass + + for attr, membs in nml2_doc_info.items(): + num_members = len(membs["members"]) + ctr = 0 + for amemb in membs["members"]: + amemb_info = "" + ctr += 1 + if isinstance(amemb, str): + amemb_info += amemb + else: + amemb_info += amemb.info( + show_contents="set", return_format="string" + ) + if len(amemb_info) > 0: + info += f"*** {attr} ({ctr}/{num_members}) ***\n\n{amemb_info}\n*** {attr} ({ctr}/{num_members}) ***\n\n" + print(info) diff --git a/pyneuroml/utils/jnmlwrapper.py b/pyneuroml/utils/jnmlwrapper.py new file mode 100644 index 00000000..aa013a06 --- /dev/null +++ b/pyneuroml/utils/jnmlwrapper.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +""" +Simple wrapper around jNeuroML to allow users to use jnml using the version +bundled in PyNeuroML + +File: pyneuroml/utils/jnmlwrapper.py + +Copyright 2025 NeuroML contributors +Author: Ankur Sinha +""" + +import logging +import os +import sys + +from ..runners import run_jneuroml + + +def __jnmlwrapper(): + """Wrapper around jNeuroML jar shipped with PyNeuroML. + + The following environment variables can be set: + + - JNML_MAX_MEMORY_LOCAL: set the maximum memory available to the Java + Virtual Machine (default: 400M) + + """ + max_memory = os.getenv("JNML_MAX_MEMORY_LOCAL", "400M") + logging.getLogger("pyneuroml.runners").setLevel(logging.CRITICAL) + + retstat, output = run_jneuroml( + pre_args=" ".join(sys.argv[1:]), + target_file="", + post_args="", + max_memory=max_memory, + report_jnml_output=False, + output_prefix="", + return_string=True, + exit_on_fail=False, + ) + + # if command ran successfully, print the output + # if it didn't, `run_jneuroml` will throw a critical error + if retstat is True: + print(output) + sys.exit(0) + else: + sys.exit(1) diff --git a/pyneuroml/utils/misc.py b/pyneuroml/utils/misc.py index 98d22bb3..2afd481c 100644 --- a/pyneuroml/utils/misc.py +++ b/pyneuroml/utils/misc.py @@ -7,7 +7,6 @@ Copyright 2024 NeuroML contributors """ - import os from pyneuroml import JNEUROML_VERSION @@ -25,3 +24,23 @@ def get_path_to_jnml_jar() -> str: "jNeuroML-%s-jar-with-dependencies.jar" % JNEUROML_VERSION, ) return jar_path + + +try: + from contextlib import chdir # Python 3.11+ +except ImportError: + from contextlib import contextmanager + + @contextmanager + def chdir(path): + """chdir context manager for python < 3.11 + + :param path: path to change to + :type path: str or os.PathLike + """ + prev_cwd = os.getcwd() + os.chdir(path) + try: + yield + finally: + os.chdir(prev_cwd) diff --git a/pyneuroml/utils/nml2py.py b/pyneuroml/utils/nml2py.py new file mode 100644 index 00000000..32de1e45 --- /dev/null +++ b/pyneuroml/utils/nml2py.py @@ -0,0 +1,539 @@ +"""NeuroML XML to Python code generator. + +This module provides the ``NmlPythonizer`` class, which loads a NeuroML XML file +and generates a Python script that recreates the model using the libNeuroML API +(component_factory, add, etc.). + +Cells, channels, and synapses that are expanded inline in the source XML are +extracted into separate files following NeuroML file naming conventions +({id}.cell.nml, {id}.channel.nml, {id}.synapse.nml). Components that were +already in separate included files are preserved as includes. + +Copyright 2026 NeuroML contributors +""" + +from __future__ import annotations + +import argparse +import logging +import re +from pathlib import Path +from typing import Any + +import neuroml +from neuroml.utils import component_factory + +import pyneuroml.utils.cli as pynmluc +from pyneuroml.io import read_neuroml2_file, write_neuroml2_file + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + + +# --------------------------------------------------------------------------- +# Type classification helper +# --------------------------------------------------------------------------- + + +def _is_scalar_type(type_name: str) -> bool: + """Return True if the type is a scalar attribute, not a child component. + + Mirrors libNeuroML's approach in ``get_class_hierarchy``: if the type name + cannot be resolved to a class in the ``neuroml`` module, it is a simple + (scalar) type like ``NmlId``, ``Float``, ``xs:string``, etc. + """ + return getattr(neuroml, type_name, None) is None + + +def _is_extractable(type_name: str) -> bool: + """Return True if the component type should be extracted to a separate file. + + Covers cells, channels, and synapses. + """ + return "Cell" in type_name or "Channel" in type_name or "Synapse" in type_name + + +def _get_file_suffix(type_name: str) -> str | None: + """Derive the NeuroML file suffix from a component type name. + + Follows conventions: {id}.cell.nml, {id}.channel.nml, {id}.synapse.nml + """ + if "Cell" in type_name: + return "cell.nml" + if "Channel" in type_name: + return "channel.nml" + if "Synapse" in type_name: + return "synapse.nml" + return None + + +def _sanitize_var_name(name: str | int) -> str: + """Convert a NeuroML id to a valid Python variable name.""" + name = str(name) + # replace anything that's not a letter/digit/underscore + name = re.sub(r"[^a-zA-Z0-9_]", "_", name) + if name and name[0].isdigit(): + name = "_" + name + if not name: + name = "_unnamed" + return name + + +# --------------------------------------------------------------------------- +# Component ordering -- human-logical model construction order +# --------------------------------------------------------------------------- + + +def _order_key(type_name: str) -> int: + """Return an ordering key for a component type. + + Follows human-logical model construction order rather than schema + dependency order: network -> populations -> cells -> channels -> + synapses -> projections -> connections -> inputs -> metadata. + """ + if type_name == "IncludeType": + return 0 + if type_name == "Network": + return 1 + if type_name == "Population": + return 2 + if "Channel" in type_name: + return 3 + if "Cell" in type_name: + return 4 + if "Synapse" in type_name: + return 5 + if "Projection" in type_name: + return 6 + if type_name in ("Connection", "ConnectionW"): + return 7 + if type_name in ("InputList", "InputW", "ExplicitInput"): + return 8 + # PulseGenerator, SineGenerator, Property, Annotation, Layout, etc. + return 9 + + +# --------------------------------------------------------------------------- +# NmlPythonizer +# --------------------------------------------------------------------------- + + +class NmlPythonizer: + """Load a NeuroML XML file and generate Python code to recreate it. + + Cells, channels, and synapses that are expanded inline in the source XML + are extracted into separate files. Components from included files are + preserved as includes. + + :param nml_file: Path to the NeuroML XML file. + For safety, this should be in the same directory that the script is + being called from. + :param output_dir: Directory for output files. Must be a single level + directory. Only the last directory will be used if multi-level + directory is provided. Any suffixes will be stripped. It will be + created in the folder where the main `nml_file` resides. If omitted, a + directory called "output_nml2py" will be created. + """ + + def __init__(self, nml_file: str, output_dir: str | None = None) -> None: + self.nml_file = nml_file + self.nml_file_path = Path(nml_file) + self.output_dir_name = ( + Path(output_dir).stem if output_dir else Path("output_nml2py") + ) + self.output_dir = self.nml_file_path.parent / self.output_dir_name + logger.info(f"{self.output_dir = }") + + # object identity -> variable_name mapping (for components without ids) + self._obj_to_var: dict[int, str] = {} + # Collected components: (obj, parent_var_name) + self._components: list[tuple[Any, str | None]] = [] + # Variable name counter for duplicates + self._var_counters: dict[str, int] = {} + + # Original include hrefs to preserve + self._original_includes: list[str] = [] + # Extracted components that need to be written to separate files + self._extracted: list[tuple[Any, str]] = [] # (obj, filename) + + # ------------------------------------------------------------------ + # Public API + # ------------------------------------------------------------------ + + def write(self) -> list[str]: + """Generate and write all output files. + + Returns list of written file paths. + """ + if self.nml_file_path.parent.absolute() != Path.cwd().absolute(): + logger.error("Please run the script in the directory of the NeuroML file.") + return [] + + # Load raw doc (no includes) --- this is what we walk for code generation + self.raw_doc = read_neuroml2_file(self.nml_file, include_includes=False) + + self.output_dir.mkdir(parents=True, exist_ok=True) + + # list of written files + written: list[str] = [] + + # Collect components from raw doc and identify extractions + self._collect_components() + + # Write extracted component files + for comp, filename in self._extracted: + filepath = self.output_dir / filename + self._write_component_file(comp, filepath) + written.append(str(filepath)) + + # Generate and write Python script + code = self.generate() + script_path = self.output_dir / self._script_filename() + + logger.info(f"Writing {script_path}") + script_path.write_text(code) + written.append(str(script_path)) + + return written + + def generate(self) -> str: + """Generate and return the Python script as a string.""" + lines: list[str] = [] + lines.extend(self._gen_header()) + lines.extend(self._gen_includes()) + lines.extend(self._gen_body()) + lines.extend(self._gen_footer()) + return "\n".join(lines) + "\n" + + # ------------------------------------------------------------------ + # Collection phase + # ------------------------------------------------------------------ + + def _collect_components(self) -> None: + """Recursively collect all components from the raw document.""" + # First, collect include hrefs from the raw doc + for inc in self.raw_doc.includes: + self._original_includes.append(inc.href) + + # Walk the raw doc's children + # "nml_doc" is a special identifier for the top level root + # NeuroMLDocument + self._walk_children(self.raw_doc, parent_var="nml_doc") + + def _walk_children(self, obj: Any, parent_var: str) -> None: + """Walk the children of a component, collecting them.""" + info_dict = obj.info(show_contents=True, return_format="dict") + + for member_name, member_info in info_dict.items(): + contents = member_info.get("members") + if contents is None: + continue + if isinstance(contents, list) and len(contents) == 0: + continue + + child_type = member_info.get("type", "") + + if not _is_scalar_type(child_type): + if not isinstance(contents, list): + contents = [contents] + + for child in contents: + if hasattr(child, "info"): + child_var = self._collect_one(child, parent_var) + if child_var is not None: + self._walk_children(child, child_var) + + def _collect_one(self, obj: Any, parent_var: str) -> str | None: + """Collect a single component, assigning a variable name. + + Returns the variable name assigned, or None if the component was skipped. + """ + type_name = type(obj).__name__ + + # Skip IncludeType --- handled separately + if type_name == "IncludeType": + return None + + # Extractable types (cells, channels, synapses) at root level + if parent_var == "nml_doc" and _is_extractable(type_name): + obj_id = getattr(obj, "id", None) + if obj_id is not None: + suffix = _get_file_suffix(type_name) + if suffix: + filename = f"{obj_id}.{suffix}" + self._extracted.append((obj, filename)) + # Skip from Python code generation + return None + + # Assign variable name + var_name = self._make_var_name(obj, type_name) + + # Track all components by object identity + self._obj_to_var[id(obj)] = var_name + + self._components.append((obj, parent_var)) + return var_name + + def _make_var_name(self, obj: Any, type_name: str) -> str: + """Create a unique Python variable name for a component.""" + if hasattr(obj, "id") and obj.id is not None: + base = _sanitize_var_name(obj.id) + else: + base = type_name.lower() + + if base not in self._var_counters: + self._var_counters[base] = 0 + return base + + self._var_counters[base] += 1 + return f"{base}_{self._var_counters[base]}" + + # ------------------------------------------------------------------ + # Component file extraction + # ------------------------------------------------------------------ + + def _write_component_file(self, comp: Any, filepath: Path) -> None: + """Write a single component to a minimal NeuroML file.""" + comp_id = getattr(comp, "id", "unnamed") + doc = component_factory("NeuroMLDocument", id=f"{comp_id}_doc") + doc.add(comp, validate=False) + logger.info(f"Writing {filepath}") + + # individual files may not be valid due to missing includes + write_neuroml2_file(doc, str(filepath), validate=False) + + # ------------------------------------------------------------------ + # Code generation + # ------------------------------------------------------------------ + + def _gen_header(self) -> list[str]: + """Generate the script header with imports and root document.""" + lines = [ + "#!/usr/bin/env python3", + f'"""Auto-generated from {self.nml_file} by NmlPythonizer."""', + "", + "from neuroml import NeuroMLDocument", + "from neuroml.utils import component_factory", + "from pyneuroml.io import write_neuroml2_file", + "", + ] + + doc_id = getattr(self.raw_doc, "id", None) or "nml_doc" + lines.append(f'nml_doc = component_factory("NeuroMLDocument", id={doc_id!r})') + + # Include root doc attributes (notes, etc.) + root_kwargs = self._build_kwargs(self.raw_doc) + # Filter out 'id' since we're using doc_id + root_kwargs = [(k, v) for k, v in root_kwargs if k != "id"] + if root_kwargs: + kw_str = self._format_kwargs(root_kwargs) + # Replace the simple line with one that includes kwargs + lines[-1] = ( + f'nml_doc = component_factory("NeuroMLDocument", id={doc_id!r}, {kw_str}, validate=False)' + ) + + lines.append("") + return lines + + def _gen_includes(self) -> list[str]: + """Generate include statements.""" + if not self._original_includes and not self._extracted: + return [] + + lines = ["# --- Includes ---"] + + # Original includes (preserved as-is) + for href in self._original_includes: + # we do not move original includes, so we must tweak the path to + # refer to the parent directory + lines.append(f'nml_doc.add("IncludeType", href={href!r})') + + # Extracted inline components + for comp, filename in self._extracted: + lines.append(f'nml_doc.add("IncludeType", href={filename!r})') + + lines.append("") + return lines + + def _gen_body(self) -> list[str]: + """Generate component creation code, ordered by dependency.""" + sorted_components = sorted( + self._components, + key=lambda item: _order_key(type(item[0]).__name__), + ) + + lines: list[str] = [] + current_section = None + + for comp, parent_var in sorted_components: + type_name = type(comp).__name__ + section = _get_section_name(type_name) + + if section != current_section: + if lines: + lines.append("") + lines.append(f"# --- {section} ---") + current_section = section + + lines.extend(self._gen_component(comp, parent_var)) + + return lines + + def _gen_component(self, obj: Any, parent_var: str | None) -> list[str]: + """Generate the add() call for a single component.""" + type_name = type(obj).__name__ + var_name = self._obj_to_var.get(id(obj), _sanitize_var_name(type_name.lower())) + + if parent_var is None: + parent_var = "nml_doc" + + kwargs = self._build_kwargs(obj) + + kw_str = self._format_kwargs(kwargs) + call = f"{var_name} = {parent_var}.add({type_name!r}, {kw_str}, validate=False)" + + return [call] + + def _build_kwargs(self, obj: Any) -> list[tuple[str, str]]: + """Build a list of (name, value_str) kwargs for the add() call.""" + info_dict = obj.info(show_contents=True, return_format="dict") + kwargs: list[tuple[str, str]] = [] + + for member_name, member_info in info_dict.items(): + member_type = member_info.get("type", "") + required = member_info.get("required", True) + + if not _is_scalar_type(member_type): + continue + + value = getattr(obj, member_name, None) + + if value is None and not required: + continue + + # always add value, even if default, so that all values are explicit in the script + value_str = self._format_value(member_name, member_type, value) + if value_str is None: + continue + + kwargs.append((member_name, value_str)) + + return kwargs + + def _format_value( + self, member_name: str, member_type: str, value: Any + ) -> str | None: + """Format a scalar attribute value for inclusion in add() kwargs.""" + if value is None: + return None + + if ( + member_type in ("NmlId", "Nml2PopulationReferencePath") + and member_name != "id" + ): + return repr(str(value)) + + if isinstance(value, bool): + return repr(value) + + if isinstance(value, (int, float)): + return repr(value) + + if isinstance(value, str): + return repr(value) + + return repr(str(value)) + + def _format_kwargs(self, kwargs: list[tuple[str, str]]) -> str: + """Format kwargs into a comma-separated string for the add() call.""" + if not kwargs: + return "" + + parts = [] + for name, value in kwargs: + parts.append(f"{name}={value}") + + return ", ".join(parts) + + def _gen_footer(self) -> list[str]: + """Generate the final validation call.""" + return [ + "", + "# --- Validate ---", + "nml_doc.validate()", + "", + "# --- To write ---", + f"write_neuroml2_file(nml_doc, {self.nml_file_path.name!r})", + ] + + def _script_filename(self) -> str: + """Derive the output script filename from the input file.""" + return Path(self.nml_file).with_suffix(".py").name + + +def _get_section_name(type_name: str) -> str: + """Return the section header name for a component type.""" + if type_name == "IncludeType": + return "Includes" + if type_name == "Network": + return "Networks" + if type_name == "Population": + return "Populations" + if "Cell" in type_name: + return "Cells" + if "Channel" in type_name: + return "Channels" + if "Synapse" in type_name: + return "Synapses" + if "Projection" in type_name: + return "Projections" + if type_name in ("Connection", "ConnectionW"): + return "Connections" + if type_name in ("InputList", "InputW", "ExplicitInput"): + return "Inputs" + return "Other" + + +def process_args(): + """ + Parse command-line arguments. + """ + parser = argparse.ArgumentParser( + description=( + "A script to convert NeuroML XML serializations into Python scripts" + ) + ) + + parser.add_argument( + "file", + type=str, + metavar="", + help="Name of the NeuroML 2 file", + ) + + parser.add_argument( + "-outputDirectory", + type=str, + metavar="", + help="Output directory", + ) + return parser.parse_args() + + +def main(args=None): + """Main runner method""" + if args is None: + args = process_args() + + cli(a=args) + + +def cli(a: Any | None = None, **kwargs: str): + """Main cli caller method""" + a = pynmluc.build_namespace({}, a, **kwargs) + + nmlfile = a.file + output_dir = a.output_directory + + converter = NmlPythonizer(nmlfile, output_dir) + converter.write() diff --git a/pyneuroml/utils/plot.py b/pyneuroml/utils/plot.py index 4a862374..499993a2 100644 --- a/pyneuroml/utils/plot.py +++ b/pyneuroml/utils/plot.py @@ -351,7 +351,6 @@ def load_minimal_morphplottable__model( model_members = list(vars(nml_model).keys()) required_members = [ "id", - "cells", "morphology", "cell2_ca_poolses", "networks", @@ -359,7 +358,7 @@ def load_minimal_morphplottable__model( "includes", ] for m in model_members: - if m not in required_members: + if m not in required_members and "cells" not in m: setattr(nml_model, m, None) logger.debug(f"Dropped {m}") @@ -376,16 +375,27 @@ def load_minimal_morphplottable__model( pop.component for pop in nml_model.networks[0].populations ] + # see what cells we already have in the model document + available_cell_types = [cell.id for cell in nml_model.cells] + + # remove ones that are already available + required_cell_types = [ + cellid + for cellid in required_cell_types + if cellid not in available_cell_types + ] + # add only required cells that are included in populations to the - # document - for inc in nml_model.includes: - incl_loc = os.path.abspath(os.path.join(base_path, inc.href)) - if os.path.isfile(incl_loc): - inc = read_neuroml2_file(incl_loc) - for acell in inc.cells: - if acell.id in required_cell_types: - acell.biophysical_properties = None - nml_model.add(acell) + # document, if required + if len(required_cell_types) > 0: + for inc in nml_model.includes: + incl_loc = os.path.abspath(os.path.join(base_path, inc.href)) + if os.path.isfile(incl_loc): + inc = read_neuroml2_file(incl_loc) + for acell in inc.cells: + if acell.id in required_cell_types: + acell.biophysical_properties = None + nml_model.add(acell) else: # add any included cells or morphologies to the main document for inc in nml_model.includes: diff --git a/pyneuroml/utils/simdata.py b/pyneuroml/utils/simdata.py new file mode 100644 index 00000000..b087889e --- /dev/null +++ b/pyneuroml/utils/simdata.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python3 +""" +Utilities for analysis of simulation generated data. + +File: pyneuroml/utils/simdata.py + +Copyright 2025 NeuroML contributors +Author: Ankur Sinha +""" + +import logging +import os +import typing +from datetime import datetime + +import numpy +from lxml import etree + +logger = logging.getLogger(__name__) +logger.setLevel(logging.WARNING) + + +def load_traces_from_data_file( + data_file_names: typing.Union[str, typing.List[str]], + columns: typing.Optional[typing.List[int]] = None, +) -> typing.Dict[str, typing.Dict]: + """Load traces from a data file. + + :param data_file_names: one or more names of data files + :type data_file_names: str or list(str) + :param columns: column indices to plot + :type columns: list of ints: [1, 2, 3] + :returns: TODO + + """ + if isinstance(data_file_names, str): + data_file_names = [data_file_names] + + all_traces = {} + for f in data_file_names: + traces = {} + logger.info(f"Processing: {f}") + + data_array = numpy.loadtxt(f) + traces["t"] = data_array[:, 0] + num_cols = numpy.shape(data_array)[1] + for i in range(1, num_cols, 1): + if columns and len(columns) > 0: + if i not in columns: + logger.warning(f"Skipping column {i}") + continue + + traces[f"{f}_{i}"] = data_array[:, i] + + all_traces[f] = traces + + return all_traces + + +def load_sim_data_from_lems_file( + lems_file_name: str, + base_dir: str = ".", + get_events: bool = False, + get_traces: bool = True, + t_run: datetime = datetime(1900, 1, 1), + remove_dat_files_after_load: bool = False, +): + """Load simulation outputs from LEMS simulation run. + + .. versionadded:: 1.2.2 + + :param lems_file_name: name of LEMS file that was used to generate the data + :type lems_file_name: str + :param base_dir: directory to run in + :type base_dir: str + :param t_run: time of run + :type t_run: datetime + :param get_events: toggle whether events should be loaded + :type get_events: bool + :param get_traces: toggle whether traces should be loaded + :type get_traces: bool + :param remove_dat_files_after_load: toggle if data files should be deleted after they've been loaded + :type remove_dat_files_after_load: bool + + :returns: if both `get_events` and `get_traces` are selected, a tuple with + two dictionaries of dictionaries, one for traces, one for events, is + returned: + + .. code-block:: python + + all_traces, all_events + + Otherwise one dictionary of dictionaries for whichever was selected is + returned. + + The events dictionary has the following format: + + .. code-block:: python + + { + "outputfile": + { + '': { 'cell id': [] } + } + } + + The traces dictionary has the following format: + + .. code-block:: python + + { + "outputfile": + { + 't': [], + 'col 1': [] + 'col 2': [] + } + } + + Each list has multiple dictionaries, one each for each output file in + the LEMS file. + + :raises ValueError: if neither traces nor events are selected for loading + :raises OSError: if simulation output data file could not be found + :raises Exception: if the output file has not been modified since the + simulation was run (given as `t_run`) + """ + if not get_events and not get_traces: + raise ValueError("One of get_events or get_traces must be True") + + all_traces: typing.Dict[str, typing.Dict] = {} + all_events: typing.Dict[str, typing.Dict] = {} + + if not os.path.isfile(lems_file_name): + real_lems_file = os.path.realpath(os.path.join(base_dir, lems_file_name)) + else: + real_lems_file = os.path.realpath(lems_file_name) + + logger.debug( + f"Reloading data specified in LEMS file: {lems_file_name} ({real_lems_file}), base_dir: {base_dir}, cwd: {os.getcwd()}" + ) + + base_lems_file_path = os.path.dirname(os.path.realpath(lems_file_name)) + tree = etree.parse(real_lems_file) + + sim = tree.getroot().find("Simulation") + ns_prefix = "" + + possible_prefixes = ["{http://www.neuroml.org/lems/0.7.2}"] + if sim is None: + # print(tree.getroot().nsmap) + # print(tree.getroot().getchildren()) + for pre in possible_prefixes: + for comp in tree.getroot().findall(pre + "Component"): + if comp.attrib["type"] == "Simulation": + ns_prefix = pre + sim = comp + + if get_events: + event_output_files = sim.findall(ns_prefix + "EventOutputFile") + for i, of in enumerate(event_output_files): + events: typing.Dict = {} + + name = of.attrib["fileName"] + file_name = os.path.join(base_dir, name) + if not os.path.isfile(file_name): # If not relative to the LEMS file... + file_name = os.path.join(base_lems_file_path, name) + + # if not os.path.isfile(file_name): # If not relative to the LEMS file... + # file_name = os.path.join(os.getcwd(),name) + # ... try relative to cwd. + # if not os.path.isfile(file_name): # If not relative to the LEMS file... + # file_name = os.path.join(os.getcwd(),'NeuroML2','results',name) + # ... try relative to cwd in NeuroML2/results subdir. + if not os.path.isfile(file_name): # If not relative to the base dir... + raise OSError(f"Could not find simulation output file {file_name}") + + format_ = of.attrib["format"] + logger.info(f"Loading saved events from {file_name} (format: {format_})") + + selections = {} + for col in of.findall(ns_prefix + "EventSelection"): + id_ = int(col.attrib["id"]) + select = col.attrib["select"] + events[select] = [] + selections[id_] = select + + with open(file_name) as f: + for line in f: + values = line.split() + if format_ == "TIME_ID": + t = float(values[0]) + id_ = int(values[1]) + elif format_ == "ID_TIME": + id_ = int(values[0]) + t = float(values[1]) + logger.debug( + f"Found a event in cell {id_} ({selections[id_]}) at t = {t}" + ) + events[selections[id_]].append(t) + + if remove_dat_files_after_load: + logger.warning( + f"Removing file {file_name} after having loading its data!" + ) + os.remove(file_name) + all_events[name] = events + + if get_traces: + output_files = sim.findall(ns_prefix + "OutputFile") + for i, of in enumerate(output_files): + traces: typing.Dict = {} + traces["t"] = [] + name = of.attrib["fileName"] + file_name = os.path.join(base_dir, name) + + if not os.path.isfile(file_name): # If not relative to the LEMS file... + file_name = os.path.join(base_lems_file_path, name) + + if not os.path.isfile(file_name): # If not relative to the LEMS file... + file_name = os.path.join(os.getcwd(), name) + + # ... try relative to cwd. + if not os.path.isfile(file_name): # If not relative to the LEMS file... + file_name = os.path.join(os.getcwd(), "NeuroML2", "results", name) + # ... try relative to cwd in NeuroML2/results subdir. + if not os.path.isfile(file_name): # If not relative to the LEMS file... + raise OSError(f"Could not find simulation output file {file_name}") + + t_file_mod = datetime.fromtimestamp(os.path.getmtime(file_name)) + if t_file_mod < t_run: + raise Exception( + f"Expected output file {file_name}s has not been modified since " + f"{t_file_mod} but the simulation was run later at {t_run}." + ) + + cols = [] + cols.append("t") + for col in of.findall(ns_prefix + "OutputColumn"): + quantity = col.attrib["quantity"] + traces[quantity] = [] + cols.append(quantity) + + with open(file_name) as f: + for line in f: + values = line.split() + for vi in range(len(values)): + traces[cols[vi]].append(float(values[vi])) + + if remove_dat_files_after_load: + logger.warning( + f"Removing file {file_name}s after having loading its data!" + ) + os.remove(file_name) + + all_traces[name] = traces + + if get_events and get_traces: + return all_traces, all_events + elif get_traces: + return all_traces + else: + return all_events diff --git a/pyneuroml/utils/units.py b/pyneuroml/utils/units.py index e894efc8..926202ea 100644 --- a/pyneuroml/utils/units.py +++ b/pyneuroml/utils/units.py @@ -7,13 +7,13 @@ Copyright 2024 NeuroML contributors """ - import logging import typing import zipfile import lems.model.model as lems_model from lems.parser.LEMS import LEMSFileParser + import pyneuroml.utils.misc as pymisc logger = logging.getLogger(__name__) diff --git a/pyneuroml/utils/xml.py b/pyneuroml/utils/xml.py index 805b4e9c..03df629b 100644 --- a/pyneuroml/utils/xml.py +++ b/pyneuroml/utils/xml.py @@ -8,6 +8,7 @@ """ import typing + from lxml import etree diff --git a/pyneuroml/validators.py b/pyneuroml/validators.py index a1a83f66..5d57e83e 100644 --- a/pyneuroml/validators.py +++ b/pyneuroml/validators.py @@ -7,13 +7,12 @@ Copyright 2024 NeuroML contributors """ - import logging import typing import warnings +import pyneuroml.runners as pynmlr from pyneuroml import DEFAULTS -from pyneuroml.runners import run_jneuroml logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -45,7 +44,7 @@ def validate_neuroml1( stacklevel=2, ) - return run_jneuroml( + return pynmlr.run_jneuroml( pre_args, nml1_file_name, post_args, @@ -78,7 +77,7 @@ def validate_neuroml2( post_args = "" if max_memory is not None: - return run_jneuroml( + return pynmlr.run_jneuroml( pre_args, nml2_file_name, post_args, @@ -89,7 +88,7 @@ def validate_neuroml2( return_string=return_string, ) else: - return run_jneuroml( + return pynmlr.run_jneuroml( pre_args, nml2_file_name, post_args, @@ -121,7 +120,7 @@ def validate_neuroml2_lems_file( post_args = "" post_args += "-norun" - return run_jneuroml( + return pynmlr.run_jneuroml( "", nml2_lems_file_name, post_args, diff --git a/pyneuroml/xppaut/__init__.py b/pyneuroml/xppaut/__init__.py index 688a40a0..55331c73 100644 --- a/pyneuroml/xppaut/__init__.py +++ b/pyneuroml/xppaut/__init__.py @@ -251,8 +251,9 @@ def to_xpp(data, new_xpp_filename): xpp_ode = "" from pyneuroml import __version__ - xpp_ode += "\n## XPP export from pyNeuroML v%s\n"%__version__ - + + xpp_ode += "\n## XPP export from pyNeuroML v%s\n" % __version__ + xpp_ode += "\n# Parameters\n" for k, v in data["parameters"].items(): if k not in INBUILT.keys(): diff --git a/scripts/generate_test_data.py b/scripts/generate_test_data.py index f3aa24c5..b67c1966 100644 --- a/scripts/generate_test_data.py +++ b/scripts/generate_test_data.py @@ -1,5 +1,5 @@ -from random import random import math +from random import random t_max = 1 diff --git a/setup.cfg b/setup.cfg index c5dc1441..f5db1a6f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = pyNeuroML -version = 1.3.8 +version = 1.3.22 author = Padraig Gleeson author_email = p.gleeson@gmail.com url = https://github.com/NeuroML/pyNeuroML @@ -13,26 +13,26 @@ classifiers= License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) Natural Language :: English Operating System :: OS Independent - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 + Programming Language :: Python :: 3.13 + Programming Language :: Python :: 3.14 Topic :: Scientific/Engineering [options] install_requires = - pylems>=0.6.4 + pylems>=0.6.8 airspeed>=0.5.5 - neuromllite>=0.5.7 - libNeuroML>=0.5.5 + neuromllite>=0.6.1 + libNeuroML>=0.6.7 matplotlib matplotlib-scalebar progressbar2 graphviz typing; python_version<"3.5" lxml - numpy<2.0.0 + numpy sympy ppft[dill] @@ -58,6 +58,9 @@ console_scripts = pynml-plottimeseries = pyneuroml.plot.PlotTimeSeries:_time_series_plotter_main pynml-sonata = neuromllite.SonataReader:main pynml-xpp = pyneuroml.xppaut:main + pynml-swc2nml = pyneuroml.swc.ExportNML:main + pynml-nml2py = pyneuroml.utils.nml2py:main + jnml = pyneuroml.utils.jnmlwrapper:__jnmlwrapper [options.package_data] * = @@ -79,6 +82,7 @@ brian = netpyne = netpyne + NEURON povray = opencv-python @@ -97,8 +101,9 @@ vispy-common = vispy>=0.13.0 scipy pyopengl - PyOpenGL-accelerate; python_version<"3.12" + PyOpenGL-accelerate scikit-learn + frozendict vispy-qt5 = pyNeuroML[vispy-common] @@ -138,7 +143,6 @@ all = pyNeuroML[neuron] pyNeuroML[brian] pyNeuroML[netpyne] - pyNeuroML[netpyne] pyNeuroML[povray] pyNeuroML[hdf5] pyNeuroML[analysis] @@ -156,11 +160,13 @@ dev = pytest pytest-cov pytest-xdist + parameterized kaleido pre-commit doc = + pylems pyNeuroML[all] sphinxcontrib-bibtex pydata-sphinx-theme diff --git a/test-ghactions.sh b/test-ghactions.sh index 11b9f47b..cc60b8e7 100755 --- a/test-ghactions.sh +++ b/test-ghactions.sh @@ -4,7 +4,12 @@ set -e # CI already installs package and all optional dependencies, so this is redundant. # But we keep it to allow easy local testing. -pip install .[dev] +if command -v uv +then + uv pip install .[dev] +else + pip install .[dev] +fi # required to test commands that should fail # need this because other constructs don't work: @@ -28,7 +33,7 @@ echo "## Testing all CLI tools" full_path=$(command -v pynml) bin_location=$(dirname $full_path) -for f in ${bin_location}/pynml* +for f in ${bin_location}/pynml* ${bin_location}/jnml do current_exec=$(basename $f) echo "-> Testing $current_exec runs" diff --git a/tests/HH_example_cell.nml b/tests/HH_example_cell.nml index 85c43d4f..ae973c86 100644 --- a/tests/HH_example_cell.nml +++ b/tests/HH_example_cell.nml @@ -11,7 +11,7 @@ - + diff --git a/tests/HH_example_net.nml b/tests/HH_example_net.nml index 836b7012..d09be40b 100644 --- a/tests/HH_example_net.nml +++ b/tests/HH_example_net.nml @@ -1,4 +1,4 @@ - + HH cell network @@ -8,15 +8,6 @@ A population for our cell - - A populationList for our cell - - - - - - - diff --git a/tests/__init__.py b/tests/__init__.py index 66b260ec..7a4a47fe 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,12 +1,11 @@ #!/usr/bin/env python3 -import unittest import pathlib as pl +import unittest class BaseTestCase(unittest.TestCase): - """Base test case class to implement extra assertions""" def assertIsFile(self, path): diff --git a/tests/analysis/test_cell_analysis.py b/tests/analysis/test_cell_analysis.py index f2f1c58a..a183f2be 100644 --- a/tests/analysis/test_cell_analysis.py +++ b/tests/analysis/test_cell_analysis.py @@ -7,17 +7,15 @@ Copyright 2023 NeuroML contributors """ - -import unittest import pathlib - +import unittest import neuroml + from pyneuroml.analysis import generate_current_vs_frequency_curve class TestCellAnalysis(unittest.TestCase): - """Test cell analysis module""" def test_cell_analysis(self): diff --git a/tests/archive/test_archive.py b/tests/archive/test_archive.py index 8b63fef9..ac328c8c 100644 --- a/tests/archive/test_archive.py +++ b/tests/archive/test_archive.py @@ -7,7 +7,6 @@ Copyright 2023 NeuroML contributors """ - import logging import pathlib import unittest @@ -15,9 +14,10 @@ from pyneuroml.archive import ( create_combine_archive, create_combine_archive_manifest, - get_model_file_list, ) from pyneuroml.runners import run_jneuroml +from pyneuroml.utils import get_model_file_list +from pyneuroml.utils.misc import chdir logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) @@ -26,7 +26,7 @@ class TestArchiveModule(unittest.TestCase): """Test the pyneuroml.archive module.""" - def test_get_model_file_list(self): + def test_get_model_file_list_1(self): """Test get_model_file_list.""" # a NeuroML file in the tests directory thispath = pathlib.Path(__file__) @@ -35,7 +35,9 @@ def test_get_model_file_list(self): get_model_file_list("HH_example_cell.nml", filelist, dirname) self.assertEqual(4, len(filelist)) + def test_get_model_file_list_2(self): # a LEMS file in the examples directory + thispath = pathlib.Path(__file__) dirname = str(thispath.parent.parent.parent) filelist = [] get_model_file_list( @@ -43,6 +45,20 @@ def test_get_model_file_list(self): ) self.assertEqual(5, len(filelist)) + def test_get_model_file_list_2a(self): + # a LEMS file in the examples directory + thispath = pathlib.Path(__file__) + dirname = str(thispath.parent.parent.parent) + + with chdir(dirname + "/examples"): + filelist = [] + get_model_file_list( + "LEMS_NML2_Ex5_DetCell.xml", filelist, dirname + "/examples" + ) + self.assertEqual(5, len(filelist)) + + def test_get_model_file_list_3(self): + thispath = pathlib.Path(__file__) # a SEDML file in the examples directory dirname = str(thispath.parent.parent.parent) run_jneuroml( @@ -59,6 +75,8 @@ def test_get_model_file_list(self): ) self.assertEqual(6, len(filelist)) + def test_get_model_file_list_4(self): + thispath = pathlib.Path(__file__) # NeuroML file in examples directory dirname = str(thispath.parent.parent.parent) filelist = [] @@ -67,6 +85,16 @@ def test_get_model_file_list(self): ) self.assertEqual(4, len(filelist)) + def test_get_model_file_list_5(self): + thispath = pathlib.Path(__file__) + # HL23 network + dirname = str(thispath.parent.parent) + filelist = [] + get_model_file_list( + "HL23VIP.cell.nml", filelist, dirname + "/plot/L23-example/" + ) + self.assertEqual(13, len(filelist)) + def test_create_combine_archive_manifest(self): """Test create_combine_archive_manifest function.""" thispath = pathlib.Path(__file__) @@ -109,7 +137,7 @@ def test_create_combine_archive(self): rootfile=dirname + "/HH_example_cell.nml", filelist=filelist, ) - self.assertTrue(pathlib.Path(dirname + "/HH_example.neux").exists()) + self.assertTrue(pathlib.Path(dirname + "/HH_example.neux.zip").exists()) dirname = str(thispath.parent.parent.parent) filelist = [] @@ -119,7 +147,7 @@ def test_create_combine_archive(self): filelist=filelist, ) self.assertTrue( - pathlib.Path(dirname + "/examples/LEMS_NML2_Ex5_DetCell.neux").exists() + pathlib.Path(dirname + "/examples/LEMS_NML2_Ex5_DetCell.neux.zip").exists() ) dirname = str(thispath.parent.parent.parent) @@ -130,5 +158,5 @@ def test_create_combine_archive(self): filelist=filelist, ) self.assertTrue( - pathlib.Path(dirname + "/examples/NML2_SingleCompHHCell.neux").exists() + pathlib.Path(dirname + "/examples/NML2_SingleCompHHCell.neux.zip").exists() ) diff --git a/tests/channelml/CaPool.xml b/tests/channelml/CaPool.xml index c091b34c..890ce373 100644 --- a/tests/channelml/CaPool.xml +++ b/tests/channelml/CaPool.xml @@ -1,19 +1,19 @@ - - A channel from Maex, R and De Schutter, E. Synchronization of Golgi and Granule Cell Firing in a + A channel from Maex, R and De Schutter, E. Synchronization of Golgi and Granule Cell Firing in a Detailed Network Model of the Cerebellar Granule Cell Layer - - + + Signifies that the ion is involved in a process which alters its concentration - + - + This ChannelML file has been updated to reflect the preferred form of elements/attributes which will be required from v2.0. See info on Version 2 Requirements. @@ -21,7 +21,7 @@ Padraig Gleeson - + An expontially decaying pool of calcium @@ -30,15 +30,15 @@ cerebellar Granule Cell Layer. J Neurophysiol, Nov 1998; 80: 2521 - 2537 http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=PubMed&list_uids=9819260&dopt=Abstract - + - + - + - + - - + + diff --git a/tests/channelml/DoubExpSyn.xml b/tests/channelml/DoubExpSyn.xml index 64ab3e81..30eecb77 100644 --- a/tests/channelml/DoubExpSyn.xml +++ b/tests/channelml/DoubExpSyn.xml @@ -1,32 +1,32 @@ - - + ChannelML file describing a single synaptic mechanism - - + + - + Padraig Gleeson - - Simple example of a synaptic mechanism, which consists of a postsynaptic conductance which changes as + + Simple example of a synaptic mechanism, which consists of a postsynaptic conductance which changes as double exponential function of time. Mappings exist for NEURON and GENESIS. - + Receptor properties http://senselab.med.yale.edu/senselab/NeuronDB/receptors2.asp - + - + - - - \ No newline at end of file + + + diff --git a/tests/channelml/NMDA.xml b/tests/channelml/NMDA.xml index 6c647f08..e51ab401 100644 --- a/tests/channelml/NMDA.xml +++ b/tests/channelml/NMDA.xml @@ -4,31 +4,31 @@ xmlns:meta="http://morphml.org/metadata/schema" xsi:schemaLocation="http://morphml.org/channelml/schema http://www.neuroml.org/NeuroMLValidator/NeuroMLFiles/Schemata/v1.8.1/Level2/ChannelML_v1.8.1.xsd" units="Physiological Units"> - + ChannelML file describing a synaptic mechanism - - + + - + Padraig Gleeson - - + + Example of an NMDA receptor synaptic mechanism, based on Maex DeSchutter 1998, Gabbiani et al, 1994 - + - + Gabbiani F, Midtgaard J, Knopfel T. Synaptic integration in a model of cerebellar granule cells. http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=pubmed&cmd=Retrieve&dopt=AbstractPlus&list_uids=7527078 - + - Maex, R and De Schutter, E. - Synchronization of Golgi and Granule Cell Firing in a Detailed Network Model of the + Maex, R and De Schutter, E. + Synchronization of Golgi and Granule Cell Firing in a Detailed Network Model of the cerebellar Granule Cell Layer. J Neurophysiol, Nov 1998; 80: 2521 - 2537 http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=PubMed&list_uids=9819260&dopt=Abstract @@ -37,13 +37,13 @@ Receptor properties http://senselab.med.yale.edu/senselab/NeuronDB/receptors2.asp - + - + - - - - \ No newline at end of file + + + + diff --git a/tests/channelml/NaChannel_HH.xml b/tests/channelml/NaChannel_HH.xml index b1cfb0a8..73c0357b 100644 --- a/tests/channelml/NaChannel_HH.xml +++ b/tests/channelml/NaChannel_HH.xml @@ -9,7 +9,7 @@ ChannelML file containing a single Channel description - + Equations adapted from HH paper for modern convention of external potential being zero @@ -18,17 +18,17 @@ Simple example of Na conductance in squid giant axon. Based on channel from Hodgkin and Huxley 1952 - + Padraig Gleeson - UCL + UCL p.gleeson - at - ucl.ac.uk - A. L. Hodgkin and A. F. Huxley, A quantitative description of membrane current and + A. L. Hodgkin and A. F. Huxley, A quantitative description of membrane current and its application to conduction and excitation in nerve, J. Physiol., vol. 117, pp. 500-544, 1952. http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=12991237 @@ -37,31 +37,31 @@ Na channels http://senselab.med.yale.edu/senselab/NeuronDB/channelGene2.htm#table2 - - - + + + - - + + - + - - + + - + - - + + diff --git a/tests/channelml/SingleExpSyn.xml b/tests/channelml/SingleExpSyn.xml index c926e820..18a28312 100644 --- a/tests/channelml/SingleExpSyn.xml +++ b/tests/channelml/SingleExpSyn.xml @@ -1,32 +1,32 @@ - - + ChannelML file describing a single synaptic mechanism - - + + - + Padraig Gleeson - - Simple example of a synaptic mechanism, which consists of a postsynaptic conductance which changes as + + Simple example of a synaptic mechanism, which consists of a postsynaptic conductance which changes as single exponential function of time. Mappings exist for NEURON and GENESIS. - + Receptor properties http://senselab.med.yale.edu/senselab/NeuronDB/receptors2.asp - + - + - - - \ No newline at end of file + + + diff --git a/tests/channelml/test_channelml.py b/tests/channelml/test_channelml.py index 33a882c2..cd642af4 100644 --- a/tests/channelml/test_channelml.py +++ b/tests/channelml/test_channelml.py @@ -7,12 +7,13 @@ Copyright 2023 NeuroML contributors """ -import unittest import logging import pathlib as pl +import unittest from pyneuroml.channelml import channelml2nml -from pyneuroml.pynml import validate_neuroml2 +from pyneuroml.validators import validate_neuroml2 + from .. import BaseTestCase logger = logging.getLogger(__name__) @@ -20,7 +21,6 @@ class TestChannelML(BaseTestCase): - """Test ChannelML module""" def test_channelml2nml(self): diff --git a/tests/izhikevich_test_file.nml b/tests/izhikevich_test_file.nml index f9df37b2..db9b2333 100644 --- a/tests/izhikevich_test_file.nml +++ b/tests/izhikevich_test_file.nml @@ -6,4 +6,3 @@ - diff --git a/tests/lems/test_lemssimulation.py b/tests/lems/test_lemssimulation.py index f479f0e9..cc5c7c94 100644 --- a/tests/lems/test_lemssimulation.py +++ b/tests/lems/test_lemssimulation.py @@ -13,6 +13,7 @@ import unittest import pytest + from pyneuroml.lems import LEMSSimulation logger = logging.getLogger(__name__) @@ -20,7 +21,6 @@ class TestLEMSSimulation(unittest.TestCase): - """Test the LEMSSimulation class""" def test_lemssimulation_meta(self): diff --git a/tests/neuron/__init__.py b/tests/neuron/__init__.py index 38215fd2..e9c956ea 100644 --- a/tests/neuron/__init__.py +++ b/tests/neuron/__init__.py @@ -7,11 +7,9 @@ Copyright 2023 NeuroML contributors """ - import pathlib import subprocess - from pyneuroml.neuron import load_hoc_or_python_file diff --git a/tests/neuron/test_data/mods/HCNolm.mod b/tests/neuron/test_data/mods/HCNolm.mod index 7df68b52..5c2f5833 100644 --- a/tests/neuron/test_data/mods/HCNolm.mod +++ b/tests/neuron/test_data/mods/HCNolm.mod @@ -12,41 +12,41 @@ ENDCOMMENT NEURON { SUFFIX HCNolm USEION h WRITE ih VALENCE 1 ? Assuming valence = 1; TODO check this!! - - RANGE gion + + RANGE gion RANGE gmax : Will be changed when ion channel mechanism placed on cell! RANGE conductance : parameter - + RANGE g : exposure - + RANGE fopen : exposure RANGE r_instances : parameter - + RANGE r_tau : exposure - + RANGE r_inf : exposure - + RANGE r_rateScale : exposure - + RANGE r_fcond : exposure RANGE r_timeCourse_TIME_SCALE : parameter RANGE r_timeCourse_VOLT_SCALE : parameter - + RANGE r_timeCourse_t : exposure RANGE r_steadyState_rate : parameter RANGE r_steadyState_midpoint : parameter RANGE r_steadyState_scale : parameter - + RANGE r_steadyState_x : exposure RANGE r_timeCourse_V : derived variable RANGE r_tauUnscaled : derived variable RANGE conductanceScale : derived variable RANGE fopen0 : derived variable - + } UNITS { - + (nA) = (nanoamp) (uA) = (microamp) (mA) = (milliamp) @@ -60,130 +60,129 @@ UNITS { (um) = (micrometer) (umol) = (micromole) (S) = (siemens) - + } PARAMETER { - + gmax = 0 (S/cm2) : Will be changed when ion channel mechanism placed on cell! - + conductance = 1.0E-6 (uS) - r_instances = 1 + r_instances = 1 r_timeCourse_TIME_SCALE = 1 (ms) r_timeCourse_VOLT_SCALE = 1 (mV) - r_steadyState_rate = 1 + r_steadyState_rate = 1 r_steadyState_midpoint = -84.1 (mV) r_steadyState_scale = -10.2 (mV) } ASSIGNED { - + gion (S/cm2) : Transient conductance density of the channel? Standard Assigned variables with ionChannel v (mV) celsius (degC) temperature (K) eh (mV) ih (mA/cm2) - - + + r_timeCourse_V : derived variable - + r_timeCourse_t (ms) : derived variable - + r_steadyState_x : derived variable - + r_rateScale : derived variable - + r_fcond : derived variable - + r_inf : derived variable - + r_tauUnscaled (ms) : derived variable - + r_tau (ms) : derived variable - + conductanceScale : derived variable - + fopen0 : derived variable - + fopen : derived variable - + g (uS) : derived variable rate_r_q (/ms) - + } STATE { - r_q - + r_q + } INITIAL { eh = -32.9 - + temperature = celsius + 273.15 - + rates() rates() ? To ensure correct initialisation. - + r_q = r_inf - + } BREAKPOINT { - + SOLVE states METHOD cnexp - + ? DerivedVariable is based on path: conductanceScaling[*]/factor, on: Component(id=HCNolm type=ionChannelHH), from conductanceScaling; null ? Path not present in component, using factor: 1 - - conductanceScale = 1 - + + conductanceScale = 1 + ? DerivedVariable is based on path: gates[*]/fcond, on: Component(id=HCNolm type=ionChannelHH), from gates; Component(id=r type=gateHHtauInf) ? multiply applied to all instances of fcond in: ([Component(id=r type=gateHHtauInf)])) - fopen0 = r_fcond ? path based, prefix = - + fopen0 = r_fcond ? path based, prefix = + fopen = conductanceScale * fopen0 ? evaluable g = conductance * fopen ? evaluable - gion = gmax * fopen - + gion = gmax * fopen + ih = gion * (v - eh) - + } DERIVATIVE states { rates() - r_q' = rate_r_q - + r_q' = rate_r_q + } PROCEDURE rates() { - + r_timeCourse_V = v / r_timeCourse_VOLT_SCALE ? evaluable r_timeCourse_t = ( 100 + (1 / (exp(-17.9 - 0.116* r_timeCourse_V ) + exp(-1.84 + 0.09* r_timeCourse_V ))) ) * r_timeCourse_TIME_SCALE ? evaluable r_steadyState_x = r_steadyState_rate / (1 + exp(0 - (v - r_steadyState_midpoint )/ r_steadyState_scale )) ? evaluable ? DerivedVariable is based on path: q10Settings[*]/q10, on: Component(id=r type=gateHHtauInf), from q10Settings; null ? Path not present in component, using factor: 1 - - r_rateScale = 1 - + + r_rateScale = 1 + r_fcond = r_q ^ r_instances ? evaluable ? DerivedVariable is based on path: steadyState/x, on: Component(id=r type=gateHHtauInf), from steadyState; Component(id=null type=HHSigmoidVariable) r_inf = r_steadyState_x ? path based, prefix = r_ - + ? DerivedVariable is based on path: timeCourse/t, on: Component(id=r type=gateHHtauInf), from timeCourse; Component(id=null type=Bezaire_HCNolm_tau) r_tauUnscaled = r_timeCourse_t ? path based, prefix = r_ - + r_tau = r_tauUnscaled / r_rateScale ? evaluable - - + + rate_r_q = ( r_inf - r_q ) / r_tau ? Note units of all quantities used here need to be consistent! - - - - - - - -} + + + + + + +} diff --git a/tests/neuron/test_data/mods/Kdrfast.mod b/tests/neuron/test_data/mods/Kdrfast.mod index 479ff8ca..b8c261bf 100644 --- a/tests/neuron/test_data/mods/Kdrfast.mod +++ b/tests/neuron/test_data/mods/Kdrfast.mod @@ -12,50 +12,50 @@ ENDCOMMENT NEURON { SUFFIX Kdrfast USEION k WRITE ik VALENCE 1 ? Assuming valence = 1; TODO check this!! - - RANGE gion + + RANGE gion RANGE gmax : Will be changed when ion channel mechanism placed on cell! RANGE conductance : parameter - + RANGE g : exposure - + RANGE fopen : exposure RANGE n_instances : parameter - + RANGE n_alpha : exposure - + RANGE n_beta : exposure - + RANGE n_tau : exposure - + RANGE n_inf : exposure - + RANGE n_rateScale : exposure - + RANGE n_fcond : exposure RANGE n_forwardRate_rate : parameter RANGE n_forwardRate_midpoint : parameter RANGE n_forwardRate_scale : parameter - + RANGE n_forwardRate_r : exposure RANGE n_reverseRate_TIME_SCALE : parameter RANGE n_reverseRate_VOLT_SCALE : parameter - + RANGE n_reverseRate_r : exposure RANGE n_q10Settings_q10Factor : parameter RANGE n_q10Settings_experimentalTemp : parameter RANGE n_q10Settings_TENDEGREES : parameter - + RANGE n_q10Settings_q10 : exposure RANGE n_forwardRate_x : derived variable RANGE n_reverseRate_V : derived variable RANGE conductanceScale : derived variable RANGE fopen0 : derived variable - + } UNITS { - + (nA) = (nanoamp) (uA) = (microamp) (mA) = (milliamp) @@ -69,148 +69,147 @@ UNITS { (um) = (micrometer) (umol) = (micromole) (S) = (siemens) - + } PARAMETER { - + gmax = 0 (S/cm2) : Will be changed when ion channel mechanism placed on cell! - + conductance = 1.0E-6 (uS) - n_instances = 4 + n_instances = 4 n_forwardRate_rate = 0.42000002 (kHz) n_forwardRate_midpoint = -18 (mV) n_forwardRate_scale = 6 (mV) n_reverseRate_TIME_SCALE = 1 (ms) n_reverseRate_VOLT_SCALE = 1 (mV) - n_q10Settings_q10Factor = 3 + n_q10Settings_q10Factor = 3 n_q10Settings_experimentalTemp = 307.15 (K) n_q10Settings_TENDEGREES = 10 (K) } ASSIGNED { - + gion (S/cm2) : Transient conductance density of the channel? Standard Assigned variables with ionChannel v (mV) celsius (degC) temperature (K) ek (mV) ik (mA/cm2) - - + + n_forwardRate_x : derived variable - + n_forwardRate_r (kHz) : conditional derived var... - + n_reverseRate_V : derived variable - + n_reverseRate_r (kHz) : derived variable - + n_q10Settings_q10 : derived variable - + n_rateScale : derived variable - + n_alpha (kHz) : derived variable - + n_beta (kHz) : derived variable - + n_fcond : derived variable - + n_inf : derived variable - + n_tau (ms) : derived variable - + conductanceScale : derived variable - + fopen0 : derived variable - + fopen : derived variable - + g (uS) : derived variable rate_n_q (/ms) - + } STATE { - n_q - + n_q + } INITIAL { ek = -77.0 - + temperature = celsius + 273.15 - + rates() rates() ? To ensure correct initialisation. - + n_q = n_inf - + } BREAKPOINT { - + SOLVE states METHOD cnexp - + ? DerivedVariable is based on path: conductanceScaling[*]/factor, on: Component(id=Kdrfast type=ionChannelHH), from conductanceScaling; null ? Path not present in component, using factor: 1 - - conductanceScale = 1 - + + conductanceScale = 1 + ? DerivedVariable is based on path: gates[*]/fcond, on: Component(id=Kdrfast type=ionChannelHH), from gates; Component(id=n type=gateHHrates) ? multiply applied to all instances of fcond in: ([Component(id=n type=gateHHrates)])) - fopen0 = n_fcond ? path based, prefix = - + fopen0 = n_fcond ? path based, prefix = + fopen = conductanceScale * fopen0 ? evaluable g = conductance * fopen ? evaluable - gion = gmax * fopen - + gion = gmax * fopen + ik = gion * (v - ek) - + } DERIVATIVE states { rates() - n_q' = rate_n_q - + n_q' = rate_n_q + } PROCEDURE rates() { - + n_forwardRate_x = (v - n_forwardRate_midpoint ) / n_forwardRate_scale ? evaluable - if (n_forwardRate_x != 0) { + if (n_forwardRate_x != 0) { n_forwardRate_r = n_forwardRate_rate * n_forwardRate_x / (1 - exp(0 - n_forwardRate_x )) ? evaluable cdv - } else if (n_forwardRate_x == 0) { + } else if (n_forwardRate_x == 0) { n_forwardRate_r = n_forwardRate_rate ? evaluable cdv } - + n_reverseRate_V = v / n_reverseRate_VOLT_SCALE ? evaluable n_reverseRate_r = ((0.264) / (exp(( n_reverseRate_V +43)/40))) / n_reverseRate_TIME_SCALE ? evaluable n_q10Settings_q10 = n_q10Settings_q10Factor ^((temperature - n_q10Settings_experimentalTemp )/ n_q10Settings_TENDEGREES ) ? evaluable ? DerivedVariable is based on path: q10Settings[*]/q10, on: Component(id=n type=gateHHrates), from q10Settings; Component(id=null type=q10ExpTemp) ? multiply applied to all instances of q10 in: ([Component(id=null type=q10ExpTemp)])) n_rateScale = n_q10Settings_q10 ? path based, prefix = n_ - + ? DerivedVariable is based on path: forwardRate/r, on: Component(id=n type=gateHHrates), from forwardRate; Component(id=null type=HHExpLinearRate) n_alpha = n_forwardRate_r ? path based, prefix = n_ - + ? DerivedVariable is based on path: reverseRate/r, on: Component(id=n type=gateHHrates), from reverseRate; Component(id=null type=Bezaire_Kdrfast_betaq) n_beta = n_reverseRate_r ? path based, prefix = n_ - + n_fcond = n_q ^ n_instances ? evaluable n_inf = n_alpha /( n_alpha + n_beta ) ? evaluable n_tau = 1/(( n_alpha + n_beta ) * n_rateScale ) ? evaluable - - + + rate_n_q = ( n_inf - n_q ) / n_tau ? Note units of all quantities used here need to be consistent! - - - - - - - - - -} + + + + + + + + +} diff --git a/tests/neuron/test_data/mods/KvAolm.mod b/tests/neuron/test_data/mods/KvAolm.mod index c26b66ac..d5863be7 100644 --- a/tests/neuron/test_data/mods/KvAolm.mod +++ b/tests/neuron/test_data/mods/KvAolm.mod @@ -12,48 +12,48 @@ ENDCOMMENT NEURON { SUFFIX KvAolm USEION k WRITE ik VALENCE 1 ? Assuming valence = 1; TODO check this!! - - RANGE gion + + RANGE gion RANGE gmax : Will be changed when ion channel mechanism placed on cell! RANGE conductance : parameter - + RANGE g : exposure - + RANGE fopen : exposure RANGE a_instances : parameter - + RANGE a_tau : exposure - + RANGE a_inf : exposure - + RANGE a_rateScale : exposure - + RANGE a_fcond : exposure RANGE a_timeCourse_tau : parameter - + RANGE a_timeCourse_t : exposure RANGE a_steadyState_rate : parameter RANGE a_steadyState_midpoint : parameter RANGE a_steadyState_scale : parameter - + RANGE a_steadyState_x : exposure RANGE b_instances : parameter - + RANGE b_tau : exposure - + RANGE b_inf : exposure - + RANGE b_rateScale : exposure - + RANGE b_fcond : exposure RANGE b_timeCourse_TIME_SCALE : parameter RANGE b_timeCourse_VOLT_SCALE : parameter - + RANGE b_timeCourse_t : exposure RANGE b_steadyState_rate : parameter RANGE b_steadyState_midpoint : parameter RANGE b_steadyState_scale : parameter - + RANGE b_steadyState_x : exposure RANGE a_tauUnscaled : derived variable RANGE b_timeCourse_V : derived variable @@ -62,11 +62,11 @@ NEURON { RANGE b_tauUnscaled : derived variable RANGE conductanceScale : derived variable RANGE fopen0 : derived variable - + } UNITS { - + (nA) = (nanoamp) (uA) = (microamp) (mA) = (milliamp) @@ -80,147 +80,147 @@ UNITS { (um) = (micrometer) (umol) = (micromole) (S) = (siemens) - + } PARAMETER { - + gmax = 0 (S/cm2) : Will be changed when ion channel mechanism placed on cell! - + conductance = 1.0E-6 (uS) - a_instances = 1 + a_instances = 1 a_timeCourse_tau = 5 (ms) - a_steadyState_rate = 1 + a_steadyState_rate = 1 a_steadyState_midpoint = -14 (mV) a_steadyState_scale = 16.6 (mV) - b_instances = 1 + b_instances = 1 b_timeCourse_TIME_SCALE = 1 (ms) b_timeCourse_VOLT_SCALE = 1 (mV) - b_steadyState_rate = 1 + b_steadyState_rate = 1 b_steadyState_midpoint = -71 (mV) b_steadyState_scale = -7.3 (mV) } ASSIGNED { - + gion (S/cm2) : Transient conductance density of the channel? Standard Assigned variables with ionChannel v (mV) celsius (degC) temperature (K) ek (mV) ik (mA/cm2) - - + + a_timeCourse_t (ms) : derived variable - + a_steadyState_x : derived variable - + a_rateScale : derived variable - + a_fcond : derived variable - + a_inf : derived variable - + a_tauUnscaled (ms) : derived variable - + a_tau (ms) : derived variable - + b_timeCourse_V : derived variable - + b_timeCourse_alpha : derived variable - + b_timeCourse_beta : derived variable - + b_timeCourse_t (ms) : derived variable - + b_steadyState_x : derived variable - + b_rateScale : derived variable - + b_fcond : derived variable - + b_inf : derived variable - + b_tauUnscaled (ms) : derived variable - + b_tau (ms) : derived variable - + conductanceScale : derived variable - + fopen0 : derived variable - + fopen : derived variable - + g (uS) : derived variable rate_a_q (/ms) rate_b_q (/ms) - + } STATE { - a_q - b_q - + a_q + b_q + } INITIAL { ek = -77.0 - + temperature = celsius + 273.15 - + rates() rates() ? To ensure correct initialisation. - + a_q = a_inf - + b_q = b_inf - + } BREAKPOINT { - + SOLVE states METHOD cnexp - + ? DerivedVariable is based on path: conductanceScaling[*]/factor, on: Component(id=KvAolm type=ionChannelHH), from conductanceScaling; null ? Path not present in component, using factor: 1 - - conductanceScale = 1 - + + conductanceScale = 1 + ? DerivedVariable is based on path: gates[*]/fcond, on: Component(id=KvAolm type=ionChannelHH), from gates; Component(id=a type=gateHHtauInf) ? multiply applied to all instances of fcond in: ([Component(id=a type=gateHHtauInf), Component(id=b type=gateHHtauInf)])) - fopen0 = a_fcond * b_fcond ? path based, prefix = - + fopen0 = a_fcond * b_fcond ? path based, prefix = + fopen = conductanceScale * fopen0 ? evaluable g = conductance * fopen ? evaluable - gion = gmax * fopen - + gion = gmax * fopen + ik = gion * (v - ek) - + } DERIVATIVE states { rates() - a_q' = rate_a_q - b_q' = rate_b_q - + a_q' = rate_a_q + b_q' = rate_b_q + } PROCEDURE rates() { - + a_timeCourse_t = a_timeCourse_tau ? evaluable a_steadyState_x = a_steadyState_rate / (1 + exp(0 - (v - a_steadyState_midpoint )/ a_steadyState_scale )) ? evaluable ? DerivedVariable is based on path: q10Settings[*]/q10, on: Component(id=a type=gateHHtauInf), from q10Settings; null ? Path not present in component, using factor: 1 - - a_rateScale = 1 - + + a_rateScale = 1 + a_fcond = a_q ^ a_instances ? evaluable ? DerivedVariable is based on path: steadyState/x, on: Component(id=a type=gateHHtauInf), from steadyState; Component(id=null type=HHSigmoidVariable) a_inf = a_steadyState_x ? path based, prefix = a_ - + ? DerivedVariable is based on path: timeCourse/t, on: Component(id=a type=gateHHtauInf), from timeCourse; Component(id=null type=fixedTimeCourse) a_tauUnscaled = a_timeCourse_t ? path based, prefix = a_ - + a_tau = a_tauUnscaled / a_rateScale ? evaluable b_timeCourse_V = v / b_timeCourse_VOLT_SCALE ? evaluable b_timeCourse_alpha = 0.000009 / exp(( b_timeCourse_V -26)/18.5) ? evaluable @@ -229,33 +229,32 @@ PROCEDURE rates() { b_steadyState_x = b_steadyState_rate / (1 + exp(0 - (v - b_steadyState_midpoint )/ b_steadyState_scale )) ? evaluable ? DerivedVariable is based on path: q10Settings[*]/q10, on: Component(id=b type=gateHHtauInf), from q10Settings; null ? Path not present in component, using factor: 1 - - b_rateScale = 1 - + + b_rateScale = 1 + b_fcond = b_q ^ b_instances ? evaluable ? DerivedVariable is based on path: steadyState/x, on: Component(id=b type=gateHHtauInf), from steadyState; Component(id=null type=HHSigmoidVariable) b_inf = b_steadyState_x ? path based, prefix = b_ - + ? DerivedVariable is based on path: timeCourse/t, on: Component(id=b type=gateHHtauInf), from timeCourse; Component(id=null type=Bezaire_KvAolm_taub) b_tauUnscaled = b_timeCourse_t ? path based, prefix = b_ - + b_tau = b_tauUnscaled / b_rateScale ? evaluable - - + + rate_a_q = ( a_inf - a_q ) / a_tau ? Note units of all quantities used here need to be consistent! - - - - - - + + + + + + rate_b_q = ( b_inf - b_q ) / b_tau ? Note units of all quantities used here need to be consistent! - - - - - - - -} + + + + + + +} diff --git a/tests/neuron/test_data/mods/Nav.mod b/tests/neuron/test_data/mods/Nav.mod index 7c1e06c5..56d88898 100644 --- a/tests/neuron/test_data/mods/Nav.mod +++ b/tests/neuron/test_data/mods/Nav.mod @@ -12,79 +12,79 @@ ENDCOMMENT NEURON { SUFFIX Nav USEION na WRITE ina VALENCE 1 ? Assuming valence = 1; TODO check this!! - - RANGE gion + + RANGE gion RANGE gmax : Will be changed when ion channel mechanism placed on cell! RANGE conductance : parameter - + RANGE g : exposure - + RANGE fopen : exposure RANGE m_instances : parameter - + RANGE m_alpha : exposure - + RANGE m_beta : exposure - + RANGE m_tau : exposure - + RANGE m_inf : exposure - + RANGE m_rateScale : exposure - + RANGE m_fcond : exposure RANGE m_forwardRate_rate : parameter RANGE m_forwardRate_midpoint : parameter RANGE m_forwardRate_scale : parameter - + RANGE m_forwardRate_r : exposure RANGE m_reverseRate_rate : parameter RANGE m_reverseRate_midpoint : parameter RANGE m_reverseRate_scale : parameter - + RANGE m_reverseRate_r : exposure RANGE m_q10Settings_q10Factor : parameter RANGE m_q10Settings_experimentalTemp : parameter RANGE m_q10Settings_TENDEGREES : parameter - + RANGE m_q10Settings_q10 : exposure RANGE h_instances : parameter - + RANGE h_alpha : exposure - + RANGE h_beta : exposure - + RANGE h_tau : exposure - + RANGE h_inf : exposure - + RANGE h_rateScale : exposure - + RANGE h_fcond : exposure RANGE h_forwardRate_TIME_SCALE : parameter RANGE h_forwardRate_VOLT_SCALE : parameter - + RANGE h_forwardRate_r : exposure RANGE h_reverseRate_rate : parameter RANGE h_reverseRate_midpoint : parameter RANGE h_reverseRate_scale : parameter - + RANGE h_reverseRate_r : exposure RANGE h_q10Settings_q10Factor : parameter RANGE h_q10Settings_experimentalTemp : parameter RANGE h_q10Settings_TENDEGREES : parameter - + RANGE h_q10Settings_q10 : exposure RANGE m_forwardRate_x : derived variable RANGE m_reverseRate_x : derived variable RANGE h_forwardRate_V : derived variable RANGE conductanceScale : derived variable RANGE fopen0 : derived variable - + } UNITS { - + (nA) = (nanoamp) (uA) = (microamp) (mA) = (milliamp) @@ -98,174 +98,174 @@ UNITS { (um) = (micrometer) (umol) = (micromole) (S) = (siemens) - + } PARAMETER { - + gmax = 0 (S/cm2) : Will be changed when ion channel mechanism placed on cell! - + conductance = 1.0E-6 (uS) - m_instances = 3 + m_instances = 3 m_forwardRate_rate = 1.5000001 (kHz) m_forwardRate_midpoint = -43 (mV) m_forwardRate_scale = 5 (mV) m_reverseRate_rate = 1.5000001 (kHz) m_reverseRate_midpoint = -15 (mV) m_reverseRate_scale = -5 (mV) - m_q10Settings_q10Factor = 3 + m_q10Settings_q10Factor = 3 m_q10Settings_experimentalTemp = 307.15 (K) m_q10Settings_TENDEGREES = 10 (K) - h_instances = 1 + h_instances = 1 h_forwardRate_TIME_SCALE = 1 (ms) h_forwardRate_VOLT_SCALE = 1 (mV) h_reverseRate_rate = 3.3300002 (kHz) h_reverseRate_midpoint = -12.5 (mV) h_reverseRate_scale = 10 (mV) - h_q10Settings_q10Factor = 3 + h_q10Settings_q10Factor = 3 h_q10Settings_experimentalTemp = 307.15 (K) h_q10Settings_TENDEGREES = 10 (K) } ASSIGNED { - + gion (S/cm2) : Transient conductance density of the channel? Standard Assigned variables with ionChannel v (mV) celsius (degC) temperature (K) ena (mV) ina (mA/cm2) - - + + m_forwardRate_x : derived variable - + m_forwardRate_r (kHz) : conditional derived var... - + m_reverseRate_x : derived variable - + m_reverseRate_r (kHz) : conditional derived var... - + m_q10Settings_q10 : derived variable - + m_rateScale : derived variable - + m_alpha (kHz) : derived variable - + m_beta (kHz) : derived variable - + m_fcond : derived variable - + m_inf : derived variable - + m_tau (ms) : derived variable - + h_forwardRate_V : derived variable - + h_forwardRate_r (kHz) : derived variable - + h_reverseRate_r (kHz) : derived variable - + h_q10Settings_q10 : derived variable - + h_rateScale : derived variable - + h_alpha (kHz) : derived variable - + h_beta (kHz) : derived variable - + h_fcond : derived variable - + h_inf : derived variable - + h_tau (ms) : derived variable - + conductanceScale : derived variable - + fopen0 : derived variable - + fopen : derived variable - + g (uS) : derived variable rate_m_q (/ms) rate_h_q (/ms) - + } STATE { - m_q - h_q - + m_q + h_q + } INITIAL { ena = 50.0 - + temperature = celsius + 273.15 - + rates() rates() ? To ensure correct initialisation. - + m_q = m_inf - + h_q = h_inf - + } BREAKPOINT { - + SOLVE states METHOD cnexp - + ? DerivedVariable is based on path: conductanceScaling[*]/factor, on: Component(id=Nav type=ionChannelHH), from conductanceScaling; null ? Path not present in component, using factor: 1 - - conductanceScale = 1 - + + conductanceScale = 1 + ? DerivedVariable is based on path: gates[*]/fcond, on: Component(id=Nav type=ionChannelHH), from gates; Component(id=m type=gateHHrates) ? multiply applied to all instances of fcond in: ([Component(id=m type=gateHHrates), Component(id=h type=gateHHrates)])) - fopen0 = m_fcond * h_fcond ? path based, prefix = - + fopen0 = m_fcond * h_fcond ? path based, prefix = + fopen = conductanceScale * fopen0 ? evaluable g = conductance * fopen ? evaluable - gion = gmax * fopen - + gion = gmax * fopen + ina = gion * (v - ena) - + } DERIVATIVE states { rates() - m_q' = rate_m_q - h_q' = rate_h_q - + m_q' = rate_m_q + h_q' = rate_h_q + } PROCEDURE rates() { - + m_forwardRate_x = (v - m_forwardRate_midpoint ) / m_forwardRate_scale ? evaluable - if (m_forwardRate_x != 0) { + if (m_forwardRate_x != 0) { m_forwardRate_r = m_forwardRate_rate * m_forwardRate_x / (1 - exp(0 - m_forwardRate_x )) ? evaluable cdv - } else if (m_forwardRate_x == 0) { + } else if (m_forwardRate_x == 0) { m_forwardRate_r = m_forwardRate_rate ? evaluable cdv } - + m_reverseRate_x = (v - m_reverseRate_midpoint ) / m_reverseRate_scale ? evaluable - if (m_reverseRate_x != 0) { + if (m_reverseRate_x != 0) { m_reverseRate_r = m_reverseRate_rate * m_reverseRate_x / (1 - exp(0 - m_reverseRate_x )) ? evaluable cdv - } else if (m_reverseRate_x == 0) { + } else if (m_reverseRate_x == 0) { m_reverseRate_r = m_reverseRate_rate ? evaluable cdv } - + m_q10Settings_q10 = m_q10Settings_q10Factor ^((temperature - m_q10Settings_experimentalTemp )/ m_q10Settings_TENDEGREES ) ? evaluable ? DerivedVariable is based on path: q10Settings[*]/q10, on: Component(id=m type=gateHHrates), from q10Settings; Component(id=null type=q10ExpTemp) ? multiply applied to all instances of q10 in: ([Component(id=null type=q10ExpTemp)])) m_rateScale = m_q10Settings_q10 ? path based, prefix = m_ - + ? DerivedVariable is based on path: forwardRate/r, on: Component(id=m type=gateHHrates), from forwardRate; Component(id=null type=HHExpLinearRate) m_alpha = m_forwardRate_r ? path based, prefix = m_ - + ? DerivedVariable is based on path: reverseRate/r, on: Component(id=m type=gateHHrates), from reverseRate; Component(id=null type=HHExpLinearRate) m_beta = m_reverseRate_r ? path based, prefix = m_ - + m_fcond = m_q ^ m_instances ? evaluable m_inf = m_alpha /( m_alpha + m_beta ) ? evaluable m_tau = 1/(( m_alpha + m_beta ) * m_rateScale ) ? evaluable @@ -276,36 +276,35 @@ PROCEDURE rates() { ? DerivedVariable is based on path: q10Settings[*]/q10, on: Component(id=h type=gateHHrates), from q10Settings; Component(id=null type=q10ExpTemp) ? multiply applied to all instances of q10 in: ([Component(id=null type=q10ExpTemp)])) h_rateScale = h_q10Settings_q10 ? path based, prefix = h_ - + ? DerivedVariable is based on path: forwardRate/r, on: Component(id=h type=gateHHrates), from forwardRate; Component(id=null type=Bezaire_Nav_alphah) h_alpha = h_forwardRate_r ? path based, prefix = h_ - + ? DerivedVariable is based on path: reverseRate/r, on: Component(id=h type=gateHHrates), from reverseRate; Component(id=null type=HHSigmoidRate) h_beta = h_reverseRate_r ? path based, prefix = h_ - + h_fcond = h_q ^ h_instances ? evaluable h_inf = h_alpha /( h_alpha + h_beta ) ? evaluable h_tau = 1/(( h_alpha + h_beta ) * h_rateScale ) ? evaluable - - + + rate_m_q = ( m_inf - m_q ) / m_tau ? Note units of all quantities used here need to be consistent! - - - - - - - - + + + + + + + + rate_h_q = ( h_inf - h_q ) / h_tau ? Note units of all quantities used here need to be consistent! - - - - - - - - - -} + + + + + + + + +} diff --git a/tests/neuron/test_data/mods/leak_chan.mod b/tests/neuron/test_data/mods/leak_chan.mod index 5217ea7b..ce4218c7 100644 --- a/tests/neuron/test_data/mods/leak_chan.mod +++ b/tests/neuron/test_data/mods/leak_chan.mod @@ -13,19 +13,19 @@ NEURON { SUFFIX leak_chan NONSPECIFIC_CURRENT i RANGE e - - RANGE gion + + RANGE gion RANGE gmax : Will be changed when ion channel mechanism placed on cell! RANGE conductance : parameter - + RANGE g : exposure - + RANGE fopen : exposure - + } UNITS { - + (nA) = (nanoamp) (uA) = (microamp) (mA) = (milliamp) @@ -39,59 +39,58 @@ UNITS { (um) = (micrometer) (umol) = (micromole) (S) = (siemens) - + } PARAMETER { - + gmax = 0 (S/cm2) : Will be changed when ion channel mechanism placed on cell! - + conductance = 1.0E-6 (uS) } ASSIGNED { - + gion (S/cm2) : Transient conductance density of the channel? Standard Assigned variables with ionChannel v (mV) celsius (degC) temperature (K) e (mV) i (mA/cm2) - - + + fopen : derived variable - + g (uS) : derived variable - + } STATE { - + } INITIAL { temperature = celsius + 273.15 - + rates() rates() ? To ensure correct initialisation. - + } BREAKPOINT { - + rates() fopen = 1 ? evaluable g = conductance ? evaluable - gion = gmax * fopen - + gion = gmax * fopen + i = gion * (v - e) - + } PROCEDURE rates() { - - - - -} + + + +} diff --git a/tests/neuron/test_data/olm.hoc b/tests/neuron/test_data/olm.hoc index 1564d307..a281536e 100644 --- a/tests/neuron/test_data/olm.hoc +++ b/tests/neuron/test_data/olm.hoc @@ -347,5 +347,3 @@ proc position() { local i endtemplate olm - - diff --git a/tests/neuron/test_neuron_utils.py b/tests/neuron/test_neuron_utils.py index 8afb10b6..9b855643 100644 --- a/tests/neuron/test_neuron_utils.py +++ b/tests/neuron/test_neuron_utils.py @@ -7,34 +7,31 @@ Copyright 2023 NeuroML contributors """ - -import unittest import logging -import tempfile -import pytest import pathlib +import tempfile +import unittest +import pytest from pyneuroml.neuron import ( - load_hoc_or_python_file, - morphinfo, + export_mod_to_neuroml2, get_utils_hoc, getinfo, - export_mod_to_neuroml2, + load_hoc_or_python_file, + morphinfo, ) from . import load_olm_cell - logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) class TestNeuronUtils(unittest.TestCase): - """Test Neuron Utils""" - def test_hoc_loader(self): + def test_hoc_loader1(self): """Test hoc loader util function""" with tempfile.NamedTemporaryFile(mode="w", suffix=".hoc") as f: print( @@ -47,6 +44,7 @@ def test_hoc_loader(self): self.assertTrue(load_hoc_or_python_file(f.name)) + def test_hoc_loader2(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".hoc") as f: print( """ @@ -56,8 +54,10 @@ def test_hoc_loader(self): flush=True, ) - self.assertFalse(load_hoc_or_python_file(f.name)) + with self.assertRaises(RuntimeError): + load_hoc_or_python_file(f.name) + def test_hoc_loader3(self): # loading python files is not yet implemented with tempfile.NamedTemporaryFile(mode="w", suffix=".py") as f: print( diff --git a/tests/plot/CaDynamics.nml b/tests/plot/CaDynamics.nml index 56f4242a..64f34820 100644 --- a/tests/plot/CaDynamics.nml +++ b/tests/plot/CaDynamics.nml @@ -1,15 +1,15 @@ - NeuroML 2 implementation of the Ca Pool mechanism - + - + - + @@ -37,7 +37,7 @@ - + @@ -53,7 +53,7 @@ - + diff --git a/tests/plot/CaDynamics_all.nml b/tests/plot/CaDynamics_all.nml index dd338295..207b2788 100644 --- a/tests/plot/CaDynamics_all.nml +++ b/tests/plot/CaDynamics_all.nml @@ -20,4 +20,4 @@ - \ No newline at end of file + diff --git a/tests/plot/Ca_HVA.channel.nml b/tests/plot/Ca_HVA.channel.nml index acacf383..394ce1dd 100644 --- a/tests/plot/Ca_HVA.channel.nml +++ b/tests/plot/Ca_HVA.channel.nml @@ -5,17 +5,17 @@ - High voltage activated Ca2+ current. + High voltage activated Ca2+ current. NOTE: Most Allen Institute channel models from Hay et al. 2011 use Q10 scaling. This one doesn't... See https://github.com/OpenSourceBrain/AllenInstituteNeuroML/issues/2 - -Comment from original mod file: + +Comment from original mod file: Reuveni, Friedman, Amitai, and Gutnick, J.Neurosci. 1993 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -24,7 +24,7 @@ Reuveni, Friedman, Amitai, and Gutnick, J.Neurosci. 1993 - + Calcium channels @@ -45,7 +45,7 @@ Reuveni, Friedman, Amitai, and Gutnick, J.Neurosci. 1993 - + diff --git a/tests/plot/Ca_LVA.channel.nml b/tests/plot/Ca_LVA.channel.nml index db2ee055..eb67be8d 100644 --- a/tests/plot/Ca_LVA.channel.nml +++ b/tests/plot/Ca_LVA.channel.nml @@ -7,18 +7,18 @@ Low voltage activated Ca2+ current Modified slightly for Allen Institute cell models from Hay et al. 2011 version: - - Added Q10 scaling to rate variables - -Comment from original mod file: + - Added Q10 scaling to rate variables + +Comment from original mod file: Note: mtau is an approximation from the plots :Reference : : Avery and Johnston 1996, tau from Randall 1997 :Comment: shifted by -10 mv to correct for junction potential :Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -27,7 +27,7 @@ Note: mtau is an approximation from the plots - + Ca channels @@ -50,7 +50,7 @@ Note: mtau is an approximation from the plots - + diff --git a/tests/plot/Cell_497232312.cell.nml b/tests/plot/Cell_497232312.cell.nml index 5cd3cbad..2669cb40 100644 --- a/tests/plot/Cell_497232312.cell.nml +++ b/tests/plot/Cell_497232312.cell.nml @@ -14137,8 +14137,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -14451,8 +14451,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -14564,8 +14564,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -14700,8 +14700,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -14759,8 +14759,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -14887,8 +14887,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15017,8 +15017,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15094,8 +15094,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15140,8 +15140,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15242,8 +15242,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15318,8 +15318,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15428,8 +15428,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15606,8 +15606,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15706,8 +15706,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15782,8 +15782,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15851,8 +15851,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -15990,8 +15990,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16110,8 +16110,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16222,8 +16222,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16302,8 +16302,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16342,8 +16342,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16415,8 +16415,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16473,8 +16473,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16550,8 +16550,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16624,8 +16624,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16692,8 +16692,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16753,8 +16753,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16800,8 +16800,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16867,8 +16867,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -16957,8 +16957,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17009,8 +17009,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17087,8 +17087,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17155,8 +17155,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17236,8 +17236,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17281,8 +17281,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17353,8 +17353,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17472,8 +17472,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17538,8 +17538,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17629,8 +17629,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17772,8 +17772,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17836,8 +17836,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17887,8 +17887,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -17958,8 +17958,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -18056,8 +18056,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + @@ -18163,8 +18163,8 @@ Electrophysiology on which this model is based: http://celltypes.brain-map.org/m These segmentGroups correspond to the 'cables' of NeuroML v1.8.1, and map to/from NEURON sections. - - + + diff --git a/tests/plot/Ih.channel.nml b/tests/plot/Ih.channel.nml index 5b980df2..4f47efff 100644 --- a/tests/plot/Ih.channel.nml +++ b/tests/plot/Ih.channel.nml @@ -6,14 +6,14 @@ Non-specific cation current - -Comment from original mod file: + +Comment from original mod file: Reference : : Kole,Hallermann,and Stuart, J. Neurosci. 2006 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -30,7 +30,7 @@ Reference : : Kole,Hallermann,and Stuart, J. Neurosci. 2006 - + diff --git a/tests/plot/Im.channel.nml b/tests/plot/Im.channel.nml index 1a4a9d1d..6ba1a676 100644 --- a/tests/plot/Im.channel.nml +++ b/tests/plot/Im.channel.nml @@ -7,16 +7,16 @@ Muscarinic K+ current Modified slightly for Allen Institute cell models from Hay et al. 2011 version: - - Added Q10 scaling to rate variables - -Comment from original mod file: + - Added Q10 scaling to rate variables + +Comment from original mod file: :Reference : : Adams et al. 1982 - M-currents and other potassium currents in bullfrog sympathetic neurones :Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -25,7 +25,7 @@ Comment from original mod file: - + K channels @@ -42,7 +42,7 @@ Comment from original mod file: - + diff --git a/tests/plot/Im_v2.channel.nml b/tests/plot/Im_v2.channel.nml index 14bcf88f..265982a6 100644 --- a/tests/plot/Im_v2.channel.nml +++ b/tests/plot/Im_v2.channel.nml @@ -6,14 +6,14 @@ Im current - -Comment from original mod file: + +Comment from original mod file: Based on Im model of Vervaeke et al. (2006) - + Kv7/KCNQ/M-channels in rat glutamatergic hippocampal axons and their role in regulation of excitability and transmitter release, @@ -22,7 +22,7 @@ Based on Im model of Vervaeke et al. (2006) - + K channels @@ -33,18 +33,18 @@ Based on Im model of Vervaeke et al. (2006) - - + + - + - - + + diff --git a/tests/plot/Izh2007Cells.net.nml b/tests/plot/Izh2007Cells.net.nml index 87cb8f17..bdb4f248 100644 --- a/tests/plot/Izh2007Cells.net.nml +++ b/tests/plot/Izh2007Cells.net.nml @@ -7,29 +7,29 @@ Regular spiking cell - Weakly adapting cell - + Strongly adapting cell Low threshold spiking cell @@ -55,7 +55,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -79,19 +79,19 @@ - + - + - + - + - + - \ No newline at end of file + diff --git a/tests/plot/K_P.channel.nml b/tests/plot/K_P.channel.nml index 45415ab1..adb0ef7e 100644 --- a/tests/plot/K_P.channel.nml +++ b/tests/plot/K_P.channel.nml @@ -1,7 +1,7 @@ - NeuroML file containing a single Channel description @@ -10,19 +10,19 @@ Slow inactivating K+ current Modified slightly for Allen Institute cell models from Hay et al. 2011 version: - - Added Q10 scaling to rate variables + - Added Q10 scaling to rate variables - Equations for tau/inf updated to match mod - -Comment from original mod file: + +Comment from original mod file: :Comment : The persistent component of the K current :Reference : : Voltage-gated K+ channels in layer 5 neocortical pyramidal neurones from young rats:subtypes and gradients,Korngreen and Sakmann, J. Physiology, 2000 :Comment : shifted -10 mv to correct for junction potential :Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -31,7 +31,7 @@ Comment from original mod file: - + K channels @@ -54,7 +54,7 @@ Comment from original mod file: - + diff --git a/tests/plot/K_T.channel.nml b/tests/plot/K_T.channel.nml index 24c3c24d..54a6018f 100644 --- a/tests/plot/K_T.channel.nml +++ b/tests/plot/K_T.channel.nml @@ -1,7 +1,7 @@ - NeuroML file containing a single Channel description @@ -10,19 +10,19 @@ Fast inactivating K+ current Modified slightly for Allen Institute cell models from Hay et al. 2011 version: - - Added Q10 scaling to rate variables + - Added Q10 scaling to rate variables - Equations for tau/inf updated to match mod - -Comment from original mod file: + +Comment from original mod file: :Comment : The transient component of the K current :Reference : : Voltage-gated K+ channels in layer 5 neocortical pyramidal neurones from young rats:subtypes and gradients,Korngreen and Sakmann, J. Physiology, 2000 :Comment : shifted -10 mv to correct for junction potential :Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -31,7 +31,7 @@ Comment from original mod file: - + K channels @@ -54,7 +54,7 @@ Comment from original mod file: - + diff --git a/tests/plot/Kd.channel.nml b/tests/plot/Kd.channel.nml index f8801aa2..1ee6dff2 100644 --- a/tests/plot/Kd.channel.nml +++ b/tests/plot/Kd.channel.nml @@ -6,14 +6,14 @@ Kd current - -Comment from original mod file: + +Comment from original mod file: Based on Kd model of Foust et al. (2011) - + Somatic membrane potential and Kv1 channels control spike repolarization in cortical axon collaterals and presynaptic boutons @@ -22,7 +22,7 @@ Based on Kd model of Foust et al. (2011) - + K channels @@ -33,7 +33,7 @@ Based on Kd model of Foust et al. (2011) - + @@ -47,7 +47,7 @@ Based on Kd model of Foust et al. (2011) - + diff --git a/tests/plot/Kv2like.channel.nml b/tests/plot/Kv2like.channel.nml index 6e6a4c8a..aa704474 100644 --- a/tests/plot/Kv2like.channel.nml +++ b/tests/plot/Kv2like.channel.nml @@ -6,16 +6,16 @@ Kv2-like channel - -Comment from original mod file: + +Comment from original mod file: : Kv2-like channel : Adapted from model implemented in Keren et al. 2005 : Adjusted parameters to be similar to guangxitoxin-sensitive current in mouse CA1 pyramids from Liu and Bean 2014 - + - + Constraining compartmental models using multiple voltage recordings and genetic algorithms. @@ -25,14 +25,14 @@ Comment from original mod file: - Kv2 channel regulation of action potential repolarization and firing patterns + Kv2 channel regulation of action potential repolarization and firing patterns in superior cervical ganglion neurons and hippocampal CA1 pyramidal neurons. Liu PW, Bean BP. J Neurosci. 2014 Apr 2;34(14):4991-5002. - + K channels @@ -52,7 +52,7 @@ Comment from original mod file: - + @@ -64,9 +64,9 @@ Comment from original mod file: - + - + diff --git a/tests/plot/Kv3_1.channel.nml b/tests/plot/Kv3_1.channel.nml index c32df899..0127f49a 100644 --- a/tests/plot/Kv3_1.channel.nml +++ b/tests/plot/Kv3_1.channel.nml @@ -6,14 +6,14 @@ Fast, non inactivating K+ current (Kv3-like) - -Comment from original mod file: + +Comment from original mod file: :Reference : : Characterization of a Shaw-related potassium channel family in rat brain, The EMBO Journal, vol.11, no.7,2473-2486 (1992) - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -22,7 +22,7 @@ Comment from original mod file: - + K channels @@ -38,7 +38,7 @@ Comment from original mod file: - + diff --git a/tests/plot/L23-example/TestNetwork.net.nml b/tests/plot/L23-example/TestNetwork.net.nml index 9648271e..8a68e562 100644 --- a/tests/plot/L23-example/TestNetwork.net.nml +++ b/tests/plot/L23-example/TestNetwork.net.nml @@ -2,7 +2,7 @@ Generated by NeuroMLlite v0.5.3 Generated network: TestNetwork Generation seed: 1234 - NeuroMLlite parameters: + NeuroMLlite parameters: average_rate = 100 Hz num_HL23PV = 1 num_HL23PYR = 1 diff --git a/tests/plot/L23-example/channels/Ca_HVA.channel.nml b/tests/plot/L23-example/channels/Ca_HVA.channel.nml index 4219413d..055c1e43 100644 --- a/tests/plot/L23-example/channels/Ca_HVA.channel.nml +++ b/tests/plot/L23-example/channels/Ca_HVA.channel.nml @@ -5,15 +5,15 @@ - High voltage activated Ca2+ current. - -Comment from original mod file: + High voltage activated Ca2+ current. + +Comment from original mod file: Reuveni, Friedman, Amitai, and Gutnick, J.Neurosci. 1993 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -22,7 +22,7 @@ Reuveni, Friedman, Amitai, and Gutnick, J.Neurosci. 1993 - + Calcium channels @@ -43,7 +43,7 @@ Reuveni, Friedman, Amitai, and Gutnick, J.Neurosci. 1993 - + diff --git a/tests/plot/L23-example/channels/Ih.channel.nml b/tests/plot/L23-example/channels/Ih.channel.nml index 5b980df2..4f47efff 100644 --- a/tests/plot/L23-example/channels/Ih.channel.nml +++ b/tests/plot/L23-example/channels/Ih.channel.nml @@ -6,14 +6,14 @@ Non-specific cation current - -Comment from original mod file: + +Comment from original mod file: Reference : : Kole,Hallermann,and Stuart, J. Neurosci. 2006 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -30,7 +30,7 @@ Reference : : Kole,Hallermann,and Stuart, J. Neurosci. 2006 - + diff --git a/tests/plot/L23-example/channels/Im.channel.nml b/tests/plot/L23-example/channels/Im.channel.nml index 0dd18fec..3c5a1a9e 100644 --- a/tests/plot/L23-example/channels/Im.channel.nml +++ b/tests/plot/L23-example/channels/Im.channel.nml @@ -6,15 +6,15 @@ Muscarinic K+ current - -Comment from original mod file: + +Comment from original mod file: :Reference : : Adams et al. 1982 - M-currents and other potassium currents in bullfrog sympathetic neurones :Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -23,7 +23,7 @@ Comment from original mod file: - + K channels @@ -40,7 +40,7 @@ Comment from original mod file: - + diff --git a/tests/plot/L23-example/channels/pas.channel.nml b/tests/plot/L23-example/channels/pas.channel.nml index 02de1f44..41308e61 100644 --- a/tests/plot/L23-example/channels/pas.channel.nml +++ b/tests/plot/L23-example/channels/pas.channel.nml @@ -7,7 +7,7 @@ Simple example of a leak/passive conductance. Note: for GENESIS cells with a single leak conductance, it is better to use the Rm and Em variables for a passive current. - + diff --git a/tests/plot/NaTa.channel.nml b/tests/plot/NaTa.channel.nml index 9c85eda1..225dab40 100644 --- a/tests/plot/NaTa.channel.nml +++ b/tests/plot/NaTa.channel.nml @@ -1,7 +1,7 @@ - NeuroML file containing a single Channel description @@ -10,16 +10,16 @@ Fast inactivating Na+ current Modified slightly for Allen Institute cell models from Hay et al. 2011 version: - - Added Q10 scaling to rate variables - - Values for midpoint changed to match mod - -Comment from original mod file: + - Added Q10 scaling to rate variables + - Values for midpoint changed to match mod + +Comment from original mod file: :Reference :Colbert and Pan 2002 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -28,7 +28,7 @@ Comment from original mod file: - + Na channels @@ -51,7 +51,7 @@ Comment from original mod file: - + diff --git a/tests/plot/NaTs.channel.nml b/tests/plot/NaTs.channel.nml index 5db143cb..6212a61a 100644 --- a/tests/plot/NaTs.channel.nml +++ b/tests/plot/NaTs.channel.nml @@ -1,25 +1,25 @@ - - + NeuroML file containing a single Channel description - Fast inactivating Na+ current. + Fast inactivating Na+ current. Modified slightly for Allen Institute cell models from Hay et al. 2011 version: - - Added Q10 scaling to rate variables - - Values for midpoint changed to match mod - + - Added Q10 scaling to rate variables + - Values for midpoint changed to match mod + Comment from mod file (NaTs2_t.mod): took the NaTa and shifted both activation/inactivation by 6 mv - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -28,7 +28,7 @@ Comment from mod file (NaTs2_t.mod): took the NaTa and shifted both activation/i - + Na channels @@ -51,7 +51,7 @@ Comment from mod file (NaTs2_t.mod): took the NaTa and shifted both activation/i - + diff --git a/tests/plot/NaV.channel.nml b/tests/plot/NaV.channel.nml index 09780202..b9d05063 100644 --- a/tests/plot/NaV.channel.nml +++ b/tests/plot/NaV.channel.nml @@ -1,7 +1,7 @@ - @@ -10,11 +10,11 @@ Mouse sodium current : Kinetics of Carter et al. (2012) : Based on 37 degC recordings from mouse hippocampal CA1 pyramids - + - + Na channels @@ -26,160 +26,160 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - - + + - - - - - - - + + + + + + + - + - + @@ -188,16 +188,16 @@ - + - - - - - + + + + + - + @@ -206,6 +206,6 @@ - + diff --git a/tests/plot/Nap.channel.nml b/tests/plot/Nap.channel.nml index 5b22b261..63570a0c 100644 --- a/tests/plot/Nap.channel.nml +++ b/tests/plot/Nap.channel.nml @@ -8,18 +8,18 @@ Persistent Na+ current Modified for Allen Institute cell models from Hay et al. 2011 version: - Form of conductance expression changed from: g = gbar * m^3 * h to: g = gbar * minf * h (comment in mod: assuming instantaneous activation as modeled by Magistretti and Alonso) -- Added Q10 scaling to rate variables +- Added Q10 scaling to rate variables -Comment from original mod file: +Comment from original mod file: :Comment : mtau deduced from text (said to be 6 times faster than for NaTa) :Comment : so I used the equations from NaT and multiplied by 6 :Reference : Modeled according to kinetics derived from Magistretti and Alonso 1999 :Comment: corrected rates using q10 = 2.3, target temperature 34, orginal 21 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -28,7 +28,7 @@ Comment from original mod file: - + Na channels @@ -50,7 +50,7 @@ Comment from original mod file: - + diff --git a/tests/plot/SK.channel.nml b/tests/plot/SK.channel.nml index 5d940d61..2c87db61 100644 --- a/tests/plot/SK.channel.nml +++ b/tests/plot/SK.channel.nml @@ -6,15 +6,15 @@ Small-conductance, Ca2+ activated K+ current - -Comment from original mod file: + +Comment from original mod file: : SK-type calcium-activated potassium current : Reference : Kohler et al. 1996 - + - + Models of Neocortical Layer 5b Pyramidal Cells Capturing a Wide Range of Dendritic and Perisomatic Active Properties, @@ -23,7 +23,7 @@ Comment from original mod file: - + K channels @@ -39,7 +39,7 @@ Comment from original mod file: - + diff --git a/tests/plot/olm-example/HCNolm.channel.nml b/tests/plot/olm-example/HCNolm.channel.nml index 084aa197..895c6e3d 100755 --- a/tests/plot/olm-example/HCNolm.channel.nml +++ b/tests/plot/olm-example/HCNolm.channel.nml @@ -4,21 +4,21 @@ NeuroML file containing a single ion channel - + Hyperpolarization-activated, CN-gated h channel description (from Lawrence 2006) - + - + - - + + - + @@ -29,4 +29,4 @@ - \ No newline at end of file + diff --git a/tests/plot/olm-example/Kdrfast.channel.nml b/tests/plot/olm-example/Kdrfast.channel.nml index ba2eeecb..819f6b8e 100755 --- a/tests/plot/olm-example/Kdrfast.channel.nml +++ b/tests/plot/olm-example/Kdrfast.channel.nml @@ -4,30 +4,30 @@ NeuroML file containing a single ion channel - + Fast delayed rectifier K+ channel description (from Yuen and Durand 1991, modeled by Marianne Bezaire) - + - + - - + + - + - + - - + + - + - - \ No newline at end of file + + diff --git a/tests/plot/olm-example/KvAolm.channel.nml b/tests/plot/olm-example/KvAolm.channel.nml index 416972bb..cbd0fa3f 100755 --- a/tests/plot/olm-example/KvAolm.channel.nml +++ b/tests/plot/olm-example/KvAolm.channel.nml @@ -1,35 +1,35 @@ - + NeuroML file containing a single ion channel - + A-type K+ channel description (from Zhang and McBain 1995, Martina 1998, Warman 1994 - modeled by Marianne Bezaire) - + - + - + - - + + - + - + @@ -38,5 +38,5 @@ - + diff --git a/tests/plot/olm-example/Nav.channel.nml b/tests/plot/olm-example/Nav.channel.nml index c4e056b4..b28b6349 100755 --- a/tests/plot/olm-example/Nav.channel.nml +++ b/tests/plot/olm-example/Nav.channel.nml @@ -4,37 +4,37 @@ NeuroML file containing a single ion channel - + Na+ channel description (modeled by Marianne Bezaire) - + - - + + - + - - + + - + - - + + - + - + - - - + + + - + - - \ No newline at end of file + + diff --git a/tests/plot/olm-example/leak_chan.channel.nml b/tests/plot/olm-example/leak_chan.channel.nml index 5a430360..9db16996 100755 --- a/tests/plot/olm-example/leak_chan.channel.nml +++ b/tests/plot/olm-example/leak_chan.channel.nml @@ -4,5 +4,5 @@ NeuroML file containing a single passive Channel description - + diff --git a/tests/plot/pas.channel.nml b/tests/plot/pas.channel.nml index 881a1cca..cb837f5b 100644 --- a/tests/plot/pas.channel.nml +++ b/tests/plot/pas.channel.nml @@ -6,7 +6,7 @@ Simple example of a leak/passive conductance. - + diff --git a/tests/plot/test_morphology_plot.py b/tests/plot/test_morphology_plot.py index 81cadad2..7f907df0 100644 --- a/tests/plot/test_morphology_plot.py +++ b/tests/plot/test_morphology_plot.py @@ -20,9 +20,7 @@ plot_2D_schematic, plot_segment_groups_curtain_plots, ) -from pyneuroml.plot.PlotMorphologyPlotly import ( - plot_3D_cell_morphology_plotly, -) +from pyneuroml.plot.PlotMorphologyPlotly import plot_3D_cell_morphology_plotly from pyneuroml.plot.PlotMorphologyVispy import ( create_cylindrical_mesh, make_cell_upright, @@ -31,6 +29,7 @@ plot_interactive_3D, ) from pyneuroml.pynml import read_neuroml2_file +from pyneuroml.utils.misc import chdir from .. import BaseTestCase @@ -41,13 +40,18 @@ class TestMorphologyPlot(BaseTestCase): """Test Plot module""" + @pytest.fixture(autouse=True) + def plot_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + def test_2d_point_plotter(self): """Test plot_2D_point_cells function.""" - nml_files = ["tests/plot/Izh2007Cells.net.nml"] + nml_files = ["Izh2007Cells.net.nml"] for nml_file in nml_files: ofile = pl.Path(nml_file).name for plane in ["xy"]: - filename = f"tests/plot/test_morphology_plot_2d_point_{ofile.replace('.', '_', 100)}_{plane}.png" + filename = f"test_morphology_plot_2d_point_{ofile.replace('.', '_', 100)}_{plane}.png" # remove the file first try: pl.Path(filename).unlink() @@ -62,17 +66,17 @@ def test_2d_point_plotter(self): @pytest.mark.localonly def test_3d_point_plotter(self): """Test plot_2D_point_cells function.""" - nml_files = ["tests/plot/Izh2007Cells.net.nml"] + nml_files = ["Izh2007Cells.net.nml"] for nml_file in nml_files: plot_interactive_3D(nml_file, theme="dark", nogui=True) def test_2d_plotter(self): """Test plot_2D function.""" - nml_files = ["tests/plot/Cell_497232312.cell.nml", "tests/plot/test.cell.nml"] + nml_files = ["Cell_497232312.cell.nml", "test.cell.nml"] for nml_file in nml_files: ofile = pl.Path(nml_file).name for plane in ["yz"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" # remove the file first try: pl.Path(filename).unlink() @@ -86,13 +90,13 @@ def test_2d_plotter(self): def test_2d_morphology_plotter_data_overlay(self): """Test plot_2D_cell_morphology method with data.""" - nml_files = ["tests/plot/Cell_497232312.cell.nml"] + nml_files = ["Cell_497232312.cell.nml"] for nml_file in nml_files: nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] ofile = pl.Path(nml_file).name plane = "xy" - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_with_data.png" + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_with_data.png" # remove the file first try: pl.Path(filename).unlink() @@ -119,183 +123,198 @@ def test_2d_morphology_plotter_data_overlay(self): def test_2d_plotter_network_with_spec(self): """Test plot_2D function with a network of a few cells with specs.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - # percentage - for plane in ["zx"]: - filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + # percentage + for plane in ["zx"]: + filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_spec={"point_fraction": 0.5}, - ) + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_spec={"point_fraction": 0.5}, + ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_plotter_network_with_detailed_spec(self): - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - # more detailed plot_spec - for plane in ["xy"]: - filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + # more detailed plot_spec + for plane in ["xy"]: + filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_spec={ - "point_cells": ["HL23VIP"], - "detailed_cells": ["HL23PYR"], - "schematic_cells": ["HL23PV"], - "constant_cells": ["HL23SST"], - }, - ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_spec={ + "point_cells": ["HL23VIP"], + "detailed_cells": ["HL23PYR"], + "schematic_cells": ["HL23PV"], + "constant_cells": ["HL23SST"], + }, + ) + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_plotter_network(self): """Test plot_2D function with a network of a few cells.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - for plane in ["yz"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + for plane in ["yz"]: + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D(nml_file, nogui=True, plane2d=plane, save_to_file=filename) + plot_2D(nml_file, nogui=True, plane2d=plane, save_to_file=filename) - self.assertIsFile(filename) - # pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_constant_plotter_network(self): """Test plot_2D_schematic function with a network of a few cells.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - for plane in ["xz"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_constant.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + for plane in ["xz"]: + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_constant.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_type="constant", - ) + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_type="constant", + ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_schematic_plotter_network(self): """Test plot_2D_schematic function with a network of a few cells.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - for plane in ["xy"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_schematic.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + for plane in ["xy"]: + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_schematic.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_type="schematic", - ) + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_type="schematic", + ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() @pytest.mark.localonly def test_3d_schematic_plotter(self): """Test plot_3D_schematic plotter function.""" - nml_file = "tests/plot/L23-example/HL23PYR.cell.nml" - nml_doc = read_neuroml2_file(nml_file) - cell: neuroml.Cell = nml_doc.cells[0] - plot_3D_schematic( - cell, - segment_groups=None, - nogui=True, - ) + with chdir("L23-example/"): + nml_file = "HL23PYR.cell.nml" + nml_doc = read_neuroml2_file(nml_file) + cell: neuroml.Cell = nml_doc.cells[0] + plot_3D_schematic( + cell, + segment_groups=None, + nogui=True, + ) @pytest.mark.localonly def test_3d_morphology_plotter_vispy_network(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - plot_interactive_3D(nml_file, min_width=1, nogui=True, theme="dark") + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + plot_interactive_3D(nml_file, min_width=1, nogui=True, theme="dark") @pytest.mark.localonly def test_3d_morphology_plotter_vispy_network_with_spec(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - plot_interactive_3D( - nml_file, - min_width=1, - nogui=True, - theme="dark", - plot_spec={"point_fraction": 0.5}, - ) + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + plot_interactive_3D( + nml_file, + min_width=1, + nogui=True, + theme="dark", + plot_spec={"point_fraction": 0.5}, + ) @pytest.mark.localonly def test_3d_morphology_plotter_vispy_network_with_spec2(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - plot_interactive_3D( - nml_file, - min_width=1, - nogui=True, - theme="dark", - plot_spec={ - "point_cells": ["HL23VIP"], - "detailed_cells": ["HL23PYR"], - "schematic_cells": ["HL23PV"], - "constant_cells": ["HL23SST"], - }, - ) + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + plot_interactive_3D( + nml_file, + min_width=1, + nogui=True, + theme="dark", + plot_spec={ + "point_cells": ["HL23VIP"], + "detailed_cells": ["HL23PYR"], + "schematic_cells": ["HL23PV"], + "constant_cells": ["HL23SST"], + }, + ) @pytest.mark.localonly def test_3d_plotter_vispy_morph_only(self): """Test plot_interactive_3D function with morphology only NeuroML document.""" - nml_file = "tests/plot/L23-example/HL23VIP.morph.cell.nml" - plot_interactive_3D(nml_file) + with chdir("L23-example/"): + nml_file = "HL23VIP.morph.cell.nml" + plot_interactive_3D(nml_file) @pytest.mark.localonly def test_3d_plotter_vispy(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/HL23PYR.cell.nml" - nml_doc = read_neuroml2_file(nml_file) - cell: neuroml.Cell = nml_doc.cells[0] - plot_3D_cell_morphology( - cell=cell, nogui=True, color="Groups", verbose=True, plot_type="constant" - ) + with chdir("L23-example/"): + nml_file = "HL23PYR.cell.nml" + nml_doc = read_neuroml2_file(nml_file) + cell: neuroml.Cell = nml_doc.cells[0] + plot_3D_cell_morphology( + cell=cell, + nogui=True, + color="Groups", + verbose=True, + plot_type="constant", + ) # test a circular soma - nml_file = "tests/plot/test-spherical-soma.cell.nml" + nml_file = "test-spherical-soma.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] plot_3D_cell_morphology( @@ -304,12 +323,10 @@ def test_3d_plotter_vispy(self): def test_3d_plotter_plotly(self): """Test plot_3D_cell_morphology_plotly function.""" - nml_files = ["tests/plot/Cell_497232312.cell.nml", "tests/plot/test.cell.nml"] + nml_files = ["Cell_497232312.cell.nml", "test.cell.nml"] for nml_file in nml_files: ofile = pl.Path(nml_file).name - filename = ( - f"tests/plot/test_morphology_plot_3d_{ofile.replace('.', '_', 100)}.png" - ) + filename = f"test_morphology_plot_3d_{ofile.replace('.', '_', 100)}.png" # remove the file first try: pl.Path(filename).unlink() @@ -323,8 +340,8 @@ def test_3d_plotter_plotly(self): def test_2d_schematic_plotter(self): """Test plot_2D_schematic function.""" - nml_file = "tests/plot/Cell_497232312.cell.nml" - olm_file = "tests/plot/test.cell.nml" + nml_file = "Cell_497232312.cell.nml" + olm_file = "test.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] @@ -336,7 +353,9 @@ def test_2d_schematic_plotter(self): for plane in ["xy", "yz", "xz"]: # olm cell - filename = f"tests/plot/test_schematic_plot_2d_{olm_ofile.replace('.', '_', 100)}_{plane}.png" + filename = ( + f"test_schematic_plot_2d_{olm_ofile.replace('.', '_', 100)}_{plane}.png" + ) try: pl.Path(filename).unlink() except FileNotFoundError: @@ -351,7 +370,9 @@ def test_2d_schematic_plotter(self): ) # more complex cell - filename = f"tests/plot/test_schematic_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + filename = ( + f"test_schematic_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + ) # remove the file first try: pl.Path(filename).unlink() @@ -372,14 +393,14 @@ def test_2d_schematic_plotter(self): def test_plot_segment_groups_curtain_plots(self): """Test plot_segment_groups_curtain_plots function.""" - nml_file = "tests/plot/Cell_497232312.cell.nml" + nml_file = "Cell_497232312.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] ofile = pl.Path(nml_file).name # more complex cell - filename = f"tests/plot/test_curtain_plot_2d_{ofile.replace('.', '_', 100)}.png" + filename = f"test_curtain_plot_2d_{ofile.replace('.', '_', 100)}.png" # remove the file first try: pl.Path(filename).unlink() @@ -402,14 +423,14 @@ def test_plot_segment_groups_curtain_plots(self): def test_plot_segment_groups_curtain_plots_with_data(self): """Test plot_segment_groups_curtain_plots function with data overlay.""" - nml_file = "tests/plot/Cell_497232312.cell.nml" + nml_file = "Cell_497232312.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] ofile = pl.Path(nml_file).name # more complex cell - filename = f"tests/plot/test_curtain_plot_2d_{ofile.replace('.', '_', 100)}_withdata.png" + filename = f"test_curtain_plot_2d_{ofile.replace('.', '_', 100)}_withdata.png" # remove the file first try: pl.Path(filename).unlink() diff --git a/tests/plot/test_plot.py b/tests/plot/test_plot.py index fe1083fb..9c8244da 100644 --- a/tests/plot/test_plot.py +++ b/tests/plot/test_plot.py @@ -7,13 +7,15 @@ Copyright 2023 NeuroML contributors """ -import random -import pytest -import unittest import logging import pathlib as pl +import random +import unittest + +import pytest + +from pyneuroml.plot import generate_interactive_plot, generate_plot -from pyneuroml.plot import generate_plot, generate_interactive_plot from .. import BaseTestCase logger = logging.getLogger(__name__) @@ -23,10 +25,15 @@ class TestPlot(BaseTestCase): """Test Plot module""" + @pytest.fixture(autouse=True) + def this_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + @pytest.mark.localonly def test_generate_plot_animated(self): """Test generate_plot function.""" - filename = "tests/plot/test_generate_plot.gif" + filename = "test_generate_plot.gif" # remove the file first try: @@ -58,7 +65,7 @@ def test_generate_plot_animated(self): @pytest.mark.localonly def test_generate_plot_animated_specify_writer(self): """Test generate_plot function with specific writer.""" - filename = "tests/plot/test_generate_plot_writer.gif" + filename = "test_generate_plot_writer.gif" # remove the file first try: @@ -91,8 +98,8 @@ def test_generate_plot_animated_specify_writer(self): @pytest.mark.localonly def test_generate_plot_animated_should_default_pillow_when_writer_invalid(self): """Test generate_plot function does not fail when writer is invalid.""" - filename1 = "tests/plot/test_generate_plot_writer1.gif" - filename2 = "tests/plot/test_generate_plot_writer2.gif" + filename1 = "test_generate_plot_writer1.gif" + filename2 = "test_generate_plot_writer2.gif" # remove the file first try: @@ -145,7 +152,7 @@ def test_generate_plot_animated_should_default_pillow_when_writer_invalid(self): def test_generate_plot(self): """Test generate_plot function.""" - filename = "tests/plot/test_generate_plot.png" + filename = "test_generate_plot.png" # remove the file first try: @@ -178,7 +185,7 @@ def test_generate_plot(self): def test_generate_interactive_plot(self): """Test generate_interactive_plot function.""" - filename = "tests/plot/test_generate_interactive_plot.png" + filename = "test_generate_interactive_plot.png" # remove the file first try: diff --git a/tests/plot/test_plot_time_series.py b/tests/plot/test_plot_time_series.py index d7ffd097..2c38f066 100644 --- a/tests/plot/test_plot_time_series.py +++ b/tests/plot/test_plot_time_series.py @@ -7,14 +7,14 @@ Copyright 2024 NeuroML contributors """ - +import logging import os +import tempfile import unittest import numpy -import logging + import pyneuroml.plot.PlotTimeSeries as pyplts -import tempfile from .. import BaseTestCase @@ -86,12 +86,59 @@ def test_plot_time_series_from_data_file(self): show_plot_already=False, save_figure_to="time-series-test-from-file-2.png", ) - self.assertIsFile("time-series-test-from-file.png") + self.assertIsFile("time-series-test-from-file-2.png") os.unlink("time-series-test-from-file.png") os.unlink("time-series-test-from-file-2.png") os.unlink(trace_file.name) + def test_plot_time_series_from_x_data_files(self): + """Test plot_time_series_from_data_file function""" + trace_file = tempfile.NamedTemporaryFile(mode="w", delete=False, dir=".") + for i in range(0, 1000): + print( + f"{i/1000}\t{numpy.random.default_rng().random()}\t{numpy.random.default_rng().random()}\t{numpy.random.default_rng().random()}", + file=trace_file, + ) + trace_file.flush() + trace_file.close() + + trace_file2 = tempfile.NamedTemporaryFile(mode="w", delete=False, dir=".") + for i in range(0, 1000): + print( + f"{i/1000}\t{numpy.random.default_rng().random()}\t{numpy.random.default_rng().random()}\t{numpy.random.default_rng().random()}", + file=trace_file2, + ) + trace_file2.flush() + trace_file2.close() + + pyplts.plot_time_series_from_data_files( + [trace_file.name, trace_file2.name], + title="", + offset=True, + show_plot_already=False, + single_plot=True, + save_figure_to="time-series-test-from-files.png", + ) + self.assertIsFile("time-series-test-from-files.png") + + os.unlink("time-series-test-from-files.png") + + pyplts.plot_time_series_from_data_files( + [trace_file.name, trace_file2.name], + title="", + offset=False, + show_plot_already=False, + save_figure_to="something", + ) + self.assertIsFile(f"{trace_file.name}.png") + self.assertIsFile(f"{trace_file2.name}.png") + os.unlink(f"{trace_file.name}.png") + os.unlink(f"{trace_file2.name}.png") + + os.unlink(trace_file.name) + os.unlink(trace_file2.name) + def test_plot_time_series_from_lems_file(self): """Test plot_time_series_from_lems_file function""" trace_file = tempfile.NamedTemporaryFile(mode="w", delete=False, dir=".") @@ -128,6 +175,11 @@ def test_plot_time_series_from_lems_file(self): + + + + + @@ -148,7 +200,7 @@ def test_plot_time_series_from_lems_file(self): lems_file.name, title="", offset=False, - show_plot_already=False, + show_plot_already=True, save_figure_to="time-series-test-from-lems-file.png", ) self.assertIsFile("time-series-test-from-lems-file.png") @@ -157,10 +209,10 @@ def test_plot_time_series_from_lems_file(self): lems_file.name, title="", offset=True, - show_plot_already=False, + show_plot_already=True, save_figure_to="time-series-test-from-lems-file-2.png", ) - self.assertIsFile("time-series-test-from-lems-file.png") + self.assertIsFile("time-series-test-from-lems-file-2.png") os.unlink("time-series-test-from-lems-file.png") os.unlink("time-series-test-from-lems-file-2.png") diff --git a/tests/sbml/test_sbml.py b/tests/sbml/test_sbml.py index b928d240..8a1ee9fe 100755 --- a/tests/sbml/test_sbml.py +++ b/tests/sbml/test_sbml.py @@ -3,20 +3,29 @@ import os import stat +import pytest + from pyneuroml import sbml +@pytest.fixture(autouse=True) +def this_dir(monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + + def test_sbml_validate_a_valid_file(): "ensure it validates a single valid file by returning True" - fname = "tests/sbml/test_data/valid_doc.sbml" + print(f"{os.getcwd() = }") + fname = "test_data/valid_doc.sbml" result = sbml.validate_sbml_files([fname]) assert result def test_sbml_validate_missing_inputfile(): try: - sbml.validate_sbml_files(["tests/sbml/test_data/nonexistent_file"]) + sbml.validate_sbml_files(["test_data/nonexistent_file"]) except FileNotFoundError: return except Exception: @@ -26,7 +35,7 @@ def test_sbml_validate_missing_inputfile(): def test_sbml_validate_no_read_access(): - fname = "tests/sbml/test_data/no_read_access.sbml" + fname = "test_data/no_read_access.sbml" # Remove read permission os.chmod(fname, 0) @@ -65,7 +74,7 @@ def test_sbml_validate_unit_consistency_check(): try: result = sbml.validate_sbml_files( - ["tests/sbml/test_data/inconsistent_units_doc.sbml"], strict_units=True + ["test_data/inconsistent_units_doc.sbml"], strict_units=True ) assert not result except Exception: @@ -73,7 +82,7 @@ def test_sbml_validate_unit_consistency_check(): try: result = sbml.validate_sbml_files( - ["tests/sbml/test_data/inconsistent_units_doc.sbml"], strict_units=False + ["test_data/inconsistent_units_doc.sbml"], strict_units=False ) assert result except Exception: @@ -90,7 +99,7 @@ def test_sbml_validate_flag_all_invalid_files(): n_files = 3 for i in range(n_files): - fname = "tests/sbml/test_data/invalid_doc%02d.sbml" % i + fname = "test_data/invalid_doc%02d.sbml" % i try: result = sbml.validate_sbml_files([fname]) diff --git a/tests/sedml/test_sedml.py b/tests/sedml/test_sedml.py index 8a0c1a39..e7199297 100755 --- a/tests/sedml/test_sedml.py +++ b/tests/sedml/test_sedml.py @@ -3,22 +3,28 @@ import os import stat +import pytest + from pyneuroml import sedml +@pytest.fixture(autouse=True) +def this_dir(monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + + def test_sedml_validate_a_valid_file(): "ensure it validates a single valid file by returning True" - fname = "tests/sedml/test_data/valid_doc.sedml" + fname = "test_data/valid_doc.sedml" result = sedml.validate_sedml_files([fname]) assert result def test_sedml_validate_missing_sourcefile(): try: - result = sedml.validate_sedml_files( - ["tests/sedml/test_data/missing_model_source.sedml"] - ) + result = sedml.validate_sedml_files(["test_data/missing_model_source.sedml"]) assert not result return except Exception: @@ -29,7 +35,7 @@ def test_sedml_validate_missing_sourcefile(): def test_sedml_validate_missing_inputfile(): try: - sedml.validate_sedml_files(["tests/sedml/test_data/nonexistent_file"]) + sedml.validate_sedml_files(["test_data/nonexistent_file"]) except FileNotFoundError: return except Exception: @@ -39,7 +45,7 @@ def test_sedml_validate_missing_inputfile(): def test_sedml_validate_no_read_access(): - fname = "tests/sedml/test_data/no_read_access.sedml" + fname = "test_data/no_read_access.sedml" # Remove read permission os.chmod(fname, 0) @@ -80,7 +86,7 @@ def test_sedml_validate_flag_all_invalid_files(): n_files = 2 for i in range(n_files): - fname = "tests/sedml/test_data/invalid_doc%02d.sedml" % (i + 1) + fname = "test_data/invalid_doc%02d.sedml" % (i + 1) try: result = sedml.validate_sedml_files([fname]) if not result: diff --git a/tests/swc/Case1_new_cvapp.morph.nml b/tests/swc/Case1_new_cvapp.morph.nml new file mode 100644 index 00000000..9b59f4a2 --- /dev/null +++ b/tests/swc/Case1_new_cvapp.morph.nml @@ -0,0 +1,98 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: Case1_new.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/Case2_new_cvapp.morph.nml b/tests/swc/Case2_new_cvapp.morph.nml new file mode 100644 index 00000000..ee6b6ac5 --- /dev/null +++ b/tests/swc/Case2_new_cvapp.morph.nml @@ -0,0 +1,87 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: Case2_new.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/Case3_new_cvapp.morph.nml b/tests/swc/Case3_new_cvapp.morph.nml new file mode 100644 index 00000000..64c0bc14 --- /dev/null +++ b/tests/swc/Case3_new_cvapp.morph.nml @@ -0,0 +1,76 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: Case3_new.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/Case4_new_cvapp.morph.nml b/tests/swc/Case4_new_cvapp.morph.nml new file mode 100644 index 00000000..b7102107 --- /dev/null +++ b/tests/swc/Case4_new_cvapp.morph.nml @@ -0,0 +1,108 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: Case4_new.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/Case5_new_cvapp.morph.nml b/tests/swc/Case5_new_cvapp.morph.nml new file mode 100644 index 00000000..b82e894c --- /dev/null +++ b/tests/swc/Case5_new_cvapp.morph.nml @@ -0,0 +1,102 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: Case5_new.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/__init__.py b/tests/swc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/swc/dCH-cobalt.CNG.swc b/tests/swc/dCH-cobalt.CNG.swc new file mode 100644 index 00000000..f2515181 --- /dev/null +++ b/tests/swc/dCH-cobalt.CNG.swc @@ -0,0 +1,6273 @@ +# Original file dCH-cobalt.swc edited by Duncan Donohue using StdSwc version 1.31 on 10/1/10. +# Irregularities and fixes documented in dCH-cobalt.swc.std. See StdSwc1.31.doc for more information. +# +# dCH neuron (lobula place tangential cells, LPTC) from Calliphora vicina +# identification by response properties, cobalt fills, light microscopy, 40x objective +# processed with the TREES toolbox http://www.treestoolbox.org +# scaling 1:1:1 um +# Max Planck Institute of Neurobiology, Martinsried, Germany +# Systems and Computational Neuroscience, Alexander Borst +# published in "The intrinsic electrophysiological characteristics of fly lobula plate tangential cells: I. Passive membrane properties" Haag J, Borst A. PMID 9001975 +# ORIGINAL_SOURCE +# CREATURE +# REGION +# FIELD/LAYER +# TYPE +# CONTRIBUTOR +# REFERENCE +# RAW +# EXTRAS +# SOMA_AREA +# SHRINKAGE_CORRECTION +# VERSION_NUMBER +# VERSION_DATE +# ********************************************* +# SCALE 1.0 1.0 1.0 + 1 1 -419.15 -22.7 95.4 8 -1 + 2 1 -417.75 -24.9 94.7 8 1 + 3 1 -415.65 -25.4 89.2 6.75 2 + 4 1 -418.25 -27.6 86.8 6 3 + 5 1 -419.85 -29 86.3 5.75 4 + 6 1 -419.65 -30.8 85.5 6 5 + 7 1 -422.45 -32.1 82.4 6 6 + 8 1 -423.45 -33.3 82.4 6 7 + 9 1 -425.85 -35.6 80.1 6.25 8 + 10 1 -430.45 -40.2 65 2 9 + 11 1 -434.45 -39.5 63.9 1.25 10 + 12 1 -426.75 -39.5 65 3.25 9 + 13 1 -428.15 -43.9 58.6 3.25 12 + 14 1 -422.65 -47.3 58.6 2.5 13 + 15 1 -415.85 -43.9 58.4 2.25 14 + 16 1 -410.05 -48.2 53.8 2.5 15 + 17 1 -402.55 -51.2 50.5 2.5 16 + 18 1 -393.75 -56.9 46.6 1.75 17 + 19 1 -390.05 -56.7 44.5 1.5 18 + 20 1 -387.05 -62.3 45.6 1.75 19 + 21 1 -381.15 -61 39.8 1.75 20 + 22 1 -376.25 -64.5 41.3 1.75 21 + 23 1 -369.55 -63.6 40.6 1.5 22 + 24 1 -365.35 -68.1 35.7 1.5 23 + 25 1 -354.15 -64.8 33 1.75 24 + 26 1 -353.85 -67 33 1.75 25 + 27 1 -348.85 -70.4 32 2 26 + 28 1 -343.35 -71.4 30.1 1.75 27 + 29 1 -335.75 -76.9 29.2 1.75 28 + 30 1 -322.85 -78.5 26 2.5 29 + 31 1 -319.25 -80.9 25.5 2.5 30 + 32 1 -314.45 -84 24.1 1.75 31 + 33 1 -306.05 -86.3 24.9 1.75 32 + 34 1 -294.95 -90.3 16.3 1.25 33 + 35 1 -292.95 -93.5 16.1 1.25 34 + 36 1 -287.35 -94.6 15 1.75 35 + 37 1 -276.05 -98.5 11 1.75 36 + 38 1 -268.15 -103.5 6 1.25 37 + 39 1 -264.65 -103.2 7.3 1.25 38 + 40 1 -261.15 -105.7 3.7 1.25 39 + 41 1 -257.85 -107.8 3.6 1.25 40 + 42 1 -249.55 -110.5 0.2 1.25 41 + 43 1 -241.65 -113.7 -4.5 1.5 42 + 44 1 -235.95 -119.3 -6.4 2 43 + 45 1 -229.45 -121.4 -11.3 1.5 44 + 46 1 -221.85 -124.8 -16.1 1.25 45 + 47 1 -217.95 -128.6 -16 1.25 46 + 48 1 -210.05 -134.2 -21.9 1.25 47 + 49 1 -203.95 -140.2 -28.2 1.25 48 + 50 1 -198.55 -142.5 -28 1.25 49 + 51 1 -188.45 -145.9 -32.9 1.25 50 + 52 1 -183.25 -149.1 -35.7 1.25 51 + 53 1 -173.45 -153.6 -38.8 1.25 52 + 54 1 -164.35 -158.7 -40.6 1 53 + 55 1 -151.15 -166.8 -44.4 1.25 54 + 56 1 -142.45 -173.1 -47 1.25 55 + 57 1 -131.65 -181.3 -46.8 1.25 56 + 58 1 -121.55 -186.6 -46.8 1.25 57 + 59 1 -113.65 -189.3 -45.9 1.25 58 + 60 1 -104.85 -191.3 -43.1 1.75 59 + 61 1 -99.35 -193 -42.4 2 60 + 62 1 -91.05 -193 -40.3 1.75 61 + 63 1 -86.15 -191.4 -39.5 1.5 62 + 64 1 -81.65 -192.5 -39.3 1.5 63 + 65 1 -74.75 -193.5 -40.1 1.25 64 + 66 1 -67.05 -195.7 -41.3 1.5 65 + 67 1 -62.45 -195.7 -41.9 1 66 + 68 1 -59.15 -195.2 -42.1 1.25 67 + 69 1 -54.35 -193.8 -43.2 1.75 68 + 70 1 -51.85 -194.35 -42.8 1.25 69 + 71 1 -49.35 -194.9 -42.4 1.25 70 + 72 2 -47.35 -190.4 -52.9 2.75 70 + 73 2 -45.05 -190.2 -52.9 2.5 72 + 74 2 -35.75 -191.8 -53.4 3.25 73 + 75 2 -24.95 -193 -51.6 3.75 74 + 76 2 -20.25 -193 -53.3 3.75 75 + 77 2 -11.25 -189.2 -53.8 3.75 76 + 78 2 -4.45 -187.4 -56.1 4.25 77 + 79 2 5.55 -187.4 -58.5 3.75 78 + 80 2 9.95 -187.4 -56.8 3.5 79 + 81 2 15.55 -185.7 -58.1 3.75 80 + 82 2 23.55 -185.7 -60 5 81 + 83 2 29.95 -184 -61.5 5.25 82 + 84 2 38.15 -183.8 -63.6 6.25 83 + 85 2 45.95 -181.5 -62.9 6.5 84 + 86 2 52.45 -178.9 -65.3 5.75 85 + 87 2 59.75 -178.3 -65.3 5.25 86 + 88 2 65.75 -176.1 -65.5 4.25 87 + 89 2 72.65 -171.7 -65.8 4.25 88 + 90 2 79.45 -167.5 -64.7 5.25 89 + 91 2 87.05 -164.9 -64.8 4.75 90 + 92 2 93.15 -163.3 -63.5 3 91 + 93 2 97.45 -160.3 -63.7 4 92 + 94 2 98.05 -156.9 -61.9 4.5 93 + 95 2 104.05 -151.7 -62.7 4.5 94 + 96 2 107.85 -147 -62.9 5 95 + 97 2 112.75 -141.7 -67 4.75 96 + 98 2 117.55 -137.2 -69.6 5 97 + 99 2 121.95 -134.2 -73.8 5.25 98 + 100 2 125.45 -131.2 -73.8 5.25 99 + 101 2 128.25 -127.9 -78.1 5 100 + 102 2 131.45 -124.3 -78 4.75 101 + 103 2 134.65 -120.1 -82.6 5.25 102 + 104 2 139.45 -115.3 -87.8 4 103 + 105 2 143.35 -111.5 -90.8 3.75 104 + 106 2 147.45 -104.4 -97.5 4 105 + 107 2 151.85 -99.6 -98.6 4.5 106 + 108 2 157.05 -97.3 -103.8 4.25 107 + 109 2 162.15 -92 -103.8 5 108 + 110 2 166.85 -88.2 -104.1 5.25 109 + 111 2 171.65 -81.6 -103.7 4.25 110 + 112 2 175.15 -77.7 -105.1 4.25 111 + 113 2 180.15 -73.1 -103.3 3.75 112 + 114 2 183.95 -67.9 -104.1 4.5 113 + 115 3 185.25 -68.1 -102.5 3.25 114 + 116 3 189.05 -67.6 -104.2 3.75 115 + 117 3 192.05 -64.3 -98.9 3.5 116 + 118 3 195.85 -63.2 -95.9 3.5 117 + 119 3 199.75 -60.3 -97.3 3.5 118 + 120 3 203.55 -60.5 -95.1 3 119 + 121 3 206.75 -57.9 -93.8 3.25 120 + 122 3 209.65 -54.9 -92.7 3.25 121 + 123 3 211.95 -53 -89.3 3.25 122 + 124 3 213.85 -51.5 -88.7 3 123 + 125 3 213.85 -50.4 -89.2 3.25 124 + 126 3 219.35 -47.7 -86.7 3 125 + 127 3 219.65 -45.5 -84.7 3 126 + 128 3 226.35 -43.2 -85.5 3.25 127 + 129 3 227.55 -43 -90.9 1.5 128 + 130 3 230.65 -42.1 -90.9 3.25 129 + 131 3 231.15 -41.5 -86.6 3.25 130 + 132 3 231.15 -41.5 -86.7 1.75 131 + 133 3 233.45 -42.1 -86.6 1.75 132 + 134 3 236.55 -42.1 -87.4 1.5 133 + 135 3 238.65 -40.2 -89.4 1.75 134 + 136 3 240.95 -39 -88.1 1.75 135 + 137 3 242.05 -36.9 -87.4 2 136 + 138 3 245.35 -33.4 -81.4 2.25 137 + 139 3 248.95 -32.4 -80.6 2.25 138 + 140 3 252.15 -30.5 -77.8 2.5 139 + 141 3 254.35 -29.9 -74.9 2.5 140 + 142 3 255.95 -27.3 -76.2 2 141 + 143 3 260.05 -24.4 -73.7 2.5 142 + 144 3 263.15 -21.8 -71 2.25 143 + 145 3 263.75 -20.2 -66.7 2 144 + 146 3 269.75 -17.7 -62.1 2.5 145 + 147 3 271.95 -18.5 -61.7 2.5 146 + 148 3 273.85 -17.4 -60.9 2.5 147 + 149 3 273.05 -18 -56.9 2.75 148 + 150 3 273.05 -18 -56.8 2 149 + 151 3 274.35 -16.3 -52.9 2 150 + 152 3 275.95 -16.1 -53.6 2 151 + 153 3 278.55 -12.7 -48.9 2.25 152 + 154 3 279.95 -10.8 -47.6 2.5 153 + 155 3 279.35 -12.5 -44.7 2.25 154 + 156 3 283.75 -9.5 -47.2 2.25 155 + 157 3 285.35 -9.5 -47.1 2.25 156 + 158 3 289.15 -11 -43 3 157 + 159 3 290.65 -8.3 -41.7 3 158 + 160 3 292.55 -7.3 -36.9 3.25 159 + 161 3 294.25 -9 -35.6 3 160 + 162 3 296.05 -7.2 -36.3 3 161 + 163 3 300.25 -6.3 -30.6 3.25 162 + 164 3 303.55 -5.9 -30.7 3.5 163 + 165 3 308.75 -5.2 -28.8 3.75 164 + 166 3 312.55 -4.6 -29.6 3.25 165 + 167 3 314.15 -6.9 -22.8 3.75 166 + 168 3 315.15 -5.8 -22.1 3.75 167 + 169 3 315.15 -5.8 -18.9 2.5 168 + 170 3 320.35 -2.7 -19.3 2.25 169 + 171 3 320.35 -2.7 -22.8 1.75 170 + 172 3 323.45 -0.2 -20.2 1.75 171 + 173 3 327.75 2.4 -20.2 2 172 + 174 3 330.05 3.6 -19.9 2.25 173 + 175 3 332.25 5.2 -21.6 2.5 174 + 176 3 334.75 5.9 -17.8 2.5 175 + 177 3 338.45 8.4 -16.4 2.25 176 + 178 3 340.15 7.4 -16.4 2.25 177 + 179 3 342.95 10.7 -14.8 2.25 178 + 180 3 345.45 11.6 -17.6 2.25 179 + 181 3 347.25 11.6 -17.6 2.25 180 + 182 3 351.05 12.3 -15.8 2 181 + 183 3 354.15 11.9 -15 2.25 182 + 184 3 355.95 11.9 -14.8 2.25 183 + 185 3 358.95 7.7 -15 2.25 184 + 186 3 360.55 8.8 -12.3 2 185 + 187 3 363.75 5.5 -13.1 2.5 186 + 188 3 365.25 6.4 -13.4 2.5 187 + 189 3 367.65 4.1 -10.4 2.25 188 + 190 3 369.85 3.3 -10.6 2.25 189 + 191 3 373.45 1.1 -13.8 2.25 190 + 192 3 375.95 2.1 -10.4 2.25 191 + 193 3 377.65 -2.6 -12.9 2 192 + 194 3 380.35 -5.2 -12 2 193 + 195 3 380.55 -7.7 -12.3 1.75 194 + 196 3 384.55 -10 -12 1.75 195 + 197 3 385.65 -8.7 -11.3 1.75 196 + 198 3 387.15 -10.1 -13.1 1.75 197 + 199 3 389.75 -9.6 -13.2 2 198 + 200 3 391.15 -11.9 -12.7 2 199 + 201 3 394.35 -11.5 -19.2 1.75 200 + 202 3 397.05 -10.6 -23.7 1.75 201 + 203 3 396.65 -12.9 -23.2 2 202 + 204 3 400.05 -15.9 -28.8 1.25 203 + 205 3 401.45 -18.5 -30.2 1.25 204 + 206 3 405.45 -20 -32.2 1.25 205 + 207 3 408.45 -17.1 -34.7 0.75 206 + 208 3 411.45 -19.5 -32.4 0.75 207 + 209 3 413.05 -23.8 -32.4 0.75 208 + 210 3 413.05 -25.7 -32.4 0.75 209 + 211 3 413.05 -29.2 -32.5 0.75 210 + 212 3 414.35 -31.4 -34.2 1 211 + 213 3 416.65 -34.3 -32.8 0.75 212 + 214 3 419.25 -37.5 -32.8 0.75 213 + 215 3 422.15 -40.4 -34.1 0.75 214 + 216 3 424.25 -44.8 -31.8 0.75 215 + 217 3 422.65 -46.7 -31.8 0.75 216 + 218 3 424.25 -49.1 -32.5 0.75 217 + 219 3 426.25 -51.7 -32.5 0.75 218 + 220 3 427.05 -55.1 -32.3 0.75 219 + 221 3 428.95 -58.7 -30.7 1 220 + 222 3 428.35 -60.8 -31.2 1 221 + 223 3 431.55 -66.3 -31 0.75 222 + 224 3 431.55 -71.3 -36.9 0.5 223 + 225 3 431.55 -73.7 -36.9 0.5 224 + 226 3 427.95 -68.4 -25.7 0.5 223 + 227 3 426.35 -64.2 -30.8 0.5 222 + 228 3 424.45 -62.9 -30.8 0.5 227 + 229 3 428.25 -66.8 -30.8 0.5 227 + 230 3 425.05 -60 -30.6 0.75 221 + 231 3 423.05 -58.5 -30.6 0.5 230 + 232 3 423.95 -63 -33.8 0.5 230 + 233 3 427.75 -51.8 -38.3 0.5 219 + 234 3 431.65 -54.9 -41 0.5 233 + 235 3 429.65 -58 -41 0.5 234 + 236 3 431.15 -60.1 -41 0.5 235 + 237 3 432.95 -61.3 -37.5 0.5 236 + 238 3 429.05 -61.2 -41 0.5 236 + 239 3 428.25 -57.2 -41.6 0.5 235 + 240 3 434.45 -57.9 -36.1 0.5 234 + 241 3 428.45 -49.2 -41.6 0.5 233 + 242 3 420.05 -47.6 -31.7 0.5 217 + 243 3 419.55 -42 -34.1 0.75 215 + 244 3 418.05 -43.9 -33 0.75 243 + 245 3 417.65 -39 -34.1 0.5 243 + 246 3 417.15 -38.9 -35.2 0.5 214 + 247 3 410.95 -34.8 -36 0.5 212 + 248 3 409.35 -37.5 -36 0.5 247 + 249 3 409.15 -25.7 -32.4 0.5 210 + 250 3 406.25 -22 -34.4 1.25 206 + 251 3 407.45 -23.1 -32.7 0.75 250 + 252 3 407.45 -24.3 -32.7 0.75 251 + 253 3 408.65 -27.2 -31.5 0.75 252 + 254 3 407.55 -28.9 -32.3 0.75 253 + 255 3 410.85 -32.5 -34.6 0.75 254 + 256 3 413.85 -35.9 -35.4 0.75 255 + 257 3 417.55 -39.4 -33.6 0.75 256 + 258 3 417.05 -44.6 -31.1 0.5 257 + 259 3 419.05 -47.2 -31.1 0.5 258 + 260 3 420.95 -47.8 -30.1 0.5 259 + 261 3 413.05 -46.9 -30.1 0.5 258 + 262 3 421.15 -41.1 -35 0.5 257 + 263 3 410.55 -37.7 -35.4 0.5 256 + 264 3 408.45 -36.9 -35.4 0.5 263 + 265 3 413.55 -40.2 -35.4 0.5 263 + 266 3 405.65 -30 -32.3 0.5 254 + 267 3 405.45 -27.2 -28.6 0.5 253 + 268 3 404.45 -24.1 -28.6 0.25 267 + 269 3 404.25 -28.2 -28.6 0.25 267 + 270 3 404.15 -25.4 -32.7 0.5 252 + 271 3 402.45 -23.2 -32.7 0.5 270 + 272 3 402.95 -26.7 -32.7 0.5 270 + 273 3 404.85 -23.2 -28.9 0.5 250 + 274 3 399.05 -20.3 -30.2 0.75 205 + 275 3 397.75 -14.2 -20.9 1 203 + 276 3 399.15 -17.8 -17.2 1.25 275 + 277 3 400.45 -19.4 -20.4 1.5 276 + 278 3 399.25 -21.9 -21 1.25 277 + 279 3 400.55 -22.6 -17.9 1.25 278 + 280 3 400.95 -25.4 -20 1.25 279 + 281 3 402.95 -24.7 -19.9 1.5 280 + 282 3 404.75 -28.1 -20.4 1.25 281 + 283 3 407.55 -29.6 -24.5 1.25 282 + 284 3 410.05 -32.9 -22.8 1.25 283 + 285 3 411.65 -34.5 -24.8 1.25 284 + 286 3 412.65 -35.6 -23.5 1.25 285 + 287 3 409.65 -37.7 -25.3 1 286 + 288 3 412.25 -40.6 -20.9 1 287 + 289 3 411.45 -43.9 -19.6 0.5 288 + 290 3 415.35 -45.7 -20 0.75 289 + 291 3 418.25 -50.1 -17.6 0.75 290 + 292 3 420.75 -53.3 -22.3 0.75 291 + 293 3 422.35 -55.5 -22.8 0.75 292 + 294 3 420.15 -57.3 -23 0.75 293 + 295 3 420.15 -61 -18.3 0.75 294 + 296 3 421.15 -62.8 -22.6 0.5 295 + 297 3 419.75 -67.3 -17.4 0.5 296 + 298 3 424.25 -64.3 -22.9 0.5 296 + 299 3 426.15 -66 -22.9 0.5 298 + 300 3 424.25 -61 -18.3 0.5 295 + 301 3 425.85 -58.7 -18.3 0.5 300 + 302 3 425.85 -62.5 -18.3 0.5 300 + 303 3 424.45 -57.6 -23 0.5 294 + 304 3 426.95 -58.8 -23 0.5 303 + 305 3 425.65 -55.7 -18.8 0.5 303 + 306 3 417.15 -54.4 -22.3 0.5 292 + 307 3 415.65 -52.3 -17.5 0.25 306 + 308 3 414.75 -56.9 -20.8 0.5 306 + 309 3 416.65 -48.4 -20 0.5 290 + 310 3 409.85 -45.2 -19.6 0.5 289 + 311 3 415.75 -41.7 -26.3 0.75 288 + 312 3 419.55 -44 -26.4 0.75 311 + 313 3 420.95 -46.4 -25 0.75 312 + 314 3 421.75 -47.8 -25 0.75 313 + 315 3 424.15 -50.3 -24.2 1 314 + 316 3 426.45 -52.9 -30.7 1 315 + 317 3 427.75 -54.1 -27.4 1 316 + 318 3 428.05 -57.5 -29.1 1 317 + 319 3 429.05 -60.3 -28.8 0.75 318 + 320 3 431.35 -64.5 -24.5 0.75 319 + 321 3 431.85 -68.1 -38.6 0.75 320 + 322 3 430.05 -73.7 -29.5 0.5 321 + 323 3 433.85 -66.5 -38.6 0.5 321 + 324 3 427.45 -67.8 -24.8 0.5 320 + 325 3 426.45 -62.1 -28.8 0.5 319 + 326 3 423.85 -60.5 -28.8 0.5 325 + 327 3 425.65 -64.1 -28.8 0.5 325 + 328 3 426.05 -58.5 -34 0.5 318 + 329 3 423.45 -57.6 -34 0.5 328 + 330 3 425.05 -60.7 -34 0.5 328 + 331 3 425.55 -48.9 -34.2 0.75 316 + 332 3 427.65 -52.2 -34.1 0.5 331 + 333 3 432.25 -53.5 -39.5 0.5 332 + 334 3 429.75 -56.2 -39.5 0.5 333 + 335 3 428.35 -57.2 -39.8 0.5 334 + 336 3 432.95 -58.7 -38.7 0.5 334 + 337 3 434.45 -55.3 -38.3 0.5 333 + 338 3 429.85 -48.8 -34.1 0.25 332 + 339 3 424.45 -47 -34.2 0.75 331 + 340 3 419.25 -52.6 -22 0.75 315 + 341 3 422.85 -54.7 -21.8 0.75 340 + 342 3 420.35 -57.2 -19 0.75 341 + 343 3 421.55 -58.6 -23.1 0.75 342 + 344 3 419.15 -61.5 -20.9 0.5 343 + 345 3 421.45 -64.1 -20.9 0.5 344 + 346 3 426.05 -65.3 -22.9 0.5 345 + 347 3 421.45 -67.2 -17.3 0.5 345 + 348 3 417.65 -61.6 -20.9 0.5 344 + 349 3 423.65 -60 -19.7 0.5 343 + 350 3 424.95 -62.2 -19.7 0.5 349 + 351 3 425.35 -58.4 -19.7 0.25 349 + 352 3 424.95 -57.2 -23.2 0.5 342 + 353 3 415.25 -55.1 -21.7 0.5 340 + 354 3 423.95 -42.8 -29 0.5 313 + 355 3 415.85 -38.1 -26.9 0.75 287 + 356 3 417.05 -36.4 -28.9 0.5 286 + 357 3 418.65 -38.3 -28.9 0.5 356 + 358 3 417.95 -33.8 -28.9 0.5 356 + 359 3 414.25 -30.4 -24.8 0.5 285 + 360 3 406.05 -35 -21.9 0.75 284 + 361 3 408.35 -38.6 -21.9 0.75 360 + 362 3 405.35 -42.5 -21.8 0.75 361 + 363 3 409.85 -45.3 -21.8 0.75 362 + 364 3 412.25 -47.1 -18.9 0.75 363 + 365 3 409.55 -40.9 -21.7 0.75 361 + 366 3 411.35 -28.2 -26.6 0.5 283 + 367 3 413.85 -27.1 -25.2 0.5 366 + 368 3 411.85 -31.8 -26.6 0.5 366 + 369 3 414.25 -32.4 -26.2 0.5 368 + 370 3 416.85 -29.4 -23.1 0.5 369 + 371 3 415.55 -33.9 -26.2 0.25 369 + 372 3 401.95 -30.7 -20.4 0.5 282 + 373 3 399.95 -33.5 -22.3 0.5 372 + 374 3 401.45 -36.8 -16.8 0.5 373 + 375 3 404.75 -37.4 -16.8 0.5 374 + 376 3 399.95 -38.3 -16.8 0.5 374 + 377 3 398.15 -37.2 -22.3 0.5 373 + 378 3 404.35 -23 -21.3 0.5 281 + 379 3 406.45 -22.1 -23 0.5 378 + 380 3 402.45 -21.7 -21.3 0.5 378 + 381 3 397.75 -29.4 -22.2 0.75 280 + 382 3 396.15 -33.8 -22.3 0.75 381 + 383 3 395.95 -22.6 -16.9 0.25 279 + 384 3 403.35 -21.2 -26.6 0.5 278 + 385 3 405.05 -23.8 -26.6 0.5 384 + 386 3 404.35 -19 -26.6 0.5 384 + 387 3 403.55 -19.4 -24.5 0.5 277 + 388 3 393.95 -17.9 -23.5 0.75 275 + 389 3 396.95 -7.4 -28.7 1.25 202 + 390 3 401.25 -6.5 -29.3 1 389 + 391 3 401.55 -4.3 -38.1 0.75 390 + 392 3 400.05 -0.4 -38.1 0.5 391 + 393 3 398.15 -2.1 -38.1 0.5 392 + 394 3 397.75 -1.5 -38.1 0.5 393 + 395 3 395.45 2.2 -38.1 0.5 393 + 396 3 399.85 1.1 -38.1 0.5 392 + 397 3 398.65 -3 -38.1 0.5 391 + 398 3 403.65 -9.9 -30.9 0.5 390 + 399 3 405.35 -8.3 -32.1 0.5 398 + 400 3 404.25 -12.4 -30.9 0.5 398 + 401 3 395.65 -4 -28.3 0.5 389 + 402 3 394.55 -5.6 -28.3 0.5 401 + 403 3 393.95 -7 -28.3 0.5 402 + 404 3 393.45 -3.1 -24.6 0.5 402 + 405 3 398.55 -2.8 -25.6 0.5 401 + 406 3 391.35 -6.1 -21.1 0.5 201 + 407 3 389.25 -5.7 -22.5 0.5 406 + 408 3 386.35 -0.8 -23.7 0.5 407 + 409 3 389.35 2.3 -22.7 0.5 408 + 410 3 384.05 -0.4 -22.9 0.5 408 + 411 3 393.25 -2.9 -21.8 0.5 407 + 412 3 391.65 -15 -13.2 0.5 200 + 413 3 393.45 -17.5 -16.1 0.5 412 + 414 3 396.75 -19.7 -15.1 0.5 413 + 415 3 398.55 -18.4 -15.1 0.5 414 + 416 3 396.75 -21.7 -15.1 0.5 414 + 417 3 394.75 -21.2 -15.1 0.5 413 + 418 3 396.75 -23.3 -18.2 0.5 417 + 419 3 392.65 -22 -15.8 0.25 417 + 420 3 388.75 -13.7 -13.2 0.25 412 + 421 3 390.25 -7.3 -18.4 0.5 199 + 422 3 391.15 -4.4 -20 0.25 421 + 423 3 386.05 -6.4 -19.8 0.5 421 + 424 3 387.15 -14.4 -13.1 0.5 198 + 425 3 389.55 -16.7 -13.7 0.5 424 + 426 3 391.85 -20.8 -11.1 0.5 425 + 427 3 393.85 -23.9 -12.8 0.5 426 + 428 3 388.95 -22.2 -8.7 0.5 426 + 429 3 386.45 -18.2 -13.3 0.5 425 + 430 3 387.55 -19.8 -13.3 0.5 429 + 431 3 385.55 -20.1 -13.3 0.5 430 + 432 3 389.45 -22 -13.3 0.5 430 + 433 3 384.45 -17.8 -8.4 0.5 424 + 434 3 386.55 -5.6 -15.4 0.5 197 + 435 3 388.45 -5.2 -15.4 0.5 434 + 436 3 384.35 -4.6 -15.4 0.5 434 + 437 3 379.75 -11.9 -9.8 0.5 196 + 438 3 378.55 -13.3 -10.3 0.5 437 + 439 3 381.25 -14.3 -9.8 0.5 437 + 440 3 379.45 -12.8 -13.2 0.75 195 + 441 3 382.15 -14.5 -9.3 0.75 440 + 442 3 383.45 -16.4 -13.8 0.75 441 + 443 3 385.65 -16.8 -15 0.5 442 + 444 3 388.15 -18.1 -15.2 0.5 443 + 445 3 390.35 -15.3 -15.2 0.5 444 + 446 3 390.05 -19.5 -15.2 0.5 444 + 447 3 384.15 -18.3 -13.8 0.5 442 + 448 3 375.55 -13.5 -9.5 0.5 440 + 449 3 376.95 -7.4 -12.9 0.5 194 + 450 3 379.35 0.4 -15 1 193 + 451 3 381.95 -3.5 -14.2 0.75 450 + 452 3 383.95 -3.5 -14.1 0.75 451 + 453 3 386.55 -1.5 -11.3 0.75 452 + 454 3 389.45 -4.1 -13.8 0.75 453 + 455 3 387.65 1 -8.1 0.5 453 + 456 3 384.95 -4.9 -14.1 0.5 452 + 457 3 380.45 2 -12.9 0.75 450 + 458 3 383.75 4.2 -12.8 0.75 457 + 459 3 386.05 4.8 -17.5 0.75 458 + 460 3 388.95 4.4 -14.6 0.5 459 + 461 3 390.05 5.9 -14.5 0.5 460 + 462 3 393.35 7.3 -21 0.5 461 + 463 3 395.15 7.9 -24.5 0.5 462 + 464 3 395.95 8.3 -24.5 0.5 463 + 465 3 397.25 5.5 -24.5 0.5 463 + 466 3 388.45 10.8 -21 0.5 462 + 467 3 389.65 14.2 -21 0.5 466 + 468 3 386.55 9.1 -21 0.25 466 + 469 3 391.75 1.8 -14.5 0.5 461 + 470 3 386.05 7.3 -17.6 0.5 459 + 471 3 387.25 11.2 -20.9 0.5 470 + 472 3 388.05 14.7 -24.4 0.5 471 + 473 3 389.05 16.1 -24.4 0.5 472 + 474 3 383.75 14.4 -24.3 0.5 472 + 475 3 382.05 11.2 -24.9 0.5 471 + 476 3 380.95 12.5 -24.9 0.5 475 + 477 3 382.45 8.5 -24 0.75 470 + 478 3 384.95 10.2 -24 0.5 477 + 479 3 380.65 8.7 -24 0.25 477 + 480 3 381.75 0.6 -14.3 0.5 458 + 481 3 385.25 -1.6 -11.5 0.5 480 + 482 3 380.25 1.4 -14.3 0.25 480 + 483 3 381.45 -0.3 -12.9 0.5 457 + 484 3 378.55 4.7 -7.5 0.5 192 + 485 3 380.85 5.7 -9.3 0.5 484 + 486 3 381.85 3 -9.3 0.5 485 + 487 3 384.45 1.4 -7.9 0.5 486 + 488 3 381.85 1 -9.3 0.5 486 + 489 3 383.15 -0.9 -13.1 0.5 488 + 490 3 370.65 -3 -10 0.5 191 + 491 3 369.15 -3.8 -13.1 0.5 490 + 492 3 369.55 -7.8 -13.1 0.5 491 + 493 3 367.35 -0.5 -14.5 0.5 190 + 494 3 369.25 -4.1 -10.5 0.5 493 + 495 3 366.85 -6.3 -9.4 0.5 494 + 496 3 369.25 -9 -9.4 0.5 495 + 497 3 371.35 -5.1 -10.5 0.5 494 + 498 3 371.35 -6.2 -10.5 0.5 497 + 499 3 372.95 -5.6 -10.5 0.5 498 + 500 3 371.35 -7.8 -10.5 0.5 498 + 501 3 367.95 -1.1 -11.8 0.5 493 + 502 3 364.25 -0.5 -14.5 0.5 189 + 503 3 362.15 0.5 -11.5 0.5 188 + 504 3 362.15 -1.6 -14.4 0.5 503 + 505 3 364.45 -5 -10.1 0.5 504 + 506 3 366.25 -6.3 -10.1 0.5 505 + 507 3 360.35 -3.4 -14.4 0.5 504 + 508 3 360.35 -4.7 -9.8 0.5 507 + 509 3 360.05 0.9 -16.1 0.5 187 + 510 3 358.35 4.2 -13.2 0.5 186 + 511 3 360.65 1.8 -10.6 0.5 510 + 512 3 357.85 -1.6 -14.5 0.5 511 + 513 3 355.05 3 -10.6 0.5 510 + 514 3 358.35 15.6 -14.8 0.5 184 + 515 3 360.15 17.3 -14.4 0.5 514 + 516 3 358.75 20.5 -20.1 0.5 515 + 517 3 363.15 19.5 -14.6 0.5 515 + 518 3 356.05 5.2 -18.8 0.5 183 + 519 3 348.45 14.8 -14.7 0.5 182 + 520 3 350.45 16.7 -14.7 0.5 519 + 521 3 347.65 17.6 -12.1 0.5 520 + 522 3 348.65 15.6 -11.7 0.25 519 + 523 3 342.75 4.8 -19.3 0.5 181 + 524 3 341.45 3.2 -21 0.5 523 + 525 3 346.65 1 -21 0.5 524 + 526 3 340.05 1.5 -21 0.25 524 + 527 3 337.65 14.5 -15.4 0.5 179 + 528 3 338.65 15.9 -17.5 0.25 527 + 529 3 336.25 14.5 -15.4 0.5 527 + 530 3 341.35 2.2 -15.3 0.75 178 + 531 3 342.55 0.8 -15.3 0.75 530 + 532 3 340.25 -2.4 -19.1 0.5 531 + 533 3 343.45 -5 -20.1 0.5 532 + 534 3 344.85 -0.8 -14.4 0.5 531 + 535 3 346.55 -2.3 -13.3 0.5 534 + 536 3 334.35 12.7 -19.4 0.5 177 + 537 3 333.05 14.4 -20.9 0.5 536 + 538 3 338.55 12.7 -19.4 0.5 536 + 539 3 331.85 9.7 -17.4 0.5 176 + 540 3 328.05 9.6 -17.8 0.5 175 + 541 3 326.95 9.4 -17.8 0.5 540 + 542 3 330.95 10.5 -17.8 0.5 540 + 543 3 322.55 5.3 -25.9 0.5 173 + 544 3 320.75 4.5 -25.5 0.75 172 + 545 3 320.05 4 -25.1 0.75 544 + 546 3 324.15 8.5 -27.2 0.5 545 + 547 3 325.35 8.7 -25.2 0.5 546 + 548 3 327.05 12.4 -25.6 0.5 547 + 549 3 323.65 13.7 -25.6 0.5 548 + 550 3 322.35 16.3 -24.4 0.5 549 + 551 3 321.65 11.7 -25 0.5 549 + 552 3 325.95 7 -27.5 0.5 546 + 553 3 317.85 6.6 -30.1 0.5 545 + 554 3 318.45 1.4 -25.5 0.5 544 + 555 3 323.45 -2.2 -13.2 1.5 170 + 556 3 327.65 -5.4 -16.1 1.5 555 + 557 3 329.05 -2.1 -16.4 1.25 556 + 558 3 330.95 0.6 -11.4 1.5 557 + 559 3 330.85 2.7 -10.8 1.5 558 + 560 3 335.25 3.9 -13.1 1.5 559 + 561 3 338.15 6.5 -9.6 1.5 560 + 562 3 341.15 9.1 -10.8 1.25 561 + 563 3 340.55 10.7 -9.1 1.5 562 + 564 3 344.15 11.9 -9 1.5 563 + 565 3 347.85 8.2 -6.7 1.25 564 + 566 3 351.25 7.3 -6.4 1.25 565 + 567 3 354.05 6.4 -4.7 1.25 566 + 568 3 357.05 8.2 -6.3 1.25 567 + 569 3 358.95 8.2 -8.4 1 568 + 570 3 360.85 10.1 -8.3 1 569 + 571 3 362.25 12.1 -7 1 570 + 572 3 363.95 11.1 -7.3 1.25 571 + 573 3 366.15 11.5 -7.3 1.25 572 + 574 3 368.35 16 -11.7 0.75 573 + 575 3 369.95 17.1 -12.6 0.75 574 + 576 3 372.45 15.5 -12.6 0.75 575 + 577 3 375.85 15.5 -14.1 0.5 576 + 578 3 379.05 18.9 -19.1 0.5 577 + 579 3 380.75 21.3 -19.1 0.5 578 + 580 3 381.05 15.6 -18.3 0.5 578 + 581 3 376.75 13.8 -16.4 0.5 577 + 582 3 374.15 12.6 -16.4 0.5 581 + 583 3 371.85 19.9 -15.6 0.5 576 + 584 3 373.55 21.5 -12.7 0.5 583 + 585 3 373.55 24.1 -12.7 0.5 584 + 586 3 368.25 20.4 -17.8 0.5 583 + 587 3 371.15 13.2 -12.6 0.5 575 + 588 3 368.05 10.2 -7.1 0.75 573 + 589 3 369.55 10.7 -11.5 0.75 588 + 590 3 371.25 12.4 -11.4 0.5 589 + 591 3 374.25 9.1 -11.4 0.5 590 + 592 3 377.35 8.3 -10.2 0.5 591 + 593 3 378.65 6.9 -13.2 0.5 592 + 594 3 378.25 11.3 -10.2 0.25 592 + 595 3 372.45 7 -14.5 0.75 589 + 596 3 373.25 4.8 -15.8 0.75 595 + 597 3 371.75 1.8 -12.5 0.5 596 + 598 3 371.75 -0.9 -15.2 0.5 597 + 599 3 371.75 -3.6 -13.8 0.5 598 + 600 3 370.35 -4.5 -13.8 0.5 599 + 601 3 374.65 1.8 -12.5 0.5 597 + 602 3 375.05 4.8 -12 0.5 596 + 603 3 376.75 7.6 -12 0.5 602 + 604 3 376.35 3.6 -12 0.5 602 + 605 3 365.85 8.6 -7.3 0.5 588 + 606 3 365.15 7.7 -11.1 0.5 571 + 607 3 358.95 3.5 -6.6 0.5 569 + 608 3 355.85 4.1 -7.1 0.5 607 + 609 3 360.55 1.6 -6.6 0.5 607 + 610 3 354.05 2.8 -8.4 0.25 567 + 611 3 348.05 3 -1.6 0.5 566 + 612 3 352.05 -0.4 -4.6 0.5 611 + 613 3 346.75 0.8 -1.6 0.5 611 + 614 3 345.25 15 -9.6 0.75 564 + 615 3 344.45 18.1 -10.9 1 614 + 616 3 344.45 20 -9.2 1 615 + 617 3 349.35 21.2 -10.6 1 616 + 618 3 349.55 22.4 -11.5 1 617 + 619 3 352.05 19.8 -7.6 1 618 + 620 3 353.85 22.7 -7.5 0.75 619 + 621 3 356.75 22.7 -12.4 0.75 620 + 622 3 359.15 21.6 -8.7 0.5 621 + 623 3 361.55 19.8 -8.7 0.5 622 + 624 3 365.55 22.7 -14.8 0.5 623 + 625 3 363.05 18.3 -13.8 0.5 623 + 626 3 363.05 14.4 -13.7 0.5 625 + 627 3 358.15 19.2 -10.3 0.5 621 + 628 3 361.15 16.9 -12 0.5 627 + 629 3 362.75 18.1 -10.9 0.5 628 + 630 3 358.05 15.2 -12 0.5 628 + 631 3 356.05 17.9 -10.3 0.25 627 + 632 3 354.05 20.2 -9.7 0.5 619 + 633 3 355.75 18.1 -8.9 0.75 632 + 634 3 357.15 15.8 -9.3 0.5 633 + 635 3 359.35 13.4 -11.7 0.5 634 + 636 3 360.25 12.8 -11.9 0.5 635 + 637 3 361.75 14.5 -11.9 0.5 636 + 638 3 359.35 10.4 -11.9 0.5 636 + 639 3 360.95 17.8 -14.3 0.5 635 + 640 3 357.65 20.9 -16.3 0.5 639 + 641 3 361.05 19.3 -10.4 0.5 639 + 642 3 357.15 13.4 -11.2 0.5 634 + 643 3 358.35 12.8 -11.2 0.25 642 + 644 3 354.45 12.4 -11.2 0.5 642 + 645 3 351.55 24.2 -11.4 0.5 618 + 646 3 350.35 26.5 -11.4 0.5 645 + 647 3 352.25 16.3 -13.9 0.75 617 + 648 3 352.85 15 -13.9 0.75 647 + 649 3 356.35 12.3 -9.7 0.5 648 + 650 3 350.05 14.3 -13.9 0.25 648 + 651 3 348.65 15.5 -10.9 0.5 615 + 652 3 350.15 13.9 -10.9 0.5 651 + 653 3 341.35 18.2 -12.2 0.5 614 + 654 3 343.65 19.9 -14.2 0.5 653 + 655 3 339.65 16.4 -9.9 0.25 653 + 656 3 338.45 14.3 -9.1 0.5 563 + 657 3 336.35 15.1 -13.8 0.5 656 + 658 3 340.65 1.7 -9.6 0.25 561 + 659 3 336.55 -0.9 -14.6 0.5 560 + 660 3 337.15 -3.2 -11.2 0.5 659 + 661 3 313.85 -10.4 -23.1 1.25 168 + 662 3 318.75 -11.6 -18.5 1.75 661 + 663 3 319.95 -12.4 -21.6 1.75 662 + 664 3 321.15 -13.6 -18.7 1.75 663 + 665 3 323.55 -16.6 -19.8 2 664 + 666 3 323.75 -18.5 -18.7 1.75 665 + 667 3 326.45 -20.1 -16.5 1.5 666 + 668 3 326.45 -21.7 -13.3 1.5 667 + 669 3 327.75 -23.1 -13.6 1.5 668 + 670 3 330.15 -21.6 -8.3 1.5 669 + 671 3 332.25 -21.2 -6.1 1.75 670 + 672 3 335.25 -20.8 -6.8 2 671 + 673 3 336.95 -20.8 -8.7 2.5 672 + 674 3 343.25 -18.7 -6.5 1.25 673 + 675 3 346.95 -18.1 -1 1.75 674 + 676 3 347.45 -19.2 -1.1 1.5 675 + 677 3 347.45 -14.6 -2.8 1.75 676 + 678 3 351.55 -13.5 -4 1.25 677 + 679 3 353.95 -13 -1.8 1.25 678 + 680 3 356.45 -13.5 -1.5 1.25 679 + 681 3 358.85 -14.9 -1.2 1.5 680 + 682 3 360.65 -16.5 -1.3 1.75 681 + 683 3 363.55 -17.2 -1.2 2 682 + 684 3 366.95 -14 -0.5 1.25 683 + 685 3 369.05 -15.5 -2.4 1.25 684 + 686 3 370.75 -13.9 -4.1 2 685 + 687 3 374.55 -14.4 -3.7 1.5 686 + 688 3 376.65 -16.8 -3.9 1.75 687 + 689 3 376.05 -17.7 -6.7 1.75 688 + 690 3 379.15 -17.7 -8.2 1.5 689 + 691 3 381.25 -19 -4.5 1.25 690 + 692 3 383.55 -21.2 -7.1 1 691 + 693 3 385.75 -25.5 -6.6 1.5 692 + 694 3 386.75 -27.2 -2.3 1.5 693 + 695 3 389.65 -30.3 -3.7 1.75 694 + 696 3 388.55 -28.7 -4.5 1.75 695 + 697 3 390.95 -30.9 -4.4 1.5 696 + 698 3 393.85 -31 -1.6 1.5 697 + 699 3 395.65 -32.5 -0.8 1.5 698 + 700 3 399.15 -31.4 -4.9 1 699 + 701 3 402.55 -34.4 -8.6 1 700 + 702 3 404.25 -36.6 -6.8 0.75 701 + 703 3 405.65 -37.8 -8.4 1 702 + 704 3 408.05 -39.3 -9.1 1 703 + 705 3 410.35 -40.7 -7.5 1.25 704 + 706 3 407.85 -42.3 -7.5 0.75 705 + 707 3 407.15 -43.3 -7.1 0.75 706 + 708 3 408.45 -47.2 -8.4 0.75 707 + 709 3 411.35 -49.6 -5.4 0.75 708 + 710 3 412.45 -51 -7.3 0.75 709 + 711 3 411.95 -51.1 -5.5 1 710 + 712 3 415.55 -52.5 -4.3 0.75 711 + 713 3 418.25 -54.2 -7.4 0.75 712 + 714 3 419.45 -53 -11.8 0.75 713 + 715 3 421.75 -54.3 -11.2 0.75 714 + 716 3 424.45 -54.7 -10.7 0.75 715 + 717 3 427.15 -54.7 -14.7 0.75 716 + 718 3 428.85 -59.3 -18.5 0.5 717 + 719 3 426.75 -61.1 -18.5 0.5 718 + 720 3 430.65 -64.9 -18.5 0.5 719 + 721 3 424.75 -61.6 -17.1 0.5 719 + 722 3 422.45 -57.7 -18.3 0.5 717 + 723 3 420.85 -59.4 -16.1 0.5 722 + 724 3 421.15 -54.9 -13.4 0.25 722 + 725 3 416.45 -49.4 -12.4 0.5 714 + 726 3 420.05 -57 -12.8 0.5 713 + 727 3 421.95 -58.5 -8.6 0.5 726 + 728 3 411.95 -55.1 -3.2 0.5 711 + 729 3 414.75 -58.6 -5 0.5 728 + 730 3 411.45 -60.7 -5 0.5 729 + 731 3 409.95 -62.3 -5 0.5 730 + 732 3 414.05 -62.4 -1.8 0.5 730 + 733 3 410.25 -54.5 -3.2 0.5 728 + 734 3 414.45 -48.6 -10.7 0.5 710 + 735 3 407.55 -47.2 -8.9 0.5 708 + 736 3 405.35 -41.8 -7.6 0.25 707 + 737 3 412.85 -41.9 -12.9 0.75 705 + 738 3 415.75 -40.9 -16.6 0.75 737 + 739 3 416.35 -43 -18.2 0.75 738 + 740 3 418.65 -46.8 -17.5 0.5 739 + 741 3 420.35 -47.8 -12.8 0.5 740 + 742 3 422.65 -48.6 -12.8 0.5 741 + 743 3 420.95 -50.8 -14.3 0.5 741 + 744 3 420.05 -44.2 -13.7 0.5 740 + 745 3 414.05 -46 -18.2 0.5 739 + 746 3 409.75 -44.6 -12.9 0.5 737 + 747 3 412.75 -46.2 -15.3 0.5 746 + 748 3 403.05 -41.5 -9.9 0.5 703 + 749 3 403.95 -44.1 -9.3 0.5 748 + 750 3 403.95 -46 -9.3 0.5 749 + 751 3 400.65 -42.9 -9.3 0.5 749 + 752 3 400.55 -39.7 -9.9 0.5 748 + 753 3 399.95 -29.8 -8.7 0.5 700 + 754 3 401.65 -32.2 -11.2 0.5 753 + 755 3 404.65 -33.4 -12 0.5 754 + 756 3 397.85 -28.4 -8.7 0.5 753 + 757 3 400.45 -30.1 -10 0.5 756 + 758 3 396.45 -27.5 -10.8 0.5 756 + 759 3 396.15 -35 -2.6 0.75 699 + 760 3 397.05 -37.2 -0.6 0.75 759 + 761 3 398.25 -39.7 1.3 0.75 760 + 762 3 397.75 -45.1 -1.7 0.75 761 + 763 3 399.95 -48.5 2.2 0.75 762 + 764 3 403.45 -50.5 3.6 1 763 + 765 3 404.85 -52.4 -2.2 1 764 + 766 3 405.75 -54.6 2.1 0.75 765 + 767 3 403.95 -57.7 2.2 0.75 766 + 768 3 402.75 -60.8 0.4 0.5 767 + 769 3 402.95 -61.8 0.9 0.5 768 + 770 3 405.45 -62.1 0.4 0.5 768 + 771 3 402.45 -55.9 2.2 0.5 767 + 772 3 401.15 -53.5 -2.8 0.5 765 + 773 3 399.15 -51.8 0.1 0.5 772 + 774 3 397.45 -52.9 -2.7 0.5 773 + 775 3 399.15 -49.7 -0.6 0.5 773 + 776 3 401.15 -56.2 -2.8 0.25 772 + 777 3 397.35 -49.5 2.2 0.25 763 + 778 3 394.95 -43.4 0.7 0.5 761 + 779 3 391.65 -45.5 5.3 0.5 778 + 780 3 397.65 -45.5 0.7 0.25 778 + 781 3 393.85 -38.8 -5.7 0.5 760 + 782 3 392.45 -38.2 -5.7 0.5 781 + 783 3 392.05 -35.4 -1.4 0.75 759 + 784 3 390.25 -33.2 -0.7 0.75 696 + 785 3 391.45 -34.6 -0.1 0.75 784 + 786 3 393.05 -37.9 -2.1 0.75 785 + 787 3 392.35 -41.1 -4 0.75 786 + 788 3 392.35 -42.8 -2.3 0.75 787 + 789 3 393.35 -45.9 -2.3 0.75 788 + 790 3 391.05 -48 1.7 0.75 789 + 791 3 391.05 -49.6 1.7 0.75 790 + 792 3 394.25 -49.2 1.7 0.75 791 + 793 3 391.55 -52.4 -2.3 0.75 792 + 794 3 394.55 -56 -2.3 0.75 793 + 795 3 393.85 -55.8 -2.2 0.75 794 + 796 3 398.15 -58.3 4.7 0.5 795 + 797 3 402.15 -59.9 4.6 0.5 796 + 798 3 395.45 -60.1 6.4 0.5 796 + 799 3 394.15 -61.8 5.4 0.5 798 + 800 3 392.75 -62.6 5.4 0.5 799 + 801 3 393.45 -58.9 4.8 0.5 798 + 802 3 393.85 -58.2 1.5 0.5 795 + 803 3 391.25 -55.3 2 0.5 794 + 804 3 388.45 -53.4 2 0.25 803 + 805 3 389.95 -57.8 2 0.25 803 + 806 3 395.25 -51.5 2.2 0.5 792 + 807 3 397.05 -53 2.2 0.5 806 + 808 3 389.55 -49.6 1.7 0.25 791 + 809 3 395.75 -43.1 2 0.5 789 + 810 3 389.05 -44.7 -5 0.5 788 + 811 3 387.55 -32.9 -0.1 0.5 785 + 812 3 385.45 -32.7 0.7 0.75 811 + 813 3 390.05 -37 -3.8 0.5 811 + 814 3 384.85 -30.3 -9 0.5 695 + 815 3 384.65 -33.1 -9 0.5 814 + 816 3 384.05 -29.2 -9 0.5 814 + 817 3 383.45 -29.8 -6 0.5 694 + 818 3 380.15 -24.9 -5.6 0.5 692 + 819 3 380.15 -26.7 -6.7 0.5 818 + 820 3 380.65 -28 -6.7 0.5 819 + 821 3 380.65 -30.9 -5.2 0.5 820 + 822 3 382.15 -33.3 -5.6 0.5 821 + 823 3 377.75 -29.5 -5.2 0.25 821 + 824 3 378.15 -25.7 -6.7 0.5 820 + 825 3 384.35 -28.4 -8.3 0.5 819 + 826 3 376.05 -21.3 -4.5 0.5 690 + 827 3 376.45 -22.1 -9.8 0.5 826 + 828 3 380.25 -26 -9.9 0.5 827 + 829 3 381.35 -29.9 -6.4 0.5 828 + 830 3 382.95 -32.5 -6.4 0.5 829 + 831 3 374.35 -21.6 -9.8 0.5 827 + 832 3 372.55 -27 -6.3 0.5 831 + 833 3 380.25 -12.9 -11.5 0.5 689 + 834 3 371.15 -11.2 -9.5 0.5 687 + 835 3 369.25 -9.5 -9.5 0.5 834 + 836 3 367.95 -7.9 -9.5 0.5 835 + 837 3 367.95 -12.3 -9.5 0.5 835 + 838 3 372.75 -18.1 -3.8 1.25 686 + 839 3 373.75 -19.6 -1.6 1 838 + 840 3 375.05 -21.9 -3.4 1 839 + 841 3 375.95 -24.2 -3.8 1.25 840 + 842 3 374.05 -27 -2.3 1 841 + 843 3 377.35 -30.1 -0.5 1.25 842 + 844 3 380.55 -29 3.8 0.75 843 + 845 3 383.55 -32.6 2.9 0.75 844 + 846 3 385.65 -36.2 1.9 0.75 845 + 847 3 388.05 -39.8 -3.8 0.75 846 + 848 3 389.65 -43.4 -3 0.75 847 + 849 3 392.85 -47.5 -0.2 0.75 848 + 850 3 392.15 -46.5 1.8 0.5 849 + 851 3 395.25 -49.8 1.8 0.5 850 + 852 3 397.45 -52 2.1 0.5 851 + 853 3 389.85 -48.5 1.8 0.5 850 + 854 3 380.95 -38.2 -0.2 0.5 846 + 855 3 379.45 -40.9 3.4 0.5 854 + 856 3 380.65 -43 -0.1 0.5 855 + 857 3 379.15 -48.1 1.1 0.5 856 + 858 3 375.55 -50.5 1.1 0.5 857 + 859 3 383.15 -50 1.1 0.5 857 + 860 3 382.95 -44.5 -0.1 0.5 856 + 861 3 377.95 -40.9 -0.8 0.5 855 + 862 3 375.75 -36.2 -0.8 0.5 861 + 863 3 379.85 -34.2 0.2 0.5 845 + 864 3 375.75 -32.8 4 0.75 843 + 865 3 380.35 -35.5 1.2 0.75 864 + 866 3 382.75 -37.2 4.5 0.75 865 + 867 3 384.95 -41 5.6 0.75 866 + 868 3 384.35 -42.3 5.5 0.75 867 + 869 3 386.05 -46.6 2.2 0.75 868 + 870 3 386.65 -48.1 6.1 0.75 869 + 871 3 389.75 -51.1 4.4 0.75 870 + 872 3 393.35 -52.4 8.3 0.75 871 + 873 3 396.75 -54.1 5.7 0.75 872 + 874 3 402.05 -57.2 1.6 0.5 873 + 875 3 398.35 -56.6 5.7 0.5 873 + 876 3 394.45 -55.9 5.7 0.5 875 + 877 3 399.45 -58.2 3.7 0.5 875 + 878 3 393.35 -55.1 8.3 0.25 872 + 879 3 389.75 -53.1 9.3 0.5 871 + 880 3 389.75 -55.5 6.5 0.5 879 + 881 3 388.85 -57.7 6.1 0.5 880 + 882 3 392.35 -53.9 6.5 0.5 880 + 883 3 383.05 -49.7 -0.6 0.5 870 + 884 3 380.75 -44 1.1 0.5 868 + 885 3 379.15 -40.5 0.7 0.5 866 + 886 3 380.45 -42.7 3.7 0.5 885 + 887 3 380.25 -46 -0.6 0.5 886 + 888 3 380.25 -50.5 0 0.5 887 + 889 3 381.45 -52.2 1.2 0.5 888 + 890 3 377.95 -54.6 2.7 0.5 889 + 891 3 383.85 -53.2 5.8 0.5 889 + 892 3 385.25 -53.7 2.1 0.25 891 + 893 3 383.85 -55.8 5.8 0.5 891 + 894 3 375.35 -45.7 -0.8 0.5 887 + 895 3 372.95 -43.4 -0.8 0.5 894 + 896 3 373.25 -48 1.9 0.5 894 + 897 3 382.95 -44.2 2.7 0.5 886 + 898 3 378.85 -24.2 -0.3 0.75 841 + 899 3 381.85 -21 -3.2 0.75 898 + 900 3 383.05 -26.2 -1.9 0.5 899 + 901 3 382.85 -26.3 -8.2 0.5 900 + 902 3 386.95 -26.3 -9.5 0.5 901 + 903 3 389.45 -24.1 -9.5 0.5 902 + 904 3 388.25 -30.8 -9.5 0.5 902 + 905 3 382.65 -30.6 -9.4 0.5 901 + 906 3 384.65 -20 0.6 0.5 899 + 907 3 379.95 -28 -4.1 0.5 898 + 908 3 370.95 -21.9 -3.7 0.5 839 + 909 3 372.45 -25.6 -8 0.5 908 + 910 3 374.55 -22.6 -3.7 0.5 908 + 911 3 369.25 -19.5 -3.8 0.5 838 + 912 3 369.05 -20.1 -2.6 0.75 685 + 913 3 365.45 -24.6 0.1 0.75 912 + 914 3 369.65 -29.2 -7.5 0.5 913 + 915 3 374.15 -31.4 -5.9 0.5 914 + 916 3 375.75 -33.2 -1.8 0.5 915 + 917 3 379.65 -37.4 -0.5 0.5 916 + 918 3 381.15 -41.2 0.6 0.5 917 + 919 3 382.95 -44 1.9 0.5 918 + 920 3 382.25 -37.4 -6.1 0.5 917 + 921 3 367.65 -27.4 -2 0.25 913 + 922 3 361.75 -21.5 -1.3 1 683 + 923 3 364.85 -25.7 1.4 1 922 + 924 3 365.65 -28.1 4.8 1 923 + 925 3 367.25 -33.7 2.5 1 924 + 926 3 368.45 -37.4 3.6 0.75 925 + 927 3 368.45 -40.1 4.6 0.75 926 + 928 3 366.95 -43.2 0.2 0.5 927 + 929 3 370.25 -47 -1.8 0.5 928 + 930 3 373.05 -51.5 1.9 0.5 929 + 931 3 371.65 -37 5.8 0.5 927 + 932 3 369.65 -30.3 3.9 1 924 + 933 3 373.85 -30.3 2.8 0.75 932 + 934 3 379.45 -32.6 6.1 0.75 933 + 935 3 376.35 -37.2 6.2 0.5 933 + 936 3 376.15 -40.6 8.9 0.5 935 + 937 3 380.05 -43 5.4 0.5 936 + 938 3 372.95 -36 0.5 0.5 932 + 939 3 355.85 -18.9 0.9 0.5 681 + 940 3 357.75 -11.5 -5.2 0.5 680 + 941 3 351.15 -18.7 -2.4 0.75 677 + 942 3 351.75 -16.4 -2.9 0.5 941 + 943 3 355.65 -21.7 -5.2 0.5 942 + 944 3 357.35 -23.8 -6.6 0.5 943 + 945 3 351.95 -21 -2.3 0.5 941 + 946 3 352.75 -23.5 -1.7 0.5 945 + 947 3 349.15 -24.8 -1.7 0.5 946 + 948 3 348.25 -20.3 -2.3 0.25 945 + 949 3 342.85 -15.9 -9.2 0.5 676 + 950 3 348.35 -20.3 -0.8 0.25 675 + 951 3 341.95 -20.9 -6.6 0.75 673 + 952 3 344.45 -23.4 -4 1 951 + 953 3 345.85 -23.4 -4 0.75 952 + 954 3 347.35 -24.2 -7.7 0.75 953 + 955 3 348.95 -25.9 -3.4 1 954 + 956 3 351.15 -26.7 -5 1 955 + 957 3 351.85 -27.3 -5.7 1 956 + 958 3 350.05 -25.9 -1.8 1 957 + 959 3 354.35 -27.8 -1.8 1 958 + 960 3 358.05 -24.7 -2.8 1 959 + 961 3 361.45 -26.6 -8.5 0.5 960 + 962 3 362.55 -22.9 -8.3 0.5 961 + 963 3 362.85 -29.4 -3.8 0.5 961 + 964 3 358.85 -22.7 -6.9 0.5 960 + 965 3 358.85 -29.9 2.2 0.75 959 + 966 3 362.05 -29.2 2.7 0.5 965 + 967 3 363.75 -30.9 2.9 0.5 966 + 968 3 359.65 -31 0.9 0.5 965 + 969 3 362.45 -33.5 -0.3 0.5 968 + 970 3 363.95 -34.1 0.9 0.5 969 + 971 3 356.15 -32.4 0.9 0.5 968 + 972 3 354.45 -30.7 1.7 0.5 958 + 973 3 356.55 -31.6 0.1 0.5 972 + 974 3 359.05 -34.9 -0.3 0.5 973 + 975 3 362.05 -32.1 -1.9 0.5 974 + 976 3 364.35 -32.1 -1.9 0.5 975 + 977 3 361.85 -30 -1.9 0.5 975 + 978 3 359.95 -36.2 -0.3 0.25 974 + 979 3 357.45 -35.6 0.3 0.5 973 + 980 3 347.75 -29.2 -10.6 0.5 957 + 981 3 345.45 -31.1 -10.6 0.5 980 + 982 3 345.65 -26.3 -10.6 0.5 980 + 983 3 345.75 -26.9 -3.4 0.5 955 + 984 3 342.75 -25.9 -10.3 0.5 953 + 985 3 340.15 -28.1 -10.3 0.5 984 + 986 3 338.55 -24.9 -6.6 0.5 951 + 987 3 342.65 -23.7 -7.5 0.5 986 + 988 3 341.25 -26.3 -7.5 0.5 987 + 989 3 330.15 -26.9 -11.7 0.5 670 + 990 3 331.15 -28.7 -11.7 0.5 989 + 991 3 329.85 -30.6 -15.3 0.5 990 + 992 3 332.35 -29.3 -14.8 0.75 991 + 993 3 335.55 -28.6 -15 0.75 992 + 994 3 336.65 -25.9 -13.5 0.5 993 + 995 3 339.15 -28.8 -15.8 0.5 994 + 996 3 340.45 -30.3 -11.4 0.5 995 + 997 3 342.75 -26.8 -13.7 0.5 996 + 998 3 343.25 -27.4 -10.8 0.5 997 + 999 3 340.85 -31.2 -11.4 0.25 996 + 1000 3 337.15 -24.3 -13.5 0.5 994 + 1001 3 337.35 -31.9 -17 0.5 993 + 1002 3 337.95 -33.8 -19.1 0.5 1001 + 1003 3 338.65 -31.6 -17 0.25 1001 + 1004 3 333.55 -34.1 -16.2 0.5 992 + 1005 3 334.55 -35.8 -19.2 0.5 1004 + 1006 3 335.45 -40.1 -15.6 0.5 1005 + 1007 3 333.65 -44.1 -17.5 0.5 1006 + 1008 3 335.95 -46.9 -16.7 0.5 1007 + 1009 3 338.25 -49.3 -16.1 0.25 1008 + 1010 3 333.15 -49.1 -16.7 0.5 1008 + 1011 3 337.65 -41.3 -14.3 0.5 1006 + 1012 3 330.65 -36.3 -15.1 0.25 1005 + 1013 3 328.35 -32.4 -15 0.5 991 + 1014 3 328.25 -29.7 -11.7 0.25 990 + 1015 3 324.55 -24.9 -11.5 0.25 669 + 1016 3 323.55 -18.6 -19.1 0.5 665 + 1017 3 322.15 -20.8 -23.2 0.5 1016 + 1018 3 320.85 -23.6 -22.7 0.5 1017 + 1019 3 319.55 -19.4 -19.1 0.5 1016 + 1020 3 324.25 -9.1 -17.7 1 664 + 1021 3 326.15 -8.4 -18 1 1020 + 1022 3 328.25 -7.8 -16.3 1 1021 + 1023 3 327.45 -9.6 -13.8 1 1022 + 1024 3 330.55 -9.8 -12.3 1 1023 + 1025 3 334.25 -7.6 -11.7 1 1024 + 1026 3 334.35 -6.7 -13.6 1.25 1025 + 1027 3 336.15 -6.3 -13.3 1.25 1026 + 1028 3 337.75 -5.6 -10.1 1.25 1027 + 1029 3 339.35 -4.7 -10.1 1.25 1028 + 1030 3 340.65 -3.3 -10.9 1.25 1029 + 1031 3 339.75 -4.6 -9.8 1.25 1030 + 1032 3 344.05 -3.2 -11.7 1.25 1031 + 1033 3 345.55 -4.8 -10.1 1.25 1032 + 1034 3 347.75 -3.7 -7.1 1.25 1033 + 1035 3 348.95 -4.9 -7.4 1.25 1034 + 1036 3 350.25 -4 -8.6 1.25 1035 + 1037 3 352.35 -6.1 -5 1 1036 + 1038 3 355.05 -5.2 -7.4 1 1037 + 1039 3 356.15 -7.5 -7.4 1 1038 + 1040 3 359.05 -6.5 -8.2 0.75 1039 + 1041 3 361.55 -9.3 -7.7 0.75 1040 + 1042 3 364.65 -5.6 -6.3 0.5 1041 + 1043 3 366.95 -4.1 -7 0.5 1042 + 1044 3 363.45 -3.6 -11.8 0.5 1043 + 1045 3 367.95 -2.6 -11.1 0.5 1043 + 1046 3 366.85 -8.8 -7.9 0.25 1042 + 1047 3 368.85 -8 -7.9 0.25 1046 + 1048 3 363.15 -9 -5.2 0.5 1041 + 1049 3 358.15 -4.3 -10.5 0.5 1040 + 1050 3 358.65 -2.4 -10.5 0.25 1049 + 1051 3 361.25 -1.6 -10.5 0.25 1050 + 1052 3 356.45 -2.8 -10 0.5 1049 + 1053 3 357.85 -10.8 -10.4 0.5 1039 + 1054 3 355.95 -13.8 -15 0.5 1053 + 1055 3 358.85 -17.1 -15 0.5 1054 + 1056 3 354.85 -15.3 -10 0.5 1054 + 1057 3 360.05 -12.7 -7.3 0.5 1053 + 1058 3 362.85 -14.2 -7.3 0.5 1057 + 1059 3 353.45 -10.1 -9.9 0.5 1037 + 1060 3 349.95 -3.4 -5.3 0.5 1036 + 1061 3 354.45 -2.4 -5.8 0.5 1060 + 1062 3 348.75 0.8 -4.8 0.5 1060 + 1063 3 352.05 1.2 -4.8 0.5 1062 + 1064 3 350.55 2.6 -4.8 0.5 1062 + 1065 3 348.15 -7.7 -11.7 0.5 1035 + 1066 3 349.55 -10.5 -11.7 0.5 1065 + 1067 3 351.25 -8.8 -10.6 0.5 1065 + 1068 3 345.55 -8.4 -12.4 0.5 1033 + 1069 3 342.75 -7 -12.1 0.5 1031 + 1070 3 340.65 -1.1 -14.6 0.5 1030 + 1071 3 342.95 0.5 -11.2 0.5 1070 + 1072 3 338.45 -0.1 -11.9 0.25 1070 + 1073 3 337.85 -10.7 -16.8 0.5 1027 + 1074 3 336.95 -10.7 -11.3 0.5 1026 + 1075 3 336.95 -12.3 -15.8 0.5 1074 + 1076 3 333.55 -14.3 -15.8 0.5 1075 + 1077 3 335.55 -13.8 -12.2 0.5 1075 + 1078 3 334.85 -11.1 -11.7 0.25 1025 + 1079 3 331.95 -12.6 -20.1 0.5 1024 + 1080 3 325.95 -5.2 -13.8 0.5 1023 + 1081 3 322.55 -8.2 -24.2 0.5 663 + 1082 3 325.35 -11.8 -24.2 0.5 1081 + 1083 3 324.75 -5.9 -26.4 0.5 1081 + 1084 3 316.95 -15.7 -24.8 0.5 662 + 1085 3 315.55 -18.8 -22.8 0.5 1084 + 1086 3 320.55 -17.3 -24.8 0.25 1084 + 1087 3 310.45 -11 -24 0.5 167 + 1088 3 314.15 -1.6 -31.4 0.5 166 + 1089 3 311.15 0.4 -34.3 0.5 1088 + 1090 3 312.35 1.1 -34.3 0.5 1089 + 1091 3 308.75 3.7 -34.3 0.5 1090 + 1092 3 308.55 -2 -31.7 0.5 1090 + 1093 3 307.45 -10.6 -34.4 0.5 165 + 1094 3 307.45 -12 -34.4 0.5 1093 + 1095 3 310.75 -13.9 -34.2 0.5 1094 + 1096 3 312.55 -15.1 -33.9 0.5 1095 + 1097 3 312.25 -19.9 -32.1 0.5 1096 + 1098 3 308.95 -18.7 -28.4 0.5 1097 + 1099 3 305.05 -17.4 -30.6 0.5 1098 + 1100 3 302.05 -16.7 -31.2 0.5 1099 + 1101 3 300.35 -14.7 -31.9 0.5 1100 + 1102 3 300.25 -17.3 -32 0.5 1100 + 1103 3 305.05 -15.2 -30.6 0.5 1099 + 1104 3 306.85 -23.8 -28.4 0.5 1098 + 1105 3 313.85 -18.3 -32.4 0.5 1096 + 1106 3 315.35 -18.4 -28.7 0.5 1105 + 1107 3 317.25 -17.7 -29.5 0.5 1106 + 1108 3 317.05 -16.2 -29.5 0.5 1107 + 1109 3 319.35 -20.5 -29.5 0.5 1107 + 1110 3 315.35 -19.9 -33.9 0.5 1106 + 1111 3 310.55 -20.6 -30 0.5 1105 + 1112 3 307.55 -15 -34.2 0.25 1095 + 1113 3 305.95 -12.9 -34.4 0.25 1094 + 1114 3 303.55 -2.7 -32.8 0.5 164 + 1115 3 303.55 1.1 -32.9 0.5 1114 + 1116 3 300.05 2.7 -30.2 0.5 1115 + 1117 3 300.05 4.6 -30.2 0.5 1116 + 1118 3 301.75 6.3 -28.3 0.5 1117 + 1119 3 303.85 9.3 -32.2 0.5 1118 + 1120 3 304.95 13.7 -31.3 0.5 1119 + 1121 3 306.65 16.4 -32.5 0.5 1120 + 1122 3 308.85 18.1 -32.5 0.25 1121 + 1123 3 309.75 12.8 -34.5 0.5 1121 + 1124 3 305.55 9.6 -32.3 0.5 1119 + 1125 3 308.65 7.5 -29.9 0.5 1124 + 1126 3 312.85 10.7 -29.6 0.5 1125 + 1127 3 312.85 12.2 -25.9 0.5 1126 + 1128 3 316.55 13.5 -26.8 0.5 1127 + 1129 3 319.75 11.7 -26.8 0.5 1128 + 1130 3 316.55 15.3 -31.6 0.5 1128 + 1131 3 310.35 14.8 -25.9 0.5 1127 + 1132 3 315.25 7.3 -29.1 0.5 1126 + 1133 3 318.45 8.2 -29.6 0.5 1132 + 1134 3 316.35 4.6 -29.1 0.5 1132 + 1135 3 310.05 5.4 -32.2 0.5 1125 + 1136 3 306.65 5.6 -33.2 0.25 1124 + 1137 3 308.15 4 -33.2 0.25 1136 + 1138 3 305.55 5.8 -28.3 0.5 1118 + 1139 3 306.05 1.3 -34.5 0.5 1138 + 1140 3 307.25 4.2 -29.3 0.25 1138 + 1141 3 300.05 4.6 -31.1 0.5 1117 + 1142 3 295.95 3 -31.1 0.5 1141 + 1143 3 296.65 6.2 -31.1 0.5 1141 + 1144 3 300.25 -2 -34.9 0.5 163 + 1145 3 300.55 0.7 -34.9 0.5 1144 + 1146 3 296.05 -0.3 -34.9 0.5 1144 + 1147 3 298.55 -12.6 -36.3 0.5 162 + 1148 3 300.45 -14.5 -29.2 0.5 1147 + 1149 3 305.25 -17 -28 0.5 1148 + 1150 3 305.95 -19.1 -28 0.5 1149 + 1151 3 305.95 -13.4 -28 0.25 1149 + 1152 3 299.55 -17.7 -37.2 0.5 1148 + 1153 3 299.55 -19.2 -37.2 0.5 1152 + 1154 3 298.35 -21.7 -34.2 0.5 1153 + 1155 3 304.75 -19.9 -37.2 0.5 1153 + 1156 3 305.45 -21.3 -34.4 0.5 1155 + 1157 3 305.75 -17.8 -37.2 0.25 1155 + 1158 3 295.55 -13.7 -32.4 0.5 161 + 1159 3 296.95 -16 -35.6 0.5 1158 + 1160 3 292.55 -1.5 -36.9 0.25 160 + 1161 3 291.85 -14.6 -38.4 0.5 159 + 1162 3 291.85 -18.5 -41.1 0.5 1161 + 1163 3 294.95 -18.5 -37.4 0.5 1162 + 1164 3 291.45 -24 -36.5 0.5 1163 + 1165 3 296.45 -20.6 -37.3 0.25 1163 + 1166 3 289.65 -20.5 -42.1 0.5 1162 + 1167 3 292.25 -23.6 -39.5 0.5 1166 + 1168 3 293.05 -25.3 -42.5 0.5 1167 + 1169 3 287.75 -21.5 -39.5 0.25 1166 + 1170 3 290.05 -14.4 -47.5 0.5 158 + 1171 3 290.95 -14.4 -46.7 0.5 1170 + 1172 3 287.25 -17.8 -48 0.5 1171 + 1173 3 292.45 -16.3 -46.7 0.25 1171 + 1174 3 286.25 -15.1 -47.5 0.25 1170 + 1175 3 282.05 -4.6 -48.6 0.5 157 + 1176 3 282.65 -1.5 -49.7 0.5 1175 + 1177 3 278.45 -5.3 -49.7 0.5 1176 + 1178 3 282.65 0.6 -48.5 0.5 1176 + 1179 3 281.95 -15.9 -44.9 0.5 155 + 1180 3 280.35 -6.3 -55.2 0.5 154 + 1181 3 281.25 -4.6 -56.8 0.5 1180 + 1182 3 275.65 -3.3 -55.2 0.5 1180 + 1183 3 274.95 -0.2 -56.3 0.5 1182 + 1184 3 274.45 -3.3 -56 0.25 1182 + 1185 3 277.75 -18.6 -57 0.5 152 + 1186 3 280.95 -20.3 -57 0.5 1185 + 1187 3 282.95 -23.3 -56.5 0.5 1186 + 1188 3 284.85 -21.9 -52.6 0.25 1187 + 1189 3 279.65 -24.7 -58.2 0.5 1187 + 1190 3 278.45 -21.4 -57 0.25 1186 + 1191 3 277.15 -19.5 -55.5 0.5 151 + 1192 3 279.05 -20.3 -55.5 0.5 1191 + 1193 3 278.35 -21.5 -50.8 1.25 149 + 1194 3 278.45 -23 -48.9 1.25 1193 + 1195 3 280.05 -25.5 -51.9 1.25 1194 + 1196 3 284.05 -23.5 -46.2 1.25 1195 + 1197 3 285.05 -26.2 -42.8 1.25 1196 + 1198 3 287.95 -28 -42.6 1.75 1197 + 1199 3 289.45 -26.9 -43.9 1.75 1198 + 1200 3 290.95 -32.1 -39.8 1.75 1199 + 1201 3 290.95 -29.4 -44.2 1.5 1200 + 1202 3 294.35 -31.5 -44.2 1.25 1201 + 1203 3 295.85 -31.1 -41.4 1.25 1202 + 1204 3 299.25 -28 -40.4 1.5 1203 + 1205 3 301.05 -27.4 -39.1 1.5 1204 + 1206 3 303.75 -30.8 -35.1 1.75 1205 + 1207 3 306.15 -33.2 -32.1 1.5 1206 + 1208 3 307.95 -34 -32.4 1 1207 + 1209 3 309.75 -35.6 -31.4 0.75 1208 + 1210 3 308.45 -35.9 -31.3 1.25 1209 + 1211 3 311.85 -36.2 -28.3 1.25 1210 + 1212 3 313.85 -36.2 -29.2 1.5 1211 + 1213 3 312.15 -34.6 -25.9 1.5 1212 + 1214 3 312.55 -36.1 -27.4 1.25 1213 + 1215 3 316.55 -35.6 -23.2 1 1214 + 1216 3 319.35 -33.3 -24.7 1 1215 + 1217 3 320.95 -32.4 -21.8 1.5 1216 + 1218 3 321.95 -31.9 -21.8 1.5 1217 + 1219 3 325.15 -32.9 -23.5 1.25 1218 + 1220 3 324.45 -32.4 -21.4 1.5 1219 + 1221 3 329.65 -30.6 -21.9 1.25 1220 + 1222 3 332.55 -32.5 -16.9 1.25 1221 + 1223 3 333.85 -33.3 -19.3 1.5 1222 + 1224 3 336.85 -35.8 -15.4 1.5 1223 + 1225 3 338.85 -37.9 -16.8 1.5 1224 + 1226 3 341.85 -38.2 -14.7 1.5 1225 + 1227 3 341.95 -37.5 -10 1 1226 + 1228 3 346.25 -36.2 -9.6 0.75 1227 + 1229 3 349.45 -36.2 -7 1.25 1228 + 1230 3 351.35 -36.9 -8.7 1.25 1229 + 1231 3 354.45 -36 -4.6 0.75 1230 + 1232 3 357.45 -34.5 -6.2 0.75 1231 + 1233 3 358.85 -37.5 -6.7 0.5 1232 + 1234 3 361.55 -39.6 -1.5 0.5 1233 + 1235 3 362.55 -41.6 -1.5 0.5 1234 + 1236 3 365.05 -40.8 2.5 0.5 1235 + 1237 3 365.95 -42.9 2.5 0.5 1236 + 1238 3 368.25 -41.9 2.5 0.5 1237 + 1239 3 364.45 -44.3 2.5 0.5 1237 + 1240 3 361.95 -44.8 -2.7 0.5 1235 + 1241 3 363.75 -45.9 -2.7 0.25 1240 + 1242 3 363.15 -36.8 -1.5 0.5 1234 + 1243 3 360.85 -35.8 -2 0.25 1233 + 1244 3 355.65 -38.7 -7.3 0.5 1231 + 1245 3 352.35 -38.6 -8.7 0.75 1230 + 1246 3 354.85 -40.4 -7.6 0.5 1245 + 1247 3 355.05 -42.8 -4.4 0.75 1246 + 1248 3 359.45 -45.8 -2.1 0.75 1247 + 1249 3 364.15 -49.6 0.2 0.5 1248 + 1250 3 365.95 -55.1 3.9 0.5 1249 + 1251 3 370.25 -56.3 -0.3 0.5 1250 + 1252 3 367.35 -60.7 2.5 0.5 1251 + 1253 3 366.95 -64.8 4.7 0.5 1252 + 1254 3 365.15 -62.2 -0.4 0.5 1252 + 1255 3 367.15 -59.4 1.9 0.5 1250 + 1256 3 369.35 -61.1 4.5 0.5 1255 + 1257 3 364.95 -61.4 3.7 0.5 1255 + 1258 3 365.15 -54.7 -1.1 0.5 1249 + 1259 3 362.35 -57.5 0.4 0.5 1258 + 1260 3 356.35 -49.4 0.5 0.5 1248 + 1261 3 359.05 -52.1 0.5 0.5 1260 + 1262 3 360.65 -53.9 0.5 0.5 1261 + 1263 3 352.15 -46.1 -11.3 0.5 1247 + 1264 3 354.35 -50.1 -5 0.5 1263 + 1265 3 355.35 -53.4 -3.3 0.5 1264 + 1266 3 353.45 -57.2 -3.2 0.5 1265 + 1267 3 355.65 -61 -6.4 0.5 1266 + 1268 3 351.65 -57.2 -3.2 0.25 1266 + 1269 3 356.35 -55.8 -3.3 0.5 1265 + 1270 3 355.85 -46.8 -11.3 0.25 1263 + 1271 3 351.55 -44.5 -12.3 0.5 1246 + 1272 3 351.55 -47.2 -12.3 0.5 1271 + 1273 3 349.55 -41.7 -8.4 0.5 1245 + 1274 3 350.15 -44.9 -10 0.5 1273 + 1275 3 349.45 -48.3 -14.8 0.5 1274 + 1276 3 347.05 -45.6 -10 0.25 1274 + 1277 3 347.55 -42.8 -7.8 0.25 1273 + 1278 3 350.85 -32.9 -8.1 0.5 1229 + 1279 3 340.55 -41.8 -12.9 0.5 1226 + 1280 3 345.55 -42.1 -9 0.75 1279 + 1281 3 344.55 -43.9 -7.8 1 1280 + 1282 3 348.75 -45.7 -6.6 1 1281 + 1283 3 349.25 -47.4 -4.1 0.75 1282 + 1284 3 350.05 -49.2 -2.9 0.5 1283 + 1285 3 353.25 -50.9 -5.6 0.5 1284 + 1286 3 354.75 -49.2 -5.6 0.5 1285 + 1287 3 357.75 -51.7 -0.5 0.5 1286 + 1288 3 360.35 -54.4 -1.4 0.5 1287 + 1289 3 355.65 -47.3 0 0.25 1286 + 1290 3 350.05 -50.6 -1.5 0.5 1284 + 1291 3 351.75 -52.3 -1 0.5 1290 + 1292 3 353.55 -55.6 -4 0.5 1291 + 1293 3 352.25 -57.2 -3.2 0.5 1292 + 1294 3 355.55 -60.3 -4.8 0.5 1293 + 1295 3 352.15 -61.5 -3.5 0.5 1294 + 1296 3 355.85 -65.9 -3.7 0.5 1295 + 1297 3 359.75 -66.6 -3.8 0.5 1296 + 1298 3 360.75 -64.5 -3.8 0.25 1297 + 1299 3 361.05 -68.8 -3.8 0.25 1297 + 1300 3 355.85 -68.9 -0.9 0.5 1296 + 1301 3 356.75 -62.8 -3.5 0.25 1295 + 1302 3 358.35 -61.1 -1.8 0.5 1294 + 1303 3 360.95 -57.6 -6.5 0.5 1302 + 1304 3 360.05 -60.5 -1.8 0.25 1302 + 1305 3 353.05 -58.6 -8 0.25 1293 + 1306 3 350.35 -60.6 -8 0.25 1305 + 1307 3 349.95 -57.6 -8 0.25 1305 + 1308 3 355.65 -53.2 -4 0.5 1292 + 1309 3 346.55 -50.6 -1.7 0.5 1290 + 1310 3 349.65 -54.6 -3.9 0.5 1309 + 1311 3 348.25 -58.2 -6.6 0.5 1310 + 1312 3 348.25 -61.1 -8.3 0.5 1311 + 1313 3 345.55 -48.3 -4.1 0.5 1283 + 1314 3 344.95 -47.5 -11.6 0.5 1282 + 1315 3 341.15 -51.6 -7.5 0.5 1314 + 1316 3 344.95 -53.7 -8.8 0.5 1315 + 1317 3 339.85 -49.8 -7.5 0.25 1315 + 1318 3 340.55 -43.3 -12.8 0.5 1279 + 1319 3 344.05 -45.7 -12.8 0.5 1318 + 1320 3 340.15 -42 -17.4 0.5 1225 + 1321 3 336.85 -47.7 -15.7 0.5 1320 + 1322 3 340.35 -51.5 -13.4 0.5 1321 + 1323 3 340.35 -54.5 -11.2 0.5 1322 + 1324 3 342.75 -56.2 -14.4 0.5 1323 + 1325 3 340.35 -56.4 -9.9 0.5 1323 + 1326 3 336.25 -57.8 -9.9 0.5 1325 + 1327 3 337.35 -50.7 -12.5 0.5 1321 + 1328 3 333.65 -52.5 -18.6 0.5 1327 + 1329 3 335.25 -55 -13.3 0.5 1328 + 1330 3 335.25 -57.9 -16.4 0.5 1329 + 1331 3 336.45 -62 -12 0.5 1330 + 1332 3 339.55 -66.1 -11.8 0.5 1331 + 1333 3 338.55 -72.3 -13.2 0.5 1332 + 1334 3 337.05 -75.6 -8.3 0.5 1333 + 1335 3 341.15 -76.7 -8.3 0.5 1334 + 1336 3 341.05 -72.3 -13.2 0.5 1333 + 1337 3 335.05 -67.5 -13 0.25 1332 + 1338 3 331.75 -65.6 -15.1 0.25 1331 + 1339 3 332.35 -67 -15.1 0.25 1338 + 1340 3 331.75 -49.9 -18.6 0.5 1328 + 1341 3 335.15 -44.3 -22.3 0.5 1320 + 1342 3 332.75 -45.6 -22.3 0.5 1341 + 1343 3 336.85 -38.3 -25.1 0.5 1224 + 1344 3 331.85 -40.9 -26.3 0.5 1343 + 1345 3 335.65 -43.3 -23.9 0.5 1344 + 1346 3 332.85 -46.3 -22.3 0.5 1345 + 1347 3 335.65 -50.3 -26.6 0.5 1346 + 1348 3 336.45 -51.8 -26.6 0.5 1347 + 1349 3 330.65 -46.3 -22.3 0.25 1346 + 1350 3 330.35 -40.9 -26.3 0.5 1344 + 1351 3 335.15 -28.9 -16.1 0.25 1223 + 1352 3 337.05 -27.5 -16.1 0.25 1351 + 1353 3 336.15 -31.5 -16.1 0.25 1351 + 1354 3 332.55 -35.7 -22.9 0.5 1222 + 1355 3 328.55 -27.4 -19.6 0.75 1221 + 1356 3 332.15 -26.4 -20.6 0.75 1355 + 1357 3 334.05 -28.5 -20.1 0.25 1356 + 1358 3 329.45 -24.7 -20.6 0.5 1356 + 1359 3 324.45 -36.9 -18.2 0.5 1220 + 1360 3 328.45 -38.8 -18.2 0.5 1359 + 1361 3 330.15 -41.1 -21.4 0.5 1360 + 1362 3 322.45 -38.4 -18.6 0.5 1359 + 1363 3 323.65 -39.2 -25.9 0.5 1218 + 1364 3 324.25 -41.5 -25.9 0.5 1363 + 1365 3 325.15 -43.8 -24.5 0.5 1364 + 1366 3 326.15 -47 -24.2 0.5 1365 + 1367 3 327.05 -50 -22.8 0.5 1366 + 1368 3 328.45 -54.1 -22.8 0.5 1367 + 1369 3 330.65 -56 -22.9 0.5 1368 + 1370 3 327.75 -51.2 -17 0.5 1369 + 1371 3 327.75 -47.9 -19 0.5 1370 + 1372 3 331.55 -51.2 -17 0.25 1370 + 1373 3 331.95 -57.4 -19.9 0.25 1369 + 1374 3 328.45 -56.6 -27.5 0.25 1368 + 1375 3 329.55 -58.3 -27.5 0.25 1374 + 1376 3 324.25 -57.5 -27.5 0.25 1374 + 1377 3 319.55 -39.2 -26 0.5 1363 + 1378 3 319.35 -38.9 -28.8 0.5 1215 + 1379 3 321.25 -39.7 -31.2 0.5 1378 + 1380 3 316.15 -40.1 -25.1 0.5 1214 + 1381 3 316.15 -41.3 -28.3 0.5 1380 + 1382 3 317.65 -45.1 -31.1 0.5 1381 + 1383 3 318.35 -49.5 -33.6 0.5 1382 + 1384 3 318.35 -52.7 -31 0.5 1383 + 1385 3 317.65 -55.7 -31.9 0.5 1384 + 1386 3 318.55 -59.3 -31.4 0.5 1385 + 1387 3 320.35 -61.1 -32.1 0.5 1386 + 1388 3 320.15 -54.6 -30.7 0.25 1384 + 1389 3 318.35 -56.1 -30.7 0.25 1388 + 1390 3 321.15 -57.9 -33.8 0.25 1389 + 1391 3 321.45 -54.6 -30.7 0.25 1388 + 1392 3 314.65 -49.5 -33.6 0.5 1383 + 1393 3 313.25 -51.2 -36.1 0.5 1392 + 1394 3 313.45 -45.4 -32.6 0.25 1392 + 1395 3 320.15 -48.1 -29.9 0.5 1382 + 1396 3 312.45 -40.1 -30.9 0.5 1381 + 1397 3 315.05 -31.2 -27.6 0.5 1213 + 1398 3 312.95 -29.6 -31.5 0.5 1397 + 1399 3 318.85 -29.5 -33.4 0.5 1398 + 1400 3 321.75 -31.5 -33.3 0.5 1399 + 1401 3 322.55 -33.3 -33.3 0.5 1400 + 1402 3 318.85 -34.2 -33.4 0.5 1399 + 1403 3 312.95 -25.8 -33 0.5 1398 + 1404 3 318.45 -22.3 -34.2 0.5 1403 + 1405 3 314.15 -24 -33.6 0.25 1403 + 1406 3 316.15 -40.3 -32.8 0.5 1212 + 1407 3 318.75 -42.6 -35.5 0.5 1406 + 1408 3 311.95 -41.8 -35.8 0.5 1406 + 1409 3 311.35 -32.6 -38.6 0.5 1210 + 1410 3 306.85 -29.3 -41.4 0.5 1409 + 1411 3 307.75 -25.5 -38.9 0.5 1410 + 1412 3 307.75 -23.1 -38.5 0.5 1411 + 1413 3 310.55 -21 -38.5 0.5 1412 + 1414 3 308.35 -19.1 -37.8 0.5 1413 + 1415 3 311.95 -17.7 -40.7 0.5 1414 + 1416 3 306.65 -17 -41.7 0.25 1414 + 1417 3 312.75 -21 -37.8 0.5 1413 + 1418 3 314.25 -24.2 -39.3 0.5 1417 + 1419 3 310.45 -25.8 -39.3 0.25 1418 + 1420 3 315.15 -24.2 -39.3 0.25 1418 + 1421 3 314.05 -20.1 -37.8 0.25 1417 + 1422 3 306.45 -23.1 -38.5 0.25 1412 + 1423 3 311.85 -25.5 -38.9 0.5 1411 + 1424 3 304.95 -26.4 -41.1 0.5 1410 + 1425 3 306.05 -37.7 -37.3 0.5 1209 + 1426 3 306.15 -36.3 -36 0.5 1207 + 1427 3 306.15 -39.2 -32.3 0.5 1426 + 1428 3 307.75 -39.2 -34 0.75 1427 + 1429 3 307.75 -42 -31.7 0.75 1428 + 1430 3 308.35 -44.9 -33 0.5 1429 + 1431 3 310.45 -49.3 -32 0.5 1430 + 1432 3 310.45 -51.2 -32 0.5 1431 + 1433 3 307.75 -54.2 -32 0.5 1432 + 1434 3 311.45 -52.3 -37.8 0.5 1433 + 1435 3 310.85 -55.8 -28.4 0.5 1433 + 1436 3 313.05 -60.9 -33.7 0.5 1435 + 1437 3 313.55 -65 -33.1 0.5 1436 + 1438 3 314.65 -68.3 -33.1 0.5 1437 + 1439 3 312.95 -69.8 -26.1 0.5 1438 + 1440 3 311.25 -71.7 -28.2 0.5 1439 + 1441 3 316.65 -73.3 -24.6 0.5 1440 + 1442 3 318.95 -76.8 -24.6 0.5 1441 + 1443 3 315.55 -75.3 -30.3 0.25 1440 + 1444 3 315.45 -60.9 -34 0.5 1436 + 1445 3 305.65 -55.8 -33.5 0.25 1435 + 1446 3 312.45 -53.1 -29.6 0.25 1432 + 1447 3 308.35 -49.1 -35.5 0.5 1430 + 1448 3 308.35 -53.4 -36.9 0.5 1447 + 1449 3 308.35 -54.3 -36.9 0.5 1448 + 1450 3 311.45 -58.3 -37.9 0.5 1449 + 1451 3 305.45 -55.8 -37.3 0.25 1449 + 1452 3 309.95 -43 -26.9 0.5 1429 + 1453 3 311.05 -43 -28.1 0.5 1452 + 1454 3 313.95 -44.7 -26.4 0.5 1453 + 1455 3 313.95 -47.3 -23.5 0.5 1454 + 1456 3 313.65 -49.1 -25 0.5 1455 + 1457 3 319.85 -48.3 -22.3 0.5 1456 + 1458 3 320.15 -50.7 -19.9 0.75 1457 + 1459 3 325.25 -51.5 -16.8 0.75 1458 + 1460 3 327.35 -51.5 -20.9 0.5 1459 + 1461 3 327.35 -54.9 -15 0.5 1460 + 1462 3 331.25 -56 -18 0.5 1461 + 1463 3 333.75 -58.3 -18 0.5 1462 + 1464 3 332.05 -53.3 -18 0.5 1462 + 1465 3 328.85 -50.6 -14.3 0.5 1460 + 1466 3 326.95 -46.2 -19.6 0.5 1465 + 1467 3 330.35 -50.6 -14.3 0.25 1465 + 1468 3 325.25 -56.4 -19.2 0.5 1459 + 1469 3 325.25 -59.8 -20.4 0.5 1468 + 1470 3 322.95 -63.4 -21.8 0.5 1469 + 1471 3 320.65 -65.5 -21.8 0.5 1470 + 1472 3 327.65 -65.2 -18.8 0.5 1470 + 1473 3 327.15 -59.8 -19.5 0.5 1469 + 1474 3 319.85 -53.8 -23.7 0.5 1457 + 1475 3 317.85 -56 -23.7 0.5 1474 + 1476 3 315.75 -60.9 -23 0.5 1475 + 1477 3 317.65 -65.8 -27.1 0.5 1476 + 1478 3 319.05 -68.1 -28.7 0.5 1477 + 1479 3 321.05 -69.7 -25.2 0.5 1478 + 1480 3 320.65 -64.3 -25.5 0.25 1478 + 1481 3 319.95 -62.3 -23 0.25 1476 + 1482 3 321.35 -59.1 -22.4 0.5 1475 + 1483 3 313.65 -51 -25 0.25 1456 + 1484 3 313.95 -51.4 -25.6 0.5 1455 + 1485 3 312.55 -39 -28.1 0.25 1453 + 1486 3 303.05 -40.4 -32.3 0.25 1427 + 1487 3 305.35 -26.6 -38.5 0.5 1206 + 1488 3 297.55 -23.7 -38.1 0.5 1205 + 1489 3 295.85 -20.5 -36.2 0.25 1488 + 1490 3 298.35 -19.4 -36.2 0.25 1489 + 1491 3 293.65 -17.7 -37.1 0.25 1490 + 1492 3 294.95 -20.5 -40.4 0.25 1489 + 1493 3 300.75 -32.9 -37 0.5 1204 + 1494 3 301.95 -34.7 -38 0.5 1493 + 1495 3 301.95 -36.7 -38 0.5 1494 + 1496 3 300.15 -39.4 -36.9 0.5 1495 + 1497 3 302.55 -41.1 -38.7 0.5 1496 + 1498 3 296.85 -40.6 -36.9 0.5 1495 + 1499 3 300.85 -43.8 -39.5 0.25 1498 + 1500 3 295.95 -41.5 -36.9 0.25 1498 + 1501 3 298.35 -34.7 -38 0.25 1494 + 1502 3 294.95 -34.1 -45.8 0.25 1203 + 1503 3 296.25 -26 -41.1 0.25 1202 + 1504 3 288.35 -35.7 -42.5 0.5 1200 + 1505 3 293.25 -39.6 -41.8 0.5 1504 + 1506 3 294.65 -40.3 -41.8 0.5 1505 + 1507 3 295.45 -41.2 -40.7 0.5 1506 + 1508 3 292.25 -43.9 -40.5 0.5 1507 + 1509 3 292.25 -46.5 -38.1 0.5 1508 + 1510 3 299.05 -49 -37.2 0.5 1509 + 1511 3 298.25 -52.6 -39.7 0.5 1510 + 1512 3 302.55 -56.4 -38.1 0.5 1511 + 1513 3 303.45 -58.6 -40.4 0.5 1512 + 1514 3 304.35 -61.5 -41.3 0.5 1513 + 1515 3 302.65 -62.1 -35.7 0.5 1514 + 1516 3 303.75 -69.2 -35.7 0.5 1515 + 1517 3 304.45 -73 -36 0.5 1516 + 1518 3 302.25 -74.5 -37.9 0.5 1517 + 1519 3 302.35 -78.6 -35.7 0.5 1518 + 1520 3 300.85 -79.9 -35.7 0.5 1519 + 1521 3 305.35 -80.5 -35.7 0.5 1520 + 1522 3 299.45 -80.4 -35.7 0.25 1520 + 1523 3 305.85 -81.5 -34.4 0.5 1519 + 1524 3 307.95 -73.3 -33.7 0.5 1517 + 1525 3 297.05 -62.1 -38.1 0.5 1515 + 1526 3 297.05 -70 -35.2 0.5 1525 + 1527 3 308.75 -63.9 -39.7 0.5 1514 + 1528 3 298.25 -57.2 -38.1 0.25 1512 + 1529 3 302.25 -59.7 -37.7 0.25 1528 + 1530 3 299.95 -57.2 -37.1 0.25 1528 + 1531 3 299.45 -52.6 -35.7 0.5 1511 + 1532 3 295.95 -49.8 -35.7 0.5 1531 + 1533 3 295.25 -53.6 -35.7 0.5 1531 + 1534 3 301.85 -44.2 -39.1 0.5 1510 + 1535 3 303.05 -40.7 -36.7 0.5 1534 + 1536 3 304.05 -38.7 -34.8 0.5 1535 + 1537 3 306.15 -40.3 -38.4 0.5 1536 + 1538 3 301.05 -36.3 -34.8 0.25 1536 + 1539 3 297.45 -45.3 -37.6 0.25 1508 + 1540 3 295.85 -36 -42.7 0.5 1506 + 1541 3 295.45 -35.2 -40.1 0.5 1540 + 1542 3 297.15 -32.8 -43.8 0.5 1541 + 1543 3 291.75 -33.5 -40.1 0.25 1541 + 1544 3 289.95 -38.5 -39.3 0.5 1505 + 1545 3 290.75 -38.6 -40.9 0.5 1504 + 1546 3 286.75 -40 -42.6 0.5 1545 + 1547 3 284.25 -36.4 -42.6 0.25 1546 + 1548 3 284.85 -41.1 -42.6 0.5 1546 + 1549 3 291.35 -23.8 -44.3 0.5 1199 + 1550 3 291.35 -21.3 -44.4 0.5 1549 + 1551 3 287.35 -20.9 -43.6 0.25 1197 + 1552 3 284.05 -20.7 -50.7 0.5 1196 + 1553 3 284.05 -19.2 -50.7 0.5 1552 + 1554 3 280.85 -17.6 -52.4 0.5 1553 + 1555 3 278.35 -17.6 -52.4 0.5 1554 + 1556 3 279.75 -19.2 -50.7 0.25 1553 + 1557 3 277.95 -27.7 -52.7 0.5 1195 + 1558 3 282.15 -31.5 -51.2 0.5 1557 + 1559 3 280.25 -34.5 -55.6 0.5 1558 + 1560 3 280.25 -34.4 -58.9 0.5 1559 + 1561 3 285.55 -35.5 -59.4 0.5 1560 + 1562 3 278.25 -37.3 -55.6 0.25 1560 + 1563 3 277.15 -28.1 -56.5 0.25 1558 + 1564 3 275.15 -27.1 -57.4 0.25 1563 + 1565 3 280.05 -24.9 -55.8 0.25 1193 + 1566 3 271.35 -11.9 -65.5 0.5 148 + 1567 3 271.35 -9.4 -64 0.5 1566 + 1568 3 274.35 -7.5 -64 0.5 1567 + 1569 3 273.55 -24.3 -65.7 0.5 147 + 1570 3 272.25 -28.5 -63.2 0.5 1569 + 1571 3 275.45 -32.5 -61.3 0.5 1570 + 1572 3 277.45 -35.9 -64.1 0.5 1571 + 1573 3 277.45 -38.1 -66.4 0.5 1572 + 1574 3 279.75 -41.2 -66.6 0.25 1573 + 1575 3 273.85 -38.9 -66.4 0.25 1573 + 1576 3 271.05 -30.4 -64.8 0.5 1570 + 1577 3 269.15 -22.2 -65.7 0.25 1569 + 1578 3 268.55 -24.7 -69.8 0.5 145 + 1579 3 269.35 -26.5 -69.4 0.5 1578 + 1580 3 267.05 -28.4 -69.4 0.5 1579 + 1581 3 269.35 -29.8 -65.6 0.5 1580 + 1582 3 270.05 -32.7 -65.9 0.5 1581 + 1583 3 272.15 -36.5 -64.7 0.75 1582 + 1584 3 271.55 -39.5 -65 0.75 1583 + 1585 3 275.35 -43.6 -55.9 0.75 1584 + 1586 3 273.25 -47.8 -62.2 0.5 1585 + 1587 3 277.65 -51.3 -59.3 0.5 1586 + 1588 3 278.75 -55.2 -60.7 0.5 1587 + 1589 3 280.75 -55.2 -62.4 0.5 1588 + 1590 3 278.65 -58.9 -59.7 0.25 1589 + 1591 3 282.25 -55.2 -62.4 0.5 1589 + 1592 3 274.45 -56.7 -61.6 0.25 1588 + 1593 3 276.55 -59.1 -61.6 0.25 1592 + 1594 3 272.15 -50.4 -63.4 0.5 1586 + 1595 3 276.55 -43.6 -55.9 0.75 1585 + 1596 3 278.65 -42.9 -56.5 0.75 1595 + 1597 3 280.05 -44.7 -54.6 0.75 1596 + 1598 3 280.85 -46.5 -54.8 0.5 1597 + 1599 3 281.85 -48 -54.8 0.5 1598 + 1600 3 280.35 -50.2 -56.8 0.5 1599 + 1601 3 282.45 -53.1 -57.3 0.5 1600 + 1602 3 283.35 -56.1 -52.9 0.5 1601 + 1603 3 283.95 -57.4 -52.4 0.5 1602 + 1604 3 284.15 -58.4 -54 0.5 1603 + 1605 3 282.85 -61.5 -55.3 0.5 1604 + 1606 3 287.15 -63.9 -55 0.5 1605 + 1607 3 288.55 -67.3 -54.2 0.5 1606 + 1608 3 288.65 -62.1 -57 0.25 1606 + 1609 3 281.05 -63 -57.7 0.5 1605 + 1610 3 279.45 -64.9 -57.7 0.25 1609 + 1611 3 284.35 -64.4 -57.7 0.5 1609 + 1612 3 286.05 -59.2 -54 0.5 1604 + 1613 3 279.85 -57.4 -52.4 0.25 1603 + 1614 3 284.25 -50.2 -52.9 0.25 1600 + 1615 3 278.75 -48 -54.8 0.25 1599 + 1616 3 277.85 -46.5 -54.8 0.25 1598 + 1617 3 281.75 -41.7 -50.9 0.5 1597 + 1618 3 283.95 -44.4 -46.7 0.5 1617 + 1619 3 287.75 -45.7 -46.3 0.5 1618 + 1620 3 286.35 -50.9 -45.8 0.5 1619 + 1621 3 289.25 -52.3 -46 0.5 1620 + 1622 3 290.05 -56.7 -52 0.5 1621 + 1623 3 290.95 -61.2 -50 0.5 1622 + 1624 3 291.65 -63.3 -48.3 0.5 1623 + 1625 3 287.75 -60.4 -50 0.5 1623 + 1626 3 286.65 -59.1 -53.9 0.25 1622 + 1627 3 291.75 -53.6 -50.2 0.25 1621 + 1628 3 293.35 -55.7 -46.9 0.25 1627 + 1629 3 289.05 -55 -50.2 0.25 1627 + 1630 3 288.95 -43.9 -52.5 0.5 1619 + 1631 3 278.65 -40.8 -56.5 0.25 1596 + 1632 3 277.95 -47.8 -58.3 0.25 1595 + 1633 3 269.35 -42.8 -62.8 0.5 1584 + 1634 3 268.55 -46.4 -60.2 0.5 1633 + 1635 3 268.15 -41.6 -62.8 0.25 1633 + 1636 3 266.65 -35.2 -69.2 0.5 1582 + 1637 3 271.15 -29 -67.5 0.5 1581 + 1638 3 273.95 -26.8 -66.1 0.5 1637 + 1639 3 261.55 -29.6 -71.1 0.5 143 + 1640 3 263.45 -31 -71.7 0.5 1639 + 1641 3 258.45 -31 -71.4 0.5 1639 + 1642 3 256.75 -30.8 -75 0.5 141 + 1643 3 257.95 -30.8 -72.7 0.5 1642 + 1644 3 258.95 -35.3 -76.1 0.5 1643 + 1645 3 261.25 -38.7 -72.8 0.75 1644 + 1646 3 262.95 -38.8 -74.1 0.5 1645 + 1647 3 263.95 -41.7 -71 0.5 1646 + 1648 3 263.95 -43 -69.7 0.5 1647 + 1649 3 266.55 -44.9 -69.7 0.5 1648 + 1650 3 264.65 -47.2 -70.5 0.5 1649 + 1651 3 268.05 -50 -67.1 0.5 1650 + 1652 3 269.55 -50 -66 0.5 1651 + 1653 3 271.55 -53.8 -61.6 0.5 1652 + 1654 3 273.15 -55.2 -63.8 0.5 1653 + 1655 3 274.35 -60.2 -59.4 0.5 1654 + 1656 3 274.35 -62.4 -61.4 0.5 1655 + 1657 3 277.35 -65.9 -55.3 0.5 1656 + 1658 3 279.75 -68.5 -58.1 0.5 1657 + 1659 3 282.55 -68.5 -54.7 0.5 1658 + 1660 3 283.65 -72.4 -59.6 0.5 1659 + 1661 3 284.85 -75.2 -58.2 0.5 1660 + 1662 3 287.55 -77.2 -53.4 0.5 1661 + 1663 3 288.95 -79.2 -53.4 0.5 1662 + 1664 3 284.85 -79.3 -57.2 0.25 1661 + 1665 3 286.35 -81.9 -57.2 0.25 1664 + 1666 3 279.55 -72.4 -59.6 0.25 1660 + 1667 3 278.25 -74.6 -59.6 0.25 1666 + 1668 3 277.45 -70.8 -59.1 0.5 1658 + 1669 3 272.15 -64.9 -64.8 0.5 1656 + 1670 3 273.75 -66.2 -66.2 0.5 1669 + 1671 3 275.25 -70.3 -65.6 0.5 1670 + 1672 3 270.65 -68.9 -63 0.25 1670 + 1673 3 269.25 -64.9 -64.8 0.5 1669 + 1674 3 269.45 -56.9 -66.5 0.25 1654 + 1675 3 269.55 -48.7 -66 0.5 1652 + 1676 3 263.95 -51.3 -71.3 0.25 1651 + 1677 3 268.05 -54.2 -71.3 0.25 1676 + 1678 3 262.15 -51.3 -70.9 0.25 1676 + 1679 3 268.65 -42.2 -71.7 0.5 1649 + 1680 3 269.55 -40.6 -74.6 0.25 1679 + 1681 3 264.85 -38.4 -75.2 0.5 1647 + 1682 3 261.25 -41.6 -71.2 0.5 1645 + 1683 3 261.25 -43.9 -71.3 0.5 1682 + 1684 3 261.05 -48.3 -76.1 0.5 1683 + 1685 3 261.25 -45.6 -75.8 0.5 1683 + 1686 3 254.75 -36.3 -73 0.25 1644 + 1687 3 258.65 -29.4 -75.8 0.25 1643 + 1688 3 260.35 -31.4 -71.1 0.25 1687 + 1689 3 262.75 -32.8 -75 0.25 1688 + 1690 3 261.95 -28.2 -74.5 0.25 1688 + 1691 3 244.55 -28.3 -85.5 0.25 139 + 1692 3 243.05 -25.5 -85.5 0.25 1691 + 1693 3 247.45 -37.2 -82.6 0.5 138 + 1694 3 246.95 -37.2 -80.2 0.5 1693 + 1695 3 249.65 -39.2 -80.2 0.5 1694 + 1696 3 250.55 -43 -79.4 0.5 1695 + 1697 3 251.85 -46.7 -82.8 0.5 1696 + 1698 3 250.45 -49.4 -80.3 0.25 1697 + 1699 3 253.75 -47.5 -83.9 0.25 1697 + 1700 3 254.55 -48.7 -81.5 0.25 1699 + 1701 3 254.15 -45.1 -77.7 0.5 1696 + 1702 3 252.35 -46.1 -77.7 0.5 1701 + 1703 3 256.45 -47.9 -77.7 0.25 1702 + 1704 3 256.15 -45.1 -80.1 0.5 1701 + 1705 3 252.45 -40.2 -81.8 0.5 1695 + 1706 3 254.75 -42 -82.6 0.5 1705 + 1707 3 236.05 -36.7 -92.5 0.25 135 + 1708 3 239.15 -34 -94.5 0.25 1707 + 1709 3 240.75 -31.8 -91.5 0.25 1708 + 1710 3 242.65 -31 -91.5 0.25 1709 + 1711 3 238.05 -42.8 -86 0.75 134 + 1712 3 240.55 -42.8 -85.7 0.75 1711 + 1713 3 243.75 -42.8 -84.4 0.5 1712 + 1714 3 245.65 -44.2 -86.5 0.75 1713 + 1715 3 245.65 -48.3 -86.1 0.75 1714 + 1716 3 248.95 -51.4 -84.7 0.75 1715 + 1717 3 248.95 -52.6 -84.7 1 1716 + 1718 3 251.95 -54.5 -80.7 0.75 1717 + 1719 3 254.15 -54.5 -80 0.75 1718 + 1720 3 249.45 -61.2 -78.6 0.75 1719 + 1721 3 253.95 -63.1 -74 0.75 1720 + 1722 3 253.95 -67.1 -74 1 1721 + 1723 3 250.85 -69.3 -79.5 0.5 1722 + 1724 3 249.25 -72.4 -79.1 0.5 1723 + 1725 3 247.65 -76.1 -79.2 0.5 1724 + 1726 3 251.05 -80.9 -75.8 0.5 1725 + 1727 3 248.45 -86.6 -79.7 0.5 1726 + 1728 3 252.45 -90.2 -75.8 0.5 1727 + 1729 3 255.05 -95.6 -77.1 0.5 1728 + 1730 3 248.25 -92.6 -75.1 0.5 1728 + 1731 3 253.35 -83.6 -75.3 0.25 1726 + 1732 3 254.25 -86.2 -75.3 0.25 1731 + 1733 3 248.85 -66.8 -76.7 0.25 1723 + 1734 3 256.45 -69 -73.3 0.75 1722 + 1735 3 253.05 -71.7 -74.3 0.5 1734 + 1736 3 256.75 -73.4 -74.3 0.5 1735 + 1737 3 254.45 -76.4 -74 0.5 1736 + 1738 3 254.45 -78.5 -72.7 0.5 1737 + 1739 3 257.65 -81.6 -72.7 0.5 1738 + 1740 3 254.95 -79.8 -75.4 0.5 1738 + 1741 3 259.25 -74 -71.9 0.5 1736 + 1742 3 261.45 -75.3 -71.2 0.5 1741 + 1743 3 261.45 -79.8 -65.9 0.5 1742 + 1744 3 264.15 -82.6 -68.2 0.5 1743 + 1745 3 260.25 -71.1 -71.9 0.25 1741 + 1746 3 258.75 -69 -78.4 0.5 1734 + 1747 3 255.25 -53.3 -79 0.5 1719 + 1748 3 253.85 -52.1 -76.6 0.5 1747 + 1749 3 259.35 -54.6 -73.2 0.75 1748 + 1750 3 262.45 -53.1 -75.5 0.75 1749 + 1751 3 264.45 -57.1 -74.4 0.5 1750 + 1752 3 265.25 -57.1 -73.8 0.5 1751 + 1753 3 265.05 -58.6 -70.2 0.5 1752 + 1754 3 269.35 -63.7 -66.8 0.5 1753 + 1755 3 270.15 -66.3 -66.7 0.5 1754 + 1756 3 269.25 -68.9 -62.7 0.5 1755 + 1757 3 270.95 -70.8 -63.7 0.5 1756 + 1758 3 272.95 -70.7 -64.2 0.5 1757 + 1759 3 270.55 -72.3 -63 0.5 1758 + 1760 3 269.25 -75.9 -60.9 0.5 1759 + 1761 3 270.55 -78.1 -60.9 0.5 1760 + 1762 3 267.85 -82 -60.1 0.5 1761 + 1763 3 270.35 -86.1 -61.1 0.5 1762 + 1764 3 270.35 -88.6 -64.1 0.5 1763 + 1765 3 266.35 -90.5 -64.1 0.5 1764 + 1766 3 265.75 -82 -64.6 0.5 1762 + 1767 3 274.55 -81.1 -56.8 0.5 1761 + 1768 3 274.65 -85.4 -57.8 0.5 1767 + 1769 3 276.95 -77.5 -54.8 0.5 1767 + 1770 3 273.95 -73 -60.2 0.25 1759 + 1771 3 271.65 -67.7 -63.5 0.25 1758 + 1772 3 266.65 -72.9 -62.9 0.25 1756 + 1773 3 264.85 -63.7 -68 0.25 1754 + 1774 3 262.75 -58.3 -73.8 0.25 1752 + 1775 3 260.85 -56.8 -75 0.25 1749 + 1776 3 253.85 -49.4 -76.6 0.5 1748 + 1777 3 257.05 -56 -77.6 0.5 1747 + 1778 3 259.55 -58.3 -76 0.5 1777 + 1779 3 261.05 -61.8 -79.1 0.5 1778 + 1780 3 263.05 -64.7 -75 0.5 1779 + 1781 3 259.55 -61.5 -74.8 0.25 1778 + 1782 3 251.95 -56.5 -80.7 0.5 1718 + 1783 3 244.45 -56.6 -81 0.5 1717 + 1784 3 244.85 -60.3 -81.2 0.5 1783 + 1785 3 245.05 -65.9 -86.1 0.5 1784 + 1786 3 247.75 -68.7 -86.1 0.5 1785 + 1787 3 245.75 -66.8 -86.1 0.25 1785 + 1788 3 243.05 -62.6 -81.2 0.25 1784 + 1789 3 246.05 -41.4 -85.4 0.25 1713 + 1790 3 241.85 -45.8 -85.7 0.25 1712 + 1791 3 235.55 -38.1 -88.5 2.25 131 + 1792 3 237.35 -35.6 -88.1 2.25 1791 + 1793 3 239.55 -32.4 -83.9 2.5 1792 + 1794 3 241.85 -29.5 -86.3 2.25 1793 + 1795 3 241.25 -26.1 -85 2 1794 + 1796 3 243.35 -23.4 -83.5 2.25 1795 + 1797 3 246.65 -20.7 -82.8 2.25 1796 + 1798 3 248.55 -17 -83.3 2.5 1797 + 1799 3 249.65 -13.8 -79.5 2.75 1798 + 1800 3 249.65 -13.8 -69.2 2 1799 + 1801 3 250.45 -10.6 -68.4 2 1800 + 1802 3 254.15 -6.4 -65.8 1.25 1801 + 1803 3 251.95 -2.7 -64.5 1.75 1802 + 1804 3 255.55 -0.2 -63.9 1.75 1803 + 1805 3 256.45 2.7 -67.8 1.5 1804 + 1806 3 254.35 6 -65.1 2 1805 + 1807 3 254.35 10.8 -64.2 2.25 1806 + 1808 3 259.25 17.7 -58.6 2.25 1807 + 1809 3 257.15 20.2 -55.8 2 1808 + 1810 3 262.45 26.1 -54.3 2.25 1809 + 1811 3 262.45 26.1 -54.4 3 1810 + 1812 3 263.25 19.9 -54.4 1.75 1811 + 1813 3 263.25 22.1 -55.4 1.25 1812 + 1814 3 264.85 26 -57 1.75 1813 + 1815 3 264.85 27.6 -56.7 1.75 1814 + 1816 3 264.85 30.8 -56.5 1.5 1815 + 1817 3 264.85 34.3 -59.4 1.5 1816 + 1818 3 261.75 36.3 -58.9 1.25 1817 + 1819 3 261.45 37.8 -58.6 1.75 1818 + 1820 3 263.75 41 -55.1 1.75 1819 + 1821 3 263.75 43.3 -54 2 1820 + 1822 3 260.95 44.6 -56.4 2 1821 + 1823 3 263.05 45.7 -53.3 2 1822 + 1824 3 259.55 47.5 -54.7 1.75 1823 + 1825 3 259.55 50.8 -58.4 1.5 1824 + 1826 3 261.15 52.7 -57.3 2 1825 + 1827 3 261.55 55.5 -54.5 2 1826 + 1828 3 257.95 57.7 -55.5 1.75 1827 + 1829 3 257.75 61.7 -56.8 1.75 1828 + 1830 3 261.85 65.6 -53.4 1.75 1829 + 1831 3 263.65 67.6 -49.8 2 1830 + 1832 3 262.45 69.1 -50.4 2 1831 + 1833 3 265.75 72.2 -50 2.25 1832 + 1834 3 266.55 73.1 -50.3 2 1833 + 1835 3 267.45 77.4 -45.8 2.5 1834 + 1836 3 268.05 80 -45.4 3 1835 + 1837 3 278.55 78.3 -40.8 1.25 1836 + 1838 3 278.55 79.6 -40.8 1.25 1837 + 1839 3 279.65 83.1 -40.5 1.5 1838 + 1840 3 281.75 85.5 -39.1 1.75 1839 + 1841 3 279.65 86.7 -39.6 1.75 1840 + 1842 3 282.65 87.2 -39.8 1.75 1841 + 1843 3 280.35 89.4 -42.4 1.75 1842 + 1844 3 282.25 92.1 -43.5 1.75 1843 + 1845 3 279.15 92.2 -38.9 1.5 1844 + 1846 3 281.85 95.9 -42.8 1.5 1845 + 1847 3 280.65 97.6 -39.2 2 1846 + 1848 3 280.65 101.6 -39.1 2.25 1847 + 1849 3 282.95 103.5 -42.4 2.25 1848 + 1850 3 284.05 105.6 -42.3 2.25 1849 + 1851 3 284.05 106.9 -38.2 2.25 1850 + 1852 3 284.05 108.9 -41.8 2 1851 + 1853 3 285.55 110.5 -40.2 2 1852 + 1854 3 286.85 111.9 -42.2 2 1853 + 1855 3 287.65 112.2 -42 2 1854 + 1856 3 288.75 113.4 -39.7 1.75 1855 + 1857 3 290.75 114.4 -41.8 1.75 1856 + 1858 3 291.35 112 -42.2 1.75 1857 + 1859 3 293.15 114.4 -40.5 1.25 1858 + 1860 3 296.15 114.4 -42 1.75 1859 + 1861 3 297.15 111.6 -44.1 2 1860 + 1862 3 299.15 113.3 -41.4 1.5 1861 + 1863 3 301.25 110.4 -43.6 1.75 1862 + 1864 3 299.65 112.1 -42.5 1.75 1863 + 1865 3 304.05 112.4 -42.5 1.5 1864 + 1866 3 305.85 109.6 -42.9 1.75 1865 + 1867 3 306.95 110.4 -41.9 1.5 1866 + 1868 3 305.15 111.8 -40.6 1.25 1867 + 1869 3 308.85 113.2 -44.2 1.25 1868 + 1870 3 312.45 111.3 -44.7 1.25 1869 + 1871 3 315.35 113 -46.8 1.25 1870 + 1872 3 314.15 114.5 -48.4 1.25 1871 + 1873 3 317.15 114.4 -49 1.25 1872 + 1874 3 321.15 112.3 -55.5 1.25 1873 + 1875 3 326.45 115.4 -55.9 1 1874 + 1876 3 327.05 114.5 -59 1 1875 + 1877 3 329.25 115.8 -60.2 1 1876 + 1878 3 332.65 114.8 -68.7 1 1877 + 1879 3 333.35 115.7 -68 1 1878 + 1880 3 334.25 119.1 -68.4 1 1879 + 1881 3 337.75 121 -80.1 0.5 1880 + 1882 3 339.65 123.1 -80.1 0.5 1881 + 1883 3 334.55 122.2 -77.3 0.5 1881 + 1884 3 337.65 115.2 -68.9 0.5 1880 + 1885 3 338.55 115.6 -74.1 0.5 1884 + 1886 3 337.65 112.5 -68.9 0.5 1884 + 1887 3 339.05 110.5 -68.6 0.5 1886 + 1888 3 329.75 118.7 -69.1 0.5 1879 + 1889 3 330.95 121.1 -69.1 0.5 1888 + 1890 3 334.05 122.6 -69.2 0.5 1889 + 1891 3 328.05 122.4 -67.5 0.25 1889 + 1892 3 334.45 112.4 -63.1 0.5 1878 + 1893 3 335.65 110 -62.4 0.5 1892 + 1894 3 334.05 107.1 -68.6 0.5 1893 + 1895 3 339.55 108.2 -68.2 0.5 1894 + 1896 3 337.85 104.7 -68.6 0.5 1894 + 1897 3 338.15 109.3 -63.4 0.5 1893 + 1898 3 336.55 112.4 -64.1 0.5 1892 + 1899 3 331.65 110.2 -60.2 0.5 1877 + 1900 3 334.45 109.5 -64.1 0.5 1899 + 1901 3 333.45 108.1 -59.9 0.5 1899 + 1902 3 329.45 104.5 -59.9 0.5 1901 + 1903 3 333.65 103.4 -59.9 0.25 1902 + 1904 3 327.45 104.5 -59.9 0.5 1902 + 1905 3 335.05 106 -60.5 0.5 1901 + 1906 3 327.05 109.2 -64.7 0.5 1876 + 1907 3 330.45 107.1 -64.7 0.5 1906 + 1908 3 324.55 110.9 -64.7 0.25 1906 + 1909 3 318.75 110.5 -58.2 0.5 1874 + 1910 3 322.95 107.3 -59.5 0.25 1909 + 1911 3 324.75 105.9 -58.9 0.25 1910 + 1912 3 319.65 105.9 -59.5 0.25 1910 + 1913 3 316.55 107.8 -52.9 0.5 1909 + 1914 3 317.15 118.2 -56 1.25 1873 + 1915 3 319.95 119 -53 1 1914 + 1916 3 323.75 118.2 -60.6 1 1915 + 1917 3 325.55 124 -68.3 0.5 1916 + 1918 3 321.85 125.6 -68.3 0.5 1917 + 1919 3 326.55 125.9 -68.3 0.5 1918 + 1920 3 320.55 125.7 -68.3 0.25 1918 + 1921 3 326.65 120.8 -68.3 0.5 1917 + 1922 3 322.45 117.2 -60.6 0.75 1916 + 1923 3 327.35 115.8 -62.2 0.5 1922 + 1924 3 327.35 114 -61.2 0.5 1923 + 1925 3 328.25 119.2 -62.2 0.5 1923 + 1926 3 326.95 121.6 -59.7 0.5 1922 + 1927 3 330.15 120.2 -59.4 0.25 1926 + 1928 3 328.95 117.4 -59.7 0.5 1926 + 1929 3 324.05 115.2 -57.7 0.5 1915 + 1930 3 314.25 120 -56 0.5 1914 + 1931 3 309.65 115.6 -45.7 0.5 1872 + 1932 3 317.25 110 -50.2 0.5 1871 + 1933 3 314.15 108.8 -49.2 0.5 1870 + 1934 3 316.05 106.5 -48.7 0.5 1933 + 1935 3 318.25 108.5 -49.1 0.5 1934 + 1936 3 316.05 105.3 -48.7 0.25 1934 + 1937 3 314.15 105.6 -48.2 0.5 1933 + 1938 3 308.35 115.2 -45.7 0.5 1869 + 1939 3 310.05 117.3 -47.1 0.5 1938 + 1940 3 312.85 119.3 -49.9 0.75 1939 + 1941 3 314.25 120.7 -50.7 0.75 1940 + 1942 3 315.55 122.7 -51.2 0.75 1941 + 1943 3 315.55 124.2 -55.9 0.75 1942 + 1944 3 312.95 123.4 -60.5 0.75 1943 + 1945 3 312.95 127.4 -62.6 0.75 1944 + 1946 3 316.25 128.7 -59.1 0.75 1945 + 1947 3 316.75 125.9 -63.5 0.5 1946 + 1948 3 319.45 129.6 -64.3 0.5 1947 + 1949 3 319.15 124.6 -63.5 0.5 1947 + 1950 3 314.05 130.4 -63.9 0.5 1946 + 1951 3 311.45 130.4 -63.9 0.5 1950 + 1952 3 313.45 127.4 -60.8 0.25 1945 + 1953 3 317.75 121.7 -60.5 0.5 1944 + 1954 3 320.35 124.9 -61.4 0.5 1953 + 1955 3 318.85 120.3 -60.5 0.5 1953 + 1956 3 311.15 124.8 -55.9 0.5 1943 + 1957 3 312.75 116.8 -50.7 0.5 1941 + 1958 3 312.55 114.6 -47.1 0.5 1939 + 1959 3 310.15 107.5 -43.9 0.5 1867 + 1960 3 315.55 107.5 -44.3 0.5 1959 + 1961 3 319.15 104.1 -42.6 0.5 1960 + 1962 3 321.25 107.2 -44.5 0.5 1961 + 1963 3 320.45 102 -42.6 0.5 1961 + 1964 3 311.75 103.8 -44.7 0.5 1959 + 1965 3 314.35 104 -40.7 0.5 1964 + 1966 3 316.45 101.2 -40.7 0.5 1965 + 1967 3 308.45 103 -48.2 0.25 1964 + 1968 3 306.85 104.7 -40.7 0.5 1866 + 1969 3 303.45 103.1 -45.2 0.5 1968 + 1970 3 301.85 105.3 -45.2 0.5 1969 + 1971 3 300.95 103.8 -45.2 0.5 1970 + 1972 3 303.45 101.5 -42.6 0.5 1970 + 1973 3 304.05 101.4 -45.2 0.25 1969 + 1974 3 308.65 103.1 -40.7 0.5 1968 + 1975 3 302.55 115.4 -48.9 0.5 1864 + 1976 3 296.75 108.1 -45.3 0.5 1863 + 1977 3 300.75 115.9 -41.4 0.25 1862 + 1978 3 297.15 108.6 -46.8 0.5 1861 + 1979 3 297.15 105.9 -49 0.5 1978 + 1980 3 298.95 107.3 -50.1 0.5 1979 + 1981 3 292.95 104.3 -49 0.5 1979 + 1982 3 292.55 107.3 -47 0.5 1978 + 1983 3 296.75 117.2 -47.1 0.5 1860 + 1984 3 299.75 120.1 -47.3 0.75 1983 + 1985 3 297.75 117.7 -45.9 0.5 1984 + 1986 3 298.65 116 -46.9 0.5 1985 + 1987 3 303.55 116 -47 0.5 1986 + 1988 3 306.05 117.6 -47 0.5 1987 + 1989 3 303.55 114.4 -47 0.5 1987 + 1990 3 301.75 121.1 -45.9 0.5 1985 + 1991 3 296.15 121.2 -47.3 0.5 1984 + 1992 3 294.05 120.2 -47.3 0.5 1991 + 1993 3 296.15 122.8 -47.3 0.25 1991 + 1994 3 294.35 118.8 -48.5 0.5 1983 + 1995 3 291.35 118.1 -40.4 1.25 1858 + 1996 3 289.25 120.2 -43.3 1.5 1995 + 1997 3 289.25 122.2 -46.7 1.25 1996 + 1998 3 295.85 126 -46 1.25 1997 + 1999 3 296.35 127.7 -48.8 0.75 1998 + 2000 3 292.05 130 -48.8 0.75 1999 + 2001 3 291.75 132.3 -53.2 1 2000 + 2002 3 295.95 135.4 -57.5 0.75 2001 + 2003 3 296.85 136.3 -57.5 0.5 2002 + 2004 3 297.65 137.6 -57.5 0.5 2003 + 2005 3 298.35 133 -57.5 0.5 2003 + 2006 3 291.45 136.5 -53.7 0.5 2002 + 2007 3 287.95 132.3 -50.1 0.5 2001 + 2008 3 287.05 134.5 -50.1 0.5 2007 + 2009 3 286.35 129.4 -53.9 0.5 2007 + 2010 3 288.35 126 -53.1 0.5 2000 + 2011 3 300.15 131.1 -45.4 0.75 1999 + 2012 3 301.95 132.8 -44.7 0.75 2011 + 2013 3 298.25 126.5 -43.9 0.75 1998 + 2014 3 299.75 126.5 -48.6 0.75 2013 + 2015 3 302.05 126.5 -46.8 0.75 2014 + 2016 3 306.25 128.5 -51.1 0.75 2015 + 2017 3 308.15 127.3 -49.2 0.5 2016 + 2018 3 309.05 129.3 -49.2 0.5 2017 + 2019 3 309.65 125 -54 0.5 2017 + 2020 3 306.85 124.3 -50.7 0.5 2016 + 2021 3 307.95 126.1 -50.7 0.5 2020 + 2022 3 303.35 121.7 -50.7 0.5 2020 + 2023 3 303.05 121.3 -47.6 0.5 2015 + 2024 3 305.45 121 -49.2 0.5 2023 + 2025 3 300.45 122.1 -47.6 0.5 2023 + 2026 3 300.85 122.5 -48.6 0.5 2014 + 2027 3 290.85 123.5 -49.5 0.75 1997 + 2028 3 291.55 125.6 -51.9 0.5 2027 + 2029 3 289.55 127.6 -49 0.5 2028 + 2030 3 292.95 125.6 -49.3 0.5 2028 + 2031 3 286.05 123.5 -46.3 0.5 2027 + 2032 3 286.25 118.1 -46.8 0.5 1995 + 2033 3 292.55 110 -40.4 0.5 1857 + 2034 3 290.85 108.2 -44.7 0.5 1856 + 2035 3 289.25 108.4 -46.5 0.5 2034 + 2036 3 292.15 110.6 -44.7 0.5 2034 + 2037 3 282.45 114.6 -45 0.75 1854 + 2038 3 281.65 117.3 -44.4 0.5 2037 + 2039 3 284.65 120.3 -44.4 0.5 2038 + 2040 3 278.85 111.4 -42.1 0.5 2037 + 2041 3 276.85 109.7 -45.7 0.75 1852 + 2042 3 275.15 111.6 -48.4 0.5 2041 + 2043 3 273.85 105.8 -43.7 0.5 2041 + 2044 3 284.85 106.9 -44.2 0.5 1851 + 2045 3 289.45 107.9 -44.2 0.5 2044 + 2046 3 287.35 102.9 -44.2 0.5 2044 + 2047 3 277.65 106.5 -45 0.5 1850 + 2048 3 275.35 102.2 -42 0.5 2047 + 2049 3 275.45 101.6 -46.7 0.5 1848 + 2050 3 272.65 103.9 -46.7 0.5 2049 + 2051 3 274.65 106.7 -48.4 0.5 2050 + 2052 3 267.05 106.7 -48.4 0.5 2051 + 2053 3 266.15 103.4 -48.4 0.25 2052 + 2054 3 267.95 108.1 -48.4 0.5 2052 + 2055 3 275.75 100.4 -52 0.5 2050 + 2056 3 270.55 100.4 -52 0.5 2055 + 2057 3 268.05 104.9 -48.4 0.5 2056 + 2058 3 267.85 99.2 -52 0.5 2056 + 2059 3 266.25 99.2 -52 0.5 2058 + 2060 3 275.45 98.9 -51.4 0.5 2049 + 2061 3 277.25 94.8 -51.5 0.5 2060 + 2062 3 273.65 99.9 -51.4 0.25 2060 + 2063 3 285.05 95.9 -43.2 0.75 1846 + 2064 3 283.35 99.5 -42.7 1 2063 + 2065 3 287.85 100.8 -41.2 1 2064 + 2066 3 290.45 102.3 -37.9 0.75 2065 + 2067 3 291.55 103.5 -37.9 0.75 2066 + 2068 3 293.05 104.8 -38.7 0.75 2067 + 2069 3 293.05 105.9 -38.7 0.5 2068 + 2070 3 296.45 106.7 -38.3 0.75 2069 + 2071 3 297.45 107.7 -38.3 0.75 2070 + 2072 3 298.45 108 -38.8 0.75 2071 + 2073 3 299.95 109.5 -37.8 0.75 2072 + 2074 3 301.65 109.5 -38.1 0.5 2073 + 2075 3 303.45 107 -41.3 0.5 2074 + 2076 3 301.65 111.1 -43.5 0.5 2074 + 2077 3 299.95 104.8 -41.8 0.5 2072 + 2078 3 292.65 109.5 -42.4 0.75 2071 + 2079 3 296.45 102.7 -43.5 0.5 2070 + 2080 3 297.15 101 -45.8 0.5 2079 + 2081 3 297.95 100.5 -47.9 0.5 2080 + 2082 3 292.65 102.4 -43.5 0.5 2079 + 2083 3 290.95 107.5 -38.7 0.5 2069 + 2084 3 294.05 100.6 -41.8 0.5 2068 + 2085 3 294.05 99.2 -41.8 0.5 2084 + 2086 3 286.25 104.8 -37.9 0.5 2067 + 2087 3 284.65 107.1 -41.6 0.5 2086 + 2088 3 292.15 97.6 -37.9 0.5 2066 + 2089 3 293.35 96.4 -41.1 0.5 2088 + 2090 3 289.35 96.4 -41.2 0.5 2065 + 2091 3 290.35 95.5 -41.2 0.5 2090 + 2092 3 292.75 96.2 -41.2 0.5 2091 + 2093 3 291.55 94.6 -41.2 0.5 2091 + 2094 3 285.15 95.3 -40.4 0.5 2064 + 2095 3 285.15 94.4 -39.7 0.5 2094 + 2096 3 288.35 95.3 -40.4 0.25 2094 + 2097 3 276.75 92.2 -47.6 0.5 1845 + 2098 3 276.45 90.9 -47.6 0.5 2097 + 2099 3 275.45 95.7 -47.6 0.5 2097 + 2100 3 287.05 87.9 -43 0.5 1843 + 2101 3 290.35 91.1 -43.1 0.75 2100 + 2102 3 295.65 89.4 -42.4 0.5 2101 + 2103 3 297.45 87.6 -42.4 0.5 2102 + 2104 3 292.35 92.8 -40 0.5 2101 + 2105 3 294.85 95 -39.3 0.5 2104 + 2106 3 299.25 97.7 -43.4 0.5 2105 + 2107 3 301.75 101.1 -43.4 0.5 2106 + 2108 3 301.45 97.7 -43.4 0.5 2106 + 2109 3 302.55 97.7 -43.4 0.5 2108 + 2110 3 297.75 91.7 -42.9 0.5 2105 + 2111 3 285.25 86.7 -39.8 0.25 1842 + 2112 3 276.85 88.1 -44.3 0.5 1841 + 2113 3 280.15 90 -44.3 0.5 2112 + 2114 3 280.15 93.7 -47.3 0.5 2113 + 2115 3 275.25 88.1 -43.1 0.25 2112 + 2116 3 272.85 82.4 -46.5 0.5 1838 + 2117 3 274.85 84.2 -46.5 0.5 2116 + 2118 3 271.35 85.8 -47.8 0.5 2117 + 2119 3 270.25 80.9 -46.5 0.25 2117 + 2120 3 272.25 83.6 -40.9 1.5 1836 + 2121 3 273.45 85 -42 1.5 2120 + 2122 3 276.45 87.6 -40.8 1.75 2121 + 2123 3 277.55 86.8 -40.8 1 2122 + 2124 3 279.05 90.8 -42.9 1 2123 + 2125 3 282.75 92.8 -41.5 1 2124 + 2126 3 286.65 93.9 -40.3 1 2125 + 2127 3 288.85 92.5 -39.6 1 2126 + 2128 3 290.45 96.1 -36.4 1 2127 + 2129 3 292.35 92.5 -38.9 1 2128 + 2130 3 294.25 94.5 -36.2 1 2129 + 2131 3 295.95 96.7 -39.5 1 2130 + 2132 3 294.25 98.3 -37.5 0.75 2131 + 2133 3 295.05 100.1 -38.3 1 2132 + 2134 3 299.65 101.4 -35.5 1.25 2133 + 2135 3 298.35 102.6 -36.8 0.75 2134 + 2136 3 301.95 102.1 -39 1.25 2135 + 2137 3 303.35 104 -39.1 1.25 2136 + 2138 3 305.65 104.8 -36.4 1.25 2137 + 2139 3 307.55 106 -38.5 1 2138 + 2140 3 306.95 103 -38.6 1 2139 + 2141 3 312.95 104.4 -38.2 1.25 2140 + 2142 3 315.75 104.4 -37.9 0.75 2141 + 2143 3 318.65 105.6 -39.1 0.75 2142 + 2144 3 318.85 104.8 -37.5 0.75 2143 + 2145 3 319.95 105.3 -39.1 0.75 2144 + 2146 3 318.15 108.4 -35.7 0.75 2145 + 2147 3 323.25 109.4 -37.5 0.75 2146 + 2148 3 326.65 111 -42.1 0.5 2147 + 2149 3 329.75 113.9 -44.8 0.5 2148 + 2150 3 328.65 108.1 -43.6 0.5 2148 + 2151 3 325.35 106.2 -41.4 0.5 2147 + 2152 3 315.75 110 -37.5 0.5 2146 + 2153 3 322.25 102.3 -39.7 0.5 2145 + 2154 3 326.15 104.8 -39 0.5 2153 + 2155 3 327.55 105.9 -41.3 0.5 2154 + 2156 3 321.75 107.5 -39 0.5 2154 + 2157 3 323.95 98.1 -41.6 0.5 2153 + 2158 3 313.45 107.3 -39.8 0.5 2144 + 2159 3 320.45 100 -39.1 0.5 2143 + 2160 3 323.35 102.1 -40.3 0.5 2159 + 2161 3 320.45 98.9 -40.8 0.5 2159 + 2162 3 322.25 94.8 -41.8 0.5 2161 + 2163 3 317.65 98.5 -39.5 0.5 2142 + 2164 3 312.95 98.9 -37.5 0.5 2141 + 2165 3 310.95 98.6 -37.5 0.5 2164 + 2166 3 316.85 93.7 -36 0.5 2165 + 2167 3 319.05 92 -39.8 0.5 2166 + 2168 3 310.95 93.8 -39.4 0.5 2165 + 2169 3 315.35 92.3 -38.9 0.5 2168 + 2170 3 312.55 108.9 -39.5 0.5 2140 + 2171 3 315.65 109.7 -37.8 0.5 2170 + 2172 3 309.65 111.3 -37.1 0.5 2170 + 2173 3 304.15 108.1 -40.9 0.5 2139 + 2174 3 307.25 110 -42.3 0.5 2173 + 2175 3 308.25 111.4 -42.3 0.5 2174 + 2176 3 302.75 109.1 -42.3 0.5 2174 + 2177 3 301.15 107.1 -39.8 0.75 2138 + 2178 3 304.55 99.2 -41 0.5 2137 + 2179 3 303.85 97.3 -36.4 0.5 2178 + 2180 3 304.85 98 -37.3 0.5 2178 + 2181 3 301.45 97.3 -37.5 0.25 2134 + 2182 3 298.95 96.3 -37.5 0.25 2181 + 2183 3 293.45 102.1 -37.1 0.5 2133 + 2184 3 297.35 96.7 -41.3 0.5 2131 + 2185 3 298.15 92.1 -43.4 0.5 2184 + 2186 3 299.95 92.1 -45.2 0.5 2185 + 2187 3 300.95 96.6 -41 0.5 2186 + 2188 3 301.15 91.1 -45.2 0.25 2186 + 2189 3 298.55 97.4 -41.3 0.25 2184 + 2190 3 292.35 97.6 -36.4 0.25 2129 + 2191 3 292.85 98.4 -36.4 0.25 2190 + 2192 3 288.75 98.4 -36.3 0.25 2190 + 2193 3 293.05 94.7 -40.1 0.75 2128 + 2194 3 296.75 91.5 -36.8 0.5 2193 + 2195 3 299.55 94 -37.9 0.5 2194 + 2196 3 301.25 95.3 -39 0.5 2195 + 2197 3 302.45 96.3 -39.3 0.5 2196 + 2198 3 299.45 96.1 -39.3 0.5 2197 + 2199 3 302.65 97.7 -39.3 0.5 2198 + 2200 3 304.75 96.3 -40.7 0.5 2197 + 2201 3 301.45 89.3 -39.2 0.5 2195 + 2202 3 296.95 90.2 -36.7 0.25 2194 + 2203 3 293.05 90.9 -37 0.25 2193 + 2204 3 288.55 91.6 -43.5 0.25 2203 + 2205 3 294.55 89.4 -36.9 0.25 2203 + 2206 3 290.75 90.4 -40.9 0.5 2127 + 2207 3 287.95 89.7 -43.8 0.5 2126 + 2208 3 289.35 88 -46.1 0.5 2207 + 2209 3 290.95 89.6 -48.2 0.5 2208 + 2210 3 288.75 91 -48.2 0.5 2209 + 2211 3 291.75 86.7 -48.2 0.25 2209 + 2212 3 277.55 84.9 -38.3 1.5 2122 + 2213 3 281.85 86.1 -42 1.5 2212 + 2214 3 283.55 84.3 -38.6 1.75 2213 + 2215 3 285.15 86.9 -35.4 1.25 2214 + 2216 3 287.45 85.9 -35.3 1.25 2215 + 2217 3 288.35 85.2 -38.4 1.25 2216 + 2218 3 289.05 84.4 -34.1 1.25 2217 + 2219 3 290.65 85 -33.3 1 2218 + 2220 3 291.95 85 -32.7 1.25 2219 + 2221 3 295.05 86.4 -34.6 1 2220 + 2222 3 297.35 87.3 -35 1.25 2221 + 2223 3 299.35 88.9 -31.9 1.25 2222 + 2224 3 300.95 89.1 -33.3 1.25 2223 + 2225 3 302.85 91.7 -29.1 1.25 2224 + 2226 3 305.35 91 -29.3 1.25 2225 + 2227 3 306.25 92.3 -29.3 1.5 2226 + 2228 3 309.15 94.6 -30.4 1.25 2227 + 2229 3 309.85 96.1 -29.5 1 2228 + 2230 3 313.15 97.8 -33.5 1 2229 + 2231 3 311.15 99.1 -32.3 1 2230 + 2232 3 312.25 101.2 -35.1 1 2231 + 2233 3 317.65 103.1 -33 1.25 2232 + 2234 3 320.35 104.6 -36.9 1.25 2233 + 2235 3 321.85 106.3 -37.6 1.25 2234 + 2236 3 323.75 108.5 -42.4 1.25 2235 + 2237 3 327.15 112.1 -41.8 1.25 2236 + 2238 3 331.35 112.8 -45.4 1.25 2237 + 2239 3 332.85 112.8 -54 1 2238 + 2240 3 337.15 112.8 -55.7 0.5 2239 + 2241 3 341.35 111.3 -56.9 0.5 2240 + 2242 3 337.15 108.9 -55.7 0.5 2240 + 2243 3 330.65 118.3 -59 0.5 2239 + 2244 3 329.65 119.8 -59.2 0.5 2243 + 2245 3 327.95 116.1 -59 0.5 2243 + 2246 3 325.95 114.7 -49.8 0.5 2238 + 2247 3 324.95 116.4 -49.8 0.25 2246 + 2248 3 323.25 114.7 -49.8 0.5 2246 + 2249 3 327.15 113.5 -49.1 0.5 2237 + 2250 3 319.95 99.6 -38.7 0.5 2233 + 2251 3 315.25 98.2 -37.7 0.25 2232 + 2252 3 308.55 99.1 -34.8 0.5 2231 + 2253 3 316.35 97.8 -35.4 0.5 2230 + 2254 3 314.05 93.1 -33.3 0.5 2229 + 2255 3 314.05 91.9 -35.1 0.5 2254 + 2256 3 316.05 93.7 -32.9 0.5 2255 + 2257 3 317.75 96.3 -34.9 0.5 2256 + 2258 3 317.15 91 -32.9 0.25 2256 + 2259 3 314.05 90 -39.6 0.5 2255 + 2260 3 307.85 89.4 -31.7 0.5 2227 + 2261 3 310.45 89.8 -31.4 0.5 2260 + 2262 3 307.35 88.2 -28.4 0.25 2260 + 2263 3 300.95 94.3 -35 0.5 2224 + 2264 3 301.85 85.4 -32 0.25 2223 + 2265 3 302.55 83.7 -32 0.25 2264 + 2266 3 300.05 83.3 -36.7 0.5 2222 + 2267 3 297.95 84 -36 0.5 2266 + 2268 3 300.25 80.7 -39.4 0.5 2267 + 2269 3 297.95 78.9 -39.4 0.25 2268 + 2270 3 295.95 80.7 -36.3 0.5 2268 + 2271 3 302.65 84 -39.7 0.5 2267 + 2272 3 306.05 85 -38.5 0.5 2271 + 2273 3 304.45 80.2 -39.7 0.25 2271 + 2274 3 301.85 86 -37.9 0.25 2266 + 2275 3 292.25 87.9 -31.9 0.5 2221 + 2276 3 292.25 80.9 -34.1 0.5 2220 + 2277 3 295.85 82.4 -34.1 0.5 2276 + 2278 3 291.25 79.6 -34.1 0.5 2276 + 2279 3 290.95 89.1 -35.3 0.5 2218 + 2280 3 293.25 86.2 -35.8 0.5 2279 + 2281 3 292.05 90.4 -35.3 0.25 2279 + 2282 3 286.45 82.9 -43.4 0.5 2215 + 2283 3 286.45 82 -43.4 0.75 2282 + 2284 3 283.65 79.1 -44.3 0.5 2283 + 2285 3 282.85 77.4 -44.3 0.5 2284 + 2286 3 289.45 82 -40.1 0.25 2283 + 2287 3 283.25 88.5 -38.8 0.5 2213 + 2288 3 281.35 82.4 -43.5 0.5 2212 + 2289 3 282.75 81.1 -43.5 0.5 2288 + 2290 3 284.65 79.2 -41.3 0.5 2289 + 2291 3 282.55 80.3 -41.3 0.5 2290 + 2292 3 288.05 78.4 -47.4 0.25 2291 + 2293 3 281.25 76.2 -45.8 0.5 2291 + 2294 3 279.65 78.9 -39.4 0.25 2289 + 2295 3 275.15 80.4 -42.5 0.5 2121 + 2296 3 271.25 74.7 -47.1 0.5 1835 + 2297 3 269.75 72.6 -47.2 0.5 2296 + 2298 3 272.75 74.7 -47.1 0.5 2296 + 2299 3 261.45 74.7 -55.1 0.5 1834 + 2300 3 268.95 69.5 -44.4 0.5 1833 + 2301 3 272.45 72.1 -44.6 0.5 2300 + 2302 3 270.65 67.4 -48.1 0.5 2300 + 2303 3 259.85 72.2 -56.7 0.5 1832 + 2304 3 261.65 74.8 -54.5 0.5 2303 + 2305 3 261.65 76.9 -53.9 0.5 2304 + 2306 3 256.75 74.8 -57.1 0.5 2304 + 2307 3 256.85 72.2 -59.5 0.5 2303 + 2308 3 255.25 61.7 -60.6 0.5 1829 + 2309 3 256.85 63.1 -61.6 0.5 2308 + 2310 3 254.45 67.6 -62.2 0.5 2309 + 2311 3 258.25 71 -61.2 0.5 2310 + 2312 3 252.85 69.9 -61.5 0.5 2310 + 2313 3 253.05 58.3 -60.4 0.5 2308 + 2314 3 251.35 62.8 -66 0.5 2313 + 2315 3 253.05 64.5 -66 0.5 2314 + 2316 3 249.85 62.8 -66 0.5 2314 + 2317 3 250.75 57.3 -61 0.25 2313 + 2318 3 262.95 59.9 -55.5 0.5 1828 + 2319 3 265.35 61.3 -57.8 0.5 2318 + 2320 3 264.15 62.9 -55.2 0.5 2319 + 2321 3 264.15 63.8 -55.2 0.5 2320 + 2322 3 267.05 64.7 -55.2 0.5 2321 + 2323 3 268.65 66.1 -56.4 0.5 2322 + 2324 3 270.65 64.9 -54.2 0.5 2323 + 2325 3 268.65 67.5 -56.4 0.5 2323 + 2326 3 265.25 65.4 -53.2 0.25 2321 + 2327 3 267.95 60.7 -55.9 0.5 2320 + 2328 3 270.35 59.8 -55.9 0.5 2327 + 2329 3 267.05 57.8 -57.8 0.5 2319 + 2330 3 256.25 55.5 -61 0.5 1827 + 2331 3 255.85 55.6 -62.5 0.5 2330 + 2332 3 254.65 57.4 -62.5 0.5 2331 + 2333 3 253.75 54.3 -62.5 0.5 2331 + 2334 3 257.15 52 -62.6 0.25 2330 + 2335 3 256.25 50.8 -63 0.5 1825 + 2336 3 264.95 48.2 -52.7 0.5 1823 + 2337 3 263.55 50.9 -52.7 0.5 2336 + 2338 3 266.35 46.2 -52.7 0.5 2336 + 2339 3 258.05 39.7 -62.5 0.75 1822 + 2340 3 253.85 35.1 -60.1 0.75 2339 + 2341 3 251.15 33.2 -65.9 0.75 2340 + 2342 3 250.95 35.4 -63.9 0.5 2341 + 2343 3 245.35 36.7 -65.7 0.5 2342 + 2344 3 245.85 32.3 -63.9 0.5 2342 + 2345 3 249.55 28.1 -67.4 0.5 2341 + 2346 3 245.95 29.2 -69.6 0.5 2345 + 2347 3 244.45 32.2 -69.6 0.5 2346 + 2348 3 244.25 26.5 -71.7 0.5 2346 + 2349 3 251.85 26.3 -67.4 0.5 2345 + 2350 3 255.35 42.2 -64.5 0.5 2339 + 2351 3 266.45 43.3 -57.2 0.5 1821 + 2352 3 259.65 38.7 -62.3 0.5 1819 + 2353 3 257.65 38.7 -63 0.5 2352 + 2354 3 254.25 41.5 -60.4 0.5 2353 + 2355 3 252.45 41.9 -60.4 0.5 2354 + 2356 3 254.25 36.9 -65.7 0.5 2354 + 2357 3 259.65 41.9 -60.8 0.25 2352 + 2358 3 258.05 44.1 -64.1 0.25 2357 + 2359 3 259.85 46.3 -64.1 0.25 2358 + 2360 3 255.55 44.1 -64.5 0.25 2358 + 2361 3 259.65 36.3 -55.1 0.25 1818 + 2362 3 261.95 32.1 -62.3 0.5 1816 + 2363 3 257.05 33.1 -62.2 0.5 2362 + 2364 3 259.15 29.5 -61.6 0.25 2362 + 2365 3 260.25 23.6 -63.9 0.5 1813 + 2366 3 256.45 24.3 -63.9 0.5 2365 + 2367 3 258.15 26.6 -63.3 0.5 2366 + 2368 3 254.15 28.5 -66.2 0.5 2367 + 2369 3 254.15 20.3 -67.4 0.5 2366 + 2370 3 252.35 19.2 -66.3 0.5 2369 + 2371 3 255.35 16.3 -66.3 0.5 2370 + 2372 3 256.35 14.7 -66.3 0.5 2371 + 2373 3 250.45 19.2 -66.3 0.25 2370 + 2374 3 262.45 28.4 -53.2 2.75 1811 + 2375 3 265.35 30.7 -55.5 2 2374 + 2376 3 267.05 34.9 -53.2 2.5 2375 + 2377 3 265.85 34.9 -53.3 1.25 2376 + 2378 3 265.85 38.5 -54.7 1.25 2377 + 2379 3 268.25 41.3 -53 1.25 2378 + 2380 3 268.25 42.3 -50.4 1.25 2379 + 2381 3 266.45 45.8 -51.8 1.25 2380 + 2382 3 266.45 48.2 -49.9 1.25 2381 + 2383 3 266.45 51.3 -49.7 1.25 2382 + 2384 3 265.55 52.3 -51.7 1.25 2383 + 2385 3 265.55 55.2 -51.2 1.25 2384 + 2386 3 265.55 58.2 -49.5 1 2385 + 2387 3 265.65 60.6 -48.4 1.25 2386 + 2388 3 265.65 62.6 -48.6 1.5 2387 + 2389 3 264.55 66.6 -47.6 1.25 2388 + 2390 3 266.45 70.5 -47.2 1.25 2389 + 2391 3 265.15 76 -47.5 1.25 2390 + 2392 3 262.15 80.7 -45.4 1.5 2391 + 2393 3 260.75 82.6 -46.6 1.5 2392 + 2394 3 260.45 84.6 -43.1 1.25 2393 + 2395 3 262.25 89.4 -46.8 1.5 2394 + 2396 3 262.95 90.4 -47.5 1.75 2395 + 2397 3 259.85 92.5 -45 1.75 2396 + 2398 3 260.65 95.3 -42.8 1.75 2397 + 2399 3 262.85 97.7 -42.3 1.5 2398 + 2400 3 264.15 102.4 -45.1 1.5 2399 + 2401 3 263.05 104.4 -44.9 2 2400 + 2402 3 260.05 107.8 -45 0.75 2401 + 2403 3 256.05 108.5 -43.1 0.5 2402 + 2404 3 268.05 110.8 -46.4 1.25 2401 + 2405 3 268.65 112.5 -43.8 1 2404 + 2406 3 267.45 116.8 -43.1 0.75 2405 + 2407 3 269.85 121.2 -46.4 0.75 2406 + 2408 3 264.45 116.8 -43.1 0.25 2406 + 2409 3 272.15 115.9 -42.9 0.5 2405 + 2410 3 264.85 92.5 -48.2 0.5 2397 + 2411 3 257.85 90.4 -47.5 0.5 2396 + 2412 3 257.05 89.8 -47.5 0.5 2411 + 2413 3 255.45 92.2 -44.6 0.5 2412 + 2414 3 255.75 87.3 -47.5 0.5 2411 + 2415 3 264.95 85.7 -43.1 0.5 2394 + 2416 3 267.25 87 -45.4 0.5 2415 + 2417 3 267.05 82.2 -42.5 0.5 2415 + 2418 3 258.45 80.2 -46.5 0.5 2393 + 2419 3 268.85 71.6 -47.2 0.25 2390 + 2420 3 269.05 66.6 -46.8 0.5 2389 + 2421 3 268.85 68.4 -48.8 0.25 2420 + 2422 3 273.25 65.4 -48.8 0.25 2421 + 2423 3 272.15 69.6 -48.8 0.25 2421 + 2424 3 270.65 62.7 -45.5 0.5 2420 + 2425 3 262.85 62.6 -50.5 0.5 2388 + 2426 3 269.95 57.2 -47.3 0.5 2386 + 2427 3 271.85 54.3 -47.5 0.5 2426 + 2428 3 263.85 55.2 -51.2 0.5 2385 + 2429 3 262.95 56.4 -51.2 0.25 2428 + 2430 3 262.75 51.2 -51.2 0.25 2428 + 2431 3 270.35 52.3 -53.6 0.5 2384 + 2432 3 263.55 51.3 -49.8 0.5 2383 + 2433 3 262.75 47.2 -49.8 0.5 2432 + 2434 3 261.45 45.8 -50.7 0.25 2433 + 2435 3 262.45 52.3 -49.8 0.5 2432 + 2436 3 260.95 52.3 -50 0.25 2435 + 2437 3 265.35 53 -49.8 0.5 2435 + 2438 3 270.65 49.9 -46.5 0.5 2382 + 2439 3 272.05 52.2 -46.5 0.5 2438 + 2440 3 270.35 57.2 -45.7 0.5 2439 + 2441 3 269.65 58.2 -45.7 0.5 2440 + 2442 3 269.65 61.3 -48.5 0.5 2441 + 2443 3 266.05 58.2 -45.7 0.5 2441 + 2444 3 271.35 52.2 -46.1 0.5 2439 + 2445 3 263.65 42.3 -54.7 0.25 2380 + 2446 3 263.45 37.5 -57 0.5 2379 + 2447 3 263.55 38.5 -56.7 0.5 2378 + 2448 3 270.05 35.9 -52.3 1.75 2376 + 2449 3 270.15 37.7 -53.2 1.75 2448 + 2450 3 269.55 40.2 -52.7 1.75 2449 + 2451 3 273.35 42 -50.1 1.75 2450 + 2452 3 276.15 46.2 -48.2 1.75 2451 + 2453 3 277.25 49.9 -43.3 1.75 2452 + 2454 3 277.25 51.9 -44.5 1.75 2453 + 2455 3 275.35 54.9 -41.7 1.75 2454 + 2456 3 278.55 57 -40.6 1.75 2455 + 2457 3 279.45 60.9 -42.8 1.75 2456 + 2458 3 280.35 62.2 -40 1.75 2457 + 2459 3 282.05 67.2 -38 1.75 2458 + 2460 3 280.65 69.3 -38 1.75 2459 + 2461 3 282.85 70.9 -40.7 1.75 2460 + 2462 3 284.95 74.1 -37.4 1.75 2461 + 2463 3 284.95 79.2 -40.4 1.75 2462 + 2464 3 287.35 81.4 -36.4 1.75 2463 + 2465 3 287.35 84.2 -39.2 1.75 2464 + 2466 3 289.95 86.4 -35.7 1.75 2465 + 2467 3 288.05 89.5 -37.2 1.75 2466 + 2468 3 289.25 93.4 -37.1 1.5 2467 + 2469 3 291.95 94.2 -37.1 1.5 2468 + 2470 3 293.95 96.9 -36.9 1.5 2469 + 2471 3 296.45 99.4 -40.2 2 2470 + 2472 3 294.35 98 -38.8 2.5 2471 + 2473 3 297.35 101.4 -44.2 1.5 2472 + 2474 3 298.35 104.4 -42.2 1.5 2473 + 2475 3 299.25 106.7 -40.8 1.5 2474 + 2476 3 300.15 109.5 -40.9 1.5 2475 + 2477 3 296.95 111.6 -41.1 1.25 2476 + 2478 3 296.45 114.3 -40.9 1.25 2477 + 2479 3 295.55 117.2 -45.5 0.5 2478 + 2480 3 291.45 111.1 -42.1 0.75 2478 + 2481 3 294.45 109.8 -41.1 0.5 2477 + 2482 3 292.95 111.9 -41.1 0.5 2481 + 2483 3 292.45 106.8 -41.1 0.5 2481 + 2484 3 305.45 109.5 -44.4 1 2476 + 2485 3 293.35 106.9 -40.8 0.5 2475 + 2486 3 300.05 98 -38.8 1.25 2472 + 2487 3 302.75 99.1 -38.6 1.25 2486 + 2488 3 306.15 99.6 -38.5 1.25 2487 + 2489 3 308.35 99.6 -38.4 1.25 2488 + 2490 3 309.95 99.6 -39.2 1.25 2489 + 2491 3 312.35 104.7 -41.1 0.75 2490 + 2492 3 314.55 101.8 -43 0.75 2491 + 2493 3 309.65 106.6 -41.1 0.5 2491 + 2494 3 313.35 98.2 -38.4 0.75 2490 + 2495 3 316.05 95.6 -41.7 0.75 2494 + 2496 3 308.35 104.5 -38.4 0.5 2489 + 2497 3 300.15 104.4 -37.9 0.5 2488 + 2498 3 297.45 107.1 -42.9 0.5 2497 + 2499 3 305.25 95.4 -43.4 0.5 2487 + 2500 3 291.25 100.6 -40.2 0.5 2471 + 2501 3 289.55 100.2 -40.2 0.5 2500 + 2502 3 288.65 98 -41.2 0.5 2470 + 2503 3 286.75 94.2 -35.9 0.5 2469 + 2504 3 286.45 96.8 -38.8 0.25 2503 + 2505 3 285.35 91.6 -36.3 0.5 2503 + 2506 3 285.85 89.5 -40.7 0.5 2467 + 2507 3 282.65 88.3 -40.7 0.5 2506 + 2508 3 284.75 91.6 -40.7 0.25 2506 + 2509 3 283.55 85.3 -43.6 0.5 2465 + 2510 3 283.55 86.5 -43.6 0.5 2509 + 2511 3 282.15 82.7 -44.6 0.5 2509 + 2512 3 281.45 80.3 -42.9 0.5 2463 + 2513 3 280.65 76.5 -37.4 0.5 2462 + 2514 3 281.05 78.7 -37.4 0.5 2513 + 2515 3 278.25 76.5 -37.3 0.5 2513 + 2516 3 277.35 72.8 -43.9 0.5 2461 + 2517 3 285.35 65.5 -39.2 0.5 2460 + 2518 3 287.75 69.4 -39 0.5 2517 + 2519 3 285.35 63.8 -37 0.5 2517 + 2520 3 275.55 64 -43.9 0.5 2458 + 2521 3 276.95 65.2 -43.9 0.5 2520 + 2522 3 271.95 60.8 -43.9 0.5 2520 + 2523 3 283.55 58.5 -40.1 0.5 2456 + 2524 3 287.95 58.1 -42.2 0.5 2523 + 2525 3 284.85 60.6 -40.6 0.5 2523 + 2526 3 283.35 61.2 -40.6 0.25 2525 + 2527 3 286.25 61.7 -40.6 0.5 2525 + 2528 3 272.35 56.2 -41.7 0.5 2455 + 2529 3 269.85 57.7 -43 0.5 2528 + 2530 3 280.45 49.1 -41.4 0.5 2454 + 2531 3 277.05 46.8 -42.7 0.5 2530 + 2532 3 281.85 52 -40.7 0.5 2530 + 2533 3 272.25 51.2 -46.5 0.75 2453 + 2534 3 268.05 47.7 -42.8 0.5 2533 + 2535 3 265.05 46.8 -49.2 0.5 2534 + 2536 3 270.25 53.8 -49.3 0.75 2533 + 2537 3 266.75 51.6 -44.9 0.5 2536 + 2538 3 265.95 55 -44.9 0.5 2537 + 2539 3 265.45 50.5 -44.9 0.25 2537 + 2540 3 270.25 55.3 -51.3 0.25 2536 + 2541 3 275.85 37.9 -47.6 0.5 2451 + 2542 3 277.35 40.6 -47.2 0.5 2541 + 2543 3 275.85 36.5 -47.6 0.25 2541 + 2544 3 271.55 31.5 -52.3 0.5 2448 + 2545 3 260.55 30.7 -56.5 0.5 2375 + 2546 3 264.65 30.6 -53 1.75 2374 + 2547 3 267.25 36.1 -52 1.75 2546 + 2548 3 267.95 35.2 -48.1 1.75 2547 + 2549 3 271.35 40.4 -48.2 1.5 2548 + 2550 3 273.85 42.2 -45.2 1.5 2549 + 2551 3 271.05 42.8 -44.9 1.5 2550 + 2552 3 274.55 42.7 -44.8 1.5 2551 + 2553 3 272.25 45.1 -44.1 1.5 2552 + 2554 3 273.25 48.3 -44.9 1.25 2553 + 2555 3 276.55 50.1 -43.7 1.5 2554 + 2556 3 278.95 52.7 -42.2 1.25 2555 + 2557 3 277.15 54.7 -40.6 1.25 2556 + 2558 3 280.95 56.3 -39.6 1.5 2557 + 2559 3 283.85 59.4 -34 1.5 2558 + 2560 3 283.85 63.5 -35.6 1.75 2559 + 2561 3 288.85 67.1 -35.9 1.75 2560 + 2562 3 286.65 67.8 -35.8 1.75 2561 + 2563 3 284.55 60.9 -35.8 1.75 2562 + 2564 3 287.25 65.3 -35.6 1.5 2563 + 2565 3 285.45 65.2 -33.8 1.5 2564 + 2566 3 288.35 67.4 -30.5 1.25 2565 + 2567 3 286.45 69.1 -30.7 1.5 2566 + 2568 3 291.15 71.1 -30.5 1.5 2567 + 2569 3 293.05 74.3 -33.1 1.5 2568 + 2570 3 291.85 76.3 -32.2 1.25 2569 + 2571 3 293.55 76.8 -28.8 1.75 2570 + 2572 3 298.35 80 -27.3 1.5 2571 + 2573 3 300.65 82.4 -26.8 1.5 2572 + 2574 3 300.65 85 -30 1.5 2573 + 2575 3 305.05 84.9 -25.9 1.5 2574 + 2576 3 305.55 85.7 -30 1.5 2575 + 2577 3 306.15 88.5 -29.3 1.5 2576 + 2578 3 307.45 90.2 -26.6 1.5 2577 + 2579 3 308.65 91.5 -29.6 1.5 2578 + 2580 3 310.95 94.5 -31.5 2 2579 + 2581 3 310.95 94.5 -29.9 1 2580 + 2582 3 313.75 96.3 -27.8 1 2581 + 2583 3 316.35 97.3 -31.3 1 2582 + 2584 3 316.35 98.2 -32.3 1 2583 + 2585 3 319.55 96.3 -32.4 1 2584 + 2586 3 322.55 98.1 -35.2 1 2585 + 2587 3 324.85 99.1 -38.2 1 2586 + 2588 3 327.25 99.1 -39.1 1 2587 + 2589 3 329.25 100.7 -41.8 1.5 2588 + 2590 3 329.25 102.4 -40.8 0.75 2589 + 2591 3 333.65 102.3 -43 1 2590 + 2592 3 335.85 102.3 -46.6 1 2591 + 2593 3 339.35 100.3 -44.9 1 2592 + 2594 3 340.55 99.7 -45 0.75 2593 + 2595 3 342.45 102.3 -49.3 0.5 2594 + 2596 3 345.25 102.3 -53.6 0.5 2595 + 2597 3 344.05 98.3 -49.3 0.5 2595 + 2598 3 338.55 97.7 -45.1 0.5 2594 + 2599 3 335.75 99.8 -45.1 0.5 2598 + 2600 3 339.35 104.6 -44.9 0.5 2593 + 2601 3 334.85 104.9 -43.8 0.5 2592 + 2602 3 331.25 105.7 -45 0.5 2590 + 2603 3 332.65 96.9 -42.3 1 2589 + 2604 3 335.85 96.9 -44.2 1 2603 + 2605 3 339.55 96.9 -43.3 1 2604 + 2606 3 342.55 94.2 -45.3 0.75 2605 + 2607 3 344.95 97.7 -45.3 0.5 2606 + 2608 3 347.05 93.8 -45.3 0.5 2607 + 2609 3 342.55 91.9 -45.3 0.5 2606 + 2610 3 343.95 87.9 -44.3 0.5 2609 + 2611 3 338.85 91.9 -45.3 0.5 2609 + 2612 3 337.55 90.5 -42.6 0.5 2611 + 2613 3 339.55 91.6 -43.7 0.5 2605 + 2614 3 333.55 93.3 -44.6 0.75 2604 + 2615 3 329.75 95.9 -42.3 0.5 2603 + 2616 3 329.05 97.7 -42.3 0.25 2615 + 2617 3 328.85 94.8 -42.3 0.25 2615 + 2618 3 327.25 97 -36.5 0.5 2588 + 2619 3 324.85 95.5 -36.5 0.5 2618 + 2620 3 322.65 95.5 -38.8 0.5 2619 + 2621 3 329.55 95.9 -36.5 0.25 2618 + 2622 3 320.95 102.6 -35.1 0.5 2587 + 2623 3 323.05 104.4 -35.1 0.5 2622 + 2624 3 319.15 102.9 -35.1 0.5 2622 + 2625 3 324.15 95.4 -33.9 0.25 2586 + 2626 3 319.55 100.6 -35.9 0.25 2585 + 2627 3 314.75 99.8 -32.3 0.25 2584 + 2628 3 318.55 93.1 -33.3 0.5 2583 + 2629 3 312.25 98.4 -34.4 0.5 2582 + 2630 3 310.45 99.8 -37.6 0.5 2629 + 2631 3 315.55 94.5 -31.6 1.5 2580 + 2632 3 318.75 94.5 -32.5 1.5 2631 + 2633 3 320.95 93.4 -30.7 1.5 2632 + 2634 3 325.25 95.2 -33.9 1.5 2633 + 2635 3 327.55 91.4 -33.1 1.5 2634 + 2636 3 331.05 90.3 -34.9 1.25 2635 + 2637 3 333.05 91 -32.1 1.25 2636 + 2638 3 336.35 91 -35.6 1.5 2637 + 2639 3 337.65 89 -32.4 1.25 2638 + 2640 3 341.05 90.8 -33.2 1.25 2639 + 2641 3 343.05 88.1 -37.5 1.25 2640 + 2642 3 346.45 89.3 -37.7 1.25 2641 + 2643 3 349.45 86.3 -37 1.25 2642 + 2644 3 352.65 85.2 -41.1 1 2643 + 2645 3 353.85 83.9 -44.2 1 2644 + 2646 3 355.35 83.9 -45.3 0.75 2645 + 2647 3 357.75 81.6 -42 0.5 2646 + 2648 3 362.05 82.3 -44.4 0.75 2647 + 2649 3 365.45 82.3 -45.8 0.75 2648 + 2650 3 369.65 82.3 -46.1 0.75 2649 + 2651 3 366.85 76 -44.1 0.5 2649 + 2652 3 369.65 77.4 -44 0.5 2651 + 2653 3 366.85 74.8 -47.5 0.5 2651 + 2654 3 363.85 76.3 -42.1 0.5 2648 + 2655 3 359.05 78.5 -41.3 0.5 2647 + 2656 3 355.35 85.8 -41.6 0.5 2646 + 2657 3 353.85 80.3 -44.2 0.5 2645 + 2658 3 347.15 84.5 -41.3 0.5 2643 + 2659 3 349.15 81.6 -41.3 0.5 2658 + 2660 3 349.15 80.2 -42.1 0.5 2659 + 2661 3 344.95 81.6 -41.3 0.5 2659 + 2662 3 345.25 85.3 -41.3 0.25 2658 + 2663 3 344.25 85.9 -37.7 0.75 2641 + 2664 3 342.85 82.8 -37 0.5 2663 + 2665 3 347.15 81.3 -35.7 0.5 2664 + 2666 3 340.85 81.8 -37 0.5 2664 + 2667 3 339.95 84.7 -37.7 0.5 2663 + 2668 3 338.35 86.5 -37.5 0.5 2639 + 2669 3 333.85 94.4 -34.4 0.5 2638 + 2670 3 333.85 95.8 -34.4 0.5 2669 + 2671 3 332.45 91.6 -34.4 0.5 2669 + 2672 3 333.05 86.7 -36.9 0.5 2637 + 2673 3 333.65 84.8 -34.6 0.5 2672 + 2674 3 330.25 83.6 -34.6 0.25 2673 + 2675 3 329.05 83.6 -34.6 0.25 2674 + 2676 3 332.55 81.8 -34.6 0.25 2674 + 2677 3 335.75 84.8 -34.6 0.5 2673 + 2678 3 327.45 85.8 -37.3 0.5 2672 + 2679 3 330.05 95.5 -36.8 0.5 2635 + 2680 3 327.35 96.9 -37 0.75 2634 + 2681 3 329.75 96.4 -33.5 0.75 2680 + 2682 3 331.45 96.4 -36.9 0.75 2681 + 2683 3 334.45 96.9 -37.4 0.75 2682 + 2684 3 336.15 98.2 -38.3 0.5 2683 + 2685 3 337.95 99 -38.3 0.5 2684 + 2686 3 337.05 94.4 -38.3 0.5 2684 + 2687 3 333.95 92.2 -34.3 0.5 2683 + 2688 3 327.35 93.4 -33.5 0.5 2681 + 2689 3 327.35 99.2 -34.1 0.25 2680 + 2690 3 314.35 89.8 -36.1 0.5 2632 + 2691 3 304.45 92.8 -31.2 0.5 2579 + 2692 3 301.75 92.8 -31.2 0.5 2691 + 2693 3 300.05 93.9 -33.6 0.5 2692 + 2694 3 300.05 89.6 -31.2 0.5 2692 + 2695 3 310.15 87.2 -32.8 0.5 2578 + 2696 3 311.95 87.2 -33.3 0.5 2695 + 2697 3 307.85 84.8 -33.3 0.5 2695 + 2698 3 301.45 89.7 -28.8 0.5 2577 + 2699 3 306.65 82.5 -32 0.5 2576 + 2700 3 304.75 81.8 -31.2 0.5 2699 + 2701 3 307.05 78 -31.2 0.5 2700 + 2702 3 303.35 82 -31.2 0.25 2700 + 2703 3 300.65 87.5 -31.7 0.5 2575 + 2704 3 298.95 86.4 -31.7 0.5 2703 + 2705 3 300.65 89.5 -31.7 0.5 2703 + 2706 3 304.35 80.3 -29.2 0.5 2573 + 2707 3 300.95 76.3 -33.8 0.25 2706 + 2708 3 305.55 76.1 -33.8 0.25 2707 + 2709 3 300.95 75.3 -33.8 0.25 2707 + 2710 3 305.55 80.3 -30.4 0.25 2706 + 2711 3 290.45 80.6 -32.4 0.75 2571 + 2712 3 294.95 83.9 -32.3 0.5 2711 + 2713 3 294.95 86.6 -33.3 0.5 2712 + 2714 3 297.85 88.7 -33.9 0.5 2713 + 2715 3 292.55 89.5 -35.8 0.25 2713 + 2716 3 287.65 81.9 -32.6 0.5 2711 + 2717 3 297.35 74 -34.1 0.5 2570 + 2718 3 301.65 73.3 -34 0.5 2717 + 2719 3 301.95 74.9 -34.1 0.5 2718 + 2720 3 305.45 71.8 -34.1 0.25 2719 + 2721 3 305.35 76.9 -34.1 0.25 2719 + 2722 3 301.65 71.4 -34 0.25 2718 + 2723 3 299.05 72.4 -38.2 0.25 2717 + 2724 3 287.15 72.3 -36.6 0.25 2568 + 2725 3 291.65 66.6 -36.3 0.5 2566 + 2726 3 293.55 66.6 -39 0.5 2725 + 2727 3 289.65 63.9 -38 0.5 2725 + 2728 3 283.25 69 -36.9 0.5 2565 + 2729 3 281.15 70.9 -34.3 0.5 2728 + 2730 3 284.15 73.2 -37.7 0.5 2729 + 2731 3 287.15 73.4 -32.5 0.5 2730 + 2732 3 285.65 70.2 -37.7 0.5 2730 + 2733 3 279.75 71.1 -38.1 0.25 2729 + 2734 3 291.95 67.1 -32.3 1 2562 + 2735 3 293.75 67.1 -32.4 1 2734 + 2736 3 295.95 67 -30 1.25 2735 + 2737 3 298.55 69.6 -32.8 1.25 2736 + 2738 3 301.45 67.9 -27.7 1.5 2737 + 2739 3 301.95 70 -27.1 1.5 2738 + 2740 3 301.95 70 -29.3 1 2739 + 2741 3 300.15 72.5 -28.9 1 2740 + 2742 3 303.15 74 -29.8 1 2741 + 2743 3 305.25 74.8 -29.6 1 2742 + 2744 3 306.75 75.7 -29.4 1 2743 + 2745 3 306.75 77.2 -30.3 1 2744 + 2746 3 307.85 81.8 -25.7 1 2745 + 2747 3 307.85 84.3 -29.5 1 2746 + 2748 3 308.75 86.2 -26.4 1 2747 + 2749 3 312.65 86.2 -28.8 1 2748 + 2750 3 314.55 88.1 -25.8 1.25 2749 + 2751 3 315.65 89.4 -29 1 2750 + 2752 3 317.05 90.7 -28.5 1 2751 + 2753 3 319.75 91.8 -26.9 1 2752 + 2754 3 323.25 89.5 -30.5 0.5 2753 + 2755 3 322.05 91 -28.4 0.75 2754 + 2756 3 322.25 93.4 -31.3 0.5 2755 + 2757 3 329.35 90.9 -31.7 0.5 2756 + 2758 3 331.35 86.6 -29.1 0.5 2757 + 2759 3 325.15 86.9 -32.8 0.5 2757 + 2760 3 325.95 95.6 -28.1 0.5 2756 + 2761 3 326.35 89.3 -30.7 0.75 2755 + 2762 3 320.65 86.9 -27.7 0.5 2754 + 2763 3 323.45 85.7 -32.3 0.5 2762 + 2764 3 319.35 86.9 -27.7 0.25 2762 + 2765 3 320.95 87.6 -34.1 0.5 2753 + 2766 3 311.45 91.3 -30.1 0.75 2751 + 2767 3 314.95 90.9 -28.6 0.5 2766 + 2768 3 316.35 84.7 -26.8 0.25 2750 + 2769 3 310.05 89.2 -32 0.5 2749 + 2770 3 306.85 87.4 -27.1 0.25 2748 + 2771 3 309.25 80.9 -27.3 0.75 2746 + 2772 3 313.25 82.5 -30.7 0.75 2771 + 2773 3 315.65 83 -29.4 0.75 2772 + 2774 3 317.45 83.8 -33 0.75 2773 + 2775 3 318.25 80.8 -34.7 0.75 2774 + 2776 3 322.65 81.5 -30.8 0.5 2775 + 2777 3 320.75 78.5 -36.8 0.5 2775 + 2778 3 320.85 77 -35.8 0.5 2777 + 2779 3 319.45 85.3 -31.8 0.5 2774 + 2780 3 317.65 79.1 -27.7 0.5 2773 + 2781 3 313.85 78.4 -29.5 0.5 2772 + 2782 3 315.25 77.3 -29.5 0.5 2781 + 2783 3 310.35 78.4 -28.2 0.25 2781 + 2784 3 311.75 78.7 -29.9 0.5 2771 + 2785 3 309.85 77.2 -27 0.5 2745 + 2786 3 311.15 78.6 -28.9 0.25 2785 + 2787 3 313.45 76.5 -31.9 0.25 2786 + 2788 3 309.85 74.4 -26.4 0.25 2785 + 2789 3 307.85 71.3 -32.3 0.5 2744 + 2790 3 307.85 69.5 -30.6 0.5 2789 + 2791 3 299.15 76.9 -31.1 0.5 2742 + 2792 3 296.75 77 -32.5 0.5 2791 + 2793 3 297.75 80.1 -32.5 0.25 2792 + 2794 3 294.55 77 -35.4 0.5 2792 + 2795 3 302.35 78.3 -35.3 0.5 2791 + 2796 3 298.65 72.5 -34.6 0.5 2741 + 2797 3 296.15 69.2 -32.4 0.5 2796 + 2798 3 296.15 71.9 -36.4 0.5 2796 + 2799 3 306.75 67.2 -24.1 1.5 2739 + 2800 3 309.15 67.8 -23.7 1.25 2799 + 2801 3 308.75 72.5 -19.7 1.25 2800 + 2802 3 313.85 71.1 -22.5 1.25 2801 + 2803 3 316.25 74.3 -22.1 1.5 2802 + 2804 3 318.55 75.1 -22.6 1.25 2803 + 2805 3 319.95 75.6 -19 1.25 2804 + 2806 3 322.65 77.3 -20.7 1.25 2805 + 2807 3 324.25 79 -19.5 1.25 2806 + 2808 3 326.85 80.5 -22.4 1.25 2807 + 2809 3 328.05 80.5 -19.2 1.25 2808 + 2810 3 329.85 81.4 -24.2 1 2809 + 2811 3 329.85 82 -25.5 1 2810 + 2812 3 331.55 83.3 -26.5 1 2811 + 2813 3 333.35 85.3 -25 1 2812 + 2814 3 335.35 84.4 -24.5 1 2813 + 2815 3 336.45 81 -30.1 0.75 2814 + 2816 3 335.15 77.6 -28.4 0.5 2815 + 2817 3 338.05 75.1 -28.2 0.5 2816 + 2818 3 339.15 77.6 -27.3 0.5 2817 + 2819 3 338.05 71.8 -28.2 0.25 2817 + 2820 3 339.05 81 -31 0.5 2815 + 2821 3 336.95 87.4 -27.6 0.5 2814 + 2822 3 334.05 81.9 -25 0.25 2813 + 2823 3 333.75 82 -26 0.5 2811 + 2824 3 336.15 82 -30.3 0.5 2823 + 2825 3 336.65 77 -32.2 0.5 2824 + 2826 3 337.95 83.3 -26.8 0.5 2824 + 2827 3 325.85 78.9 -25.1 0.25 2810 + 2828 3 333.95 81.3 -21.4 1 2809 + 2829 3 333.55 81.7 -19.3 1 2828 + 2830 3 340.65 85.4 -22.8 1 2829 + 2831 3 346.75 83.7 -28.2 1 2830 + 2832 3 348.75 82.6 -26.8 1 2831 + 2833 3 351.95 84.6 -30.2 1 2832 + 2834 3 354.85 84.6 -29.5 0.75 2833 + 2835 3 355.55 80 -26.9 0.5 2834 + 2836 3 356.25 76.2 -25.1 0.5 2835 + 2837 3 356.25 73.2 -24.1 0.5 2836 + 2838 3 358.95 78.7 -30.4 0.5 2835 + 2839 3 355.95 83.6 -33 0.5 2834 + 2840 3 359.75 80.1 -34.9 0.5 2839 + 2841 3 348.95 79.5 -30.4 0.5 2833 + 2842 3 351.15 77 -24.4 0.5 2841 + 2843 3 350.75 74.3 -28.8 0.5 2842 + 2844 3 353.15 77 -28.7 0.5 2842 + 2845 3 347.15 79.5 -26.1 0.25 2841 + 2846 3 345.75 81.9 -27.9 0.5 2832 + 2847 3 348.65 79.2 -27.9 0.5 2846 + 2848 3 343.85 86.9 -30.3 0.5 2831 + 2849 3 343.35 80.8 -22.6 0.5 2830 + 2850 3 342.95 78.9 -22.6 0.75 2849 + 2851 3 346.95 78.3 -20.8 0.5 2850 + 2852 3 348.75 76 -20 0.5 2851 + 2853 3 351.15 78.5 -19.5 0.5 2852 + 2854 3 348.75 74.3 -20 0.5 2852 + 2855 3 342.95 77.5 -26.1 0.5 2850 + 2856 3 345.75 75.8 -26.1 0.25 2855 + 2857 3 341.55 74.9 -25.1 0.25 2855 + 2858 3 340.75 79.3 -27 0.5 2849 + 2859 3 341.85 75.1 -32.2 0.25 2858 + 2860 3 343.35 73.1 -32.2 0.25 2859 + 2861 3 336.85 79.3 -26.2 0.5 2858 + 2862 3 336.75 77.6 -20 0.5 2829 + 2863 3 338.95 77.8 -24.5 0.5 2862 + 2864 3 340.65 76 -24.5 0.5 2863 + 2865 3 342.75 74.5 -21.4 0.5 2864 + 2866 3 333.85 76.3 -22.1 0.5 2862 + 2867 3 332.65 73.9 -22.5 0.5 2866 + 2868 3 332.45 78.3 -22.1 0.5 2866 + 2869 3 322.35 72.1 -24.4 0.5 2805 + 2870 3 314.45 77.2 -22.2 0.25 2804 + 2871 3 320.35 72.9 -20.9 1 2803 + 2872 3 323.15 72.9 -17.8 1 2871 + 2873 3 324.95 72.9 -20.5 1 2872 + 2874 3 330.05 71.2 -20.3 1 2873 + 2875 3 331.15 69 -21 1 2874 + 2876 3 329.95 71 -20.5 0.75 2875 + 2877 3 334.45 72.3 -16.7 0.75 2876 + 2878 3 336.75 74.5 -15.5 0.75 2877 + 2879 3 338.95 74.4 -16.3 0.75 2878 + 2880 3 341.35 73 -17.8 0.75 2879 + 2881 3 343.85 74.2 -18.7 0.75 2880 + 2882 3 345.85 75 -18.8 0.75 2881 + 2883 3 346.65 73.1 -18.2 0.75 2882 + 2884 3 348.65 73 -19.1 0.75 2883 + 2885 3 351.05 70.3 -24.9 0.5 2884 + 2886 3 353.85 71.6 -21.7 0.5 2885 + 2887 3 348.95 67.6 -26.8 0.5 2885 + 2888 3 350.05 76.6 -19.3 0.5 2884 + 2889 3 346.65 70.1 -23.5 0.5 2883 + 2890 3 343.85 77 -18.8 0.5 2882 + 2891 3 344.95 71.1 -18.7 0.25 2881 + 2892 3 341.35 70.3 -22.1 0.5 2880 + 2893 3 342.45 67.6 -20.3 0.5 2892 + 2894 3 338.15 70.3 -19 0.25 2892 + 2895 3 332.85 75.7 -21.4 0.5 2878 + 2896 3 337.95 72.3 -21.8 0.5 2877 + 2897 3 340.25 72.9 -22.1 0.5 2896 + 2898 3 339.45 67.8 -21.8 0.5 2896 + 2899 3 330.05 67.9 -16.8 0.75 2875 + 2900 3 334.85 66.9 -22.3 0.75 2899 + 2901 3 337.65 66.9 -20.8 0.75 2900 + 2902 3 339.55 66.9 -24 0.5 2901 + 2903 3 337.65 63 -18.8 0.5 2901 + 2904 3 335.85 69.6 -19.6 0.25 2900 + 2905 3 329.05 66.2 -20.4 0.5 2899 + 2906 3 326.25 74.9 -19.7 0.5 2873 + 2907 3 328.75 76.2 -23 0.5 2906 + 2908 3 331.15 79.1 -24.9 0.5 2907 + 2909 3 330.25 73.7 -20.1 0.5 2907 + 2910 3 322.65 74.9 -24 0.25 2906 + 2911 3 323.15 69 -21.4 0.5 2872 + 2912 3 315.15 69.1 -22.9 0.5 2802 + 2913 3 306.75 64.8 -23.7 0.5 2799 + 2914 3 303.85 64.5 -34.1 0.5 2738 + 2915 3 297.45 72.9 -32.5 0.5 2737 + 2916 3 295.15 63.2 -34.9 0.25 2735 + 2917 3 282.75 70.8 -33 0.5 2561 + 2918 3 287.65 59.4 -36.9 0.75 2559 + 2919 3 290.15 59.4 -34.7 0.75 2918 + 2920 3 292.75 56.1 -38.8 0.5 2919 + 2921 3 294.35 60.4 -37 0.5 2920 + 2922 3 295.75 58.8 -39.6 0.5 2921 + 2923 3 298.35 56.6 -42.6 0.5 2922 + 2924 3 290.95 63.4 -37 0.5 2921 + 2925 3 294.95 54.2 -38.6 0.5 2920 + 2926 3 278.65 58.2 -42.3 0.5 2558 + 2927 3 281.65 52.7 -43.6 0.5 2556 + 2928 3 270.95 54.9 -43.7 0.75 2555 + 2929 3 270.95 58.5 -40.9 0.75 2928 + 2930 3 269.45 60.7 -44.7 0.75 2929 + 2931 3 271.35 64.7 -45.3 0.75 2930 + 2932 3 272.55 67.8 -42.5 0.5 2931 + 2933 3 269.45 70.8 -44.4 0.75 2932 + 2934 3 270.95 71.3 -41.2 0.75 2933 + 2935 3 270.95 74.8 -43.1 0.75 2934 + 2936 3 272.15 76.6 -38.9 0.75 2935 + 2937 3 274.15 78.4 -38.3 0.75 2936 + 2938 3 271.95 79 -38.3 0.75 2937 + 2939 3 273.45 81.6 -38.1 0.5 2938 + 2940 3 273.45 83.4 -44.2 0.5 2939 + 2941 3 274.45 87 -40.9 0.5 2940 + 2942 3 274.45 90.8 -40.6 0.5 2941 + 2943 3 269.95 89.5 -45.5 0.25 2941 + 2944 3 269.85 83.4 -44.5 0.5 2940 + 2945 3 268.55 84.6 -46.7 0.25 2944 + 2946 3 268.65 79.9 -46.7 0.5 2944 + 2947 3 273.85 81.3 -38.9 0.5 2938 + 2948 3 276.75 82.7 -37.4 0.5 2947 + 2949 3 276.55 74.3 -37.3 0.5 2937 + 2950 3 267.25 71.3 -43.9 0.5 2934 + 2951 3 273.75 72.2 -43.8 0.5 2933 + 2952 3 274.95 68.6 -43.8 0.5 2951 + 2953 3 272.05 73.4 -43.8 0.25 2951 + 2954 3 267.85 66.3 -43.2 0.25 2931 + 2955 3 266.25 60.7 -44.6 0.5 2930 + 2956 3 272.15 46.9 -43.5 0.5 2553 + 2957 3 269.95 50.4 -46.1 0.5 2956 + 2958 3 268.35 52.9 -46.7 0.5 2957 + 2959 3 266.15 54.7 -47.2 0.5 2958 + 2960 3 277.05 42.7 -44.7 0.5 2552 + 2961 3 279.55 44.3 -44.2 0.5 2960 + 2962 3 278.25 45.8 -46.5 0.5 2960 + 2963 3 269.35 42.4 -47.1 0.25 2551 + 2964 3 275.75 38.8 -53.3 0.5 2550 + 2965 3 274.95 35.4 -53.9 0.5 2549 + 2966 3 271.05 33.9 -48.8 0.5 2548 + 2967 3 274.75 32.8 -51.7 0.5 2966 + 2968 3 278.05 30.8 -55.5 0.5 2967 + 2969 3 275.55 29.1 -55.5 0.5 2968 + 2970 3 272.65 31.7 -52.4 0.5 2967 + 2971 3 270.95 29.3 -54.7 0.5 2970 + 2972 3 276.05 29.6 -50.5 0.25 2970 + 2973 3 263.15 39.7 -57.5 0.25 2547 + 2974 3 270.15 22.3 -56.4 2.25 1810 + 2975 3 272.05 22.3 -52.7 2.25 2974 + 2976 3 276.35 25.8 -52.6 2 2975 + 2977 3 277.85 24.9 -49.9 2 2976 + 2978 3 283.75 25 -47.2 2 2977 + 2979 3 287.35 26.1 -40.4 2.25 2978 + 2980 3 289.75 26.1 -40.6 2 2979 + 2981 3 292.15 26.5 -35.3 3.25 2980 + 2982 3 300.55 25.7 -32.5 2.5 2981 + 2983 3 302.75 27.7 -31.1 2.25 2982 + 2984 3 300.85 26.4 -30.6 2 2983 + 2985 3 304.85 29.7 -31.9 2 2984 + 2986 3 311.35 29.8 -30 2 2985 + 2987 3 314.05 32.7 -24.4 2 2986 + 2988 3 316.15 35.4 -23.4 2 2987 + 2989 3 319.85 33.1 -18.5 2.25 2988 + 2990 3 325.95 35 -19.2 2 2989 + 2991 3 329.15 32.5 -14.8 2.25 2990 + 2992 3 328.45 33.9 -9.5 2 2991 + 2993 3 333.75 30.6 -8.3 2 2992 + 2994 3 337.35 30 -7.7 2 2993 + 2995 3 341.55 30 -9 2.25 2994 + 2996 3 344.65 30 -5.7 2.5 2995 + 2997 3 346.85 30.1 -8.3 1.75 2996 + 2998 3 347.95 30.1 -4.6 2 2997 + 2999 3 351.05 30.1 -9.1 1.75 2998 + 3000 3 354.65 32.4 -4.7 1.75 2999 + 3001 3 355.45 31 -4.7 1.75 3000 + 3002 3 355.45 31.8 -4.7 1.25 3001 + 3003 3 357.65 31.3 -2.8 1.25 3002 + 3004 3 358.95 33.9 -6.2 1.25 3003 + 3005 3 360.65 34 -3.1 1.25 3004 + 3006 3 358.85 36.3 -1.7 1.25 3005 + 3007 3 364.05 37.8 -3.8 1.25 3006 + 3008 3 366.05 39.9 -6.1 1.25 3007 + 3009 3 370.25 43.3 -6.8 1.25 3008 + 3010 3 373.05 43.2 -6.5 1 3009 + 3011 3 373.15 44.9 -10 1.25 3010 + 3012 3 377.75 46.8 -12.5 1 3011 + 3013 3 381.05 43.7 -15.2 0.75 3012 + 3014 3 375.15 50.5 -11.4 0.5 3012 + 3015 3 374.85 39.7 -8.8 0.5 3010 + 3016 3 376.75 38 -12.5 0.5 3015 + 3017 3 377.85 39.4 -12.5 0.5 3016 + 3018 3 380.45 36.3 -12.4 0.5 3017 + 3019 3 378.95 40.8 -14 0.5 3017 + 3020 3 374.25 35.6 -12.2 0.25 3016 + 3021 3 371.85 38.4 -6.3 0.5 3015 + 3022 3 367.95 36 -8.2 0.5 3008 + 3023 3 369.85 36 -9.7 0.5 3022 + 3024 3 372.85 38.8 -3 0.5 3023 + 3025 3 376.15 36.1 -1 0.5 3024 + 3026 3 374.15 40.3 -3 0.5 3024 + 3027 3 370.55 34.3 -9.7 0.5 3023 + 3028 3 356.15 37.4 -5.4 0.5 3006 + 3029 3 354.15 38.6 -2.9 0.5 3028 + 3030 3 356.15 39.4 -5.4 0.25 3028 + 3031 3 363.45 32.1 -3.1 0.5 3005 + 3032 3 366.55 34.4 -1.5 0.25 3031 + 3033 3 361.15 30.5 -1.9 0.5 3031 + 3034 3 354.15 36.2 -2.1 0.5 3004 + 3035 3 352.65 38 -2.1 0.5 3034 + 3036 3 358.05 30 -6.4 1.25 3001 + 3037 3 359.75 31.3 -7 1.5 3036 + 3038 3 362.25 30.3 -5.2 1.25 3037 + 3039 3 368.05 28.7 -3.1 1.25 3038 + 3040 3 369.15 28.4 -3.1 1.25 3039 + 3041 3 374.25 28.2 -5.1 1.25 3040 + 3042 3 375.65 26.2 -5.9 1.25 3041 + 3043 3 378.85 28.2 -6.9 1 3042 + 3044 3 383.95 26.9 -8.6 1 3043 + 3045 3 385.95 26.9 -10.7 1 3044 + 3046 3 388.35 28.4 -10.5 1 3045 + 3047 3 388.75 28.3 -10.4 1 3046 + 3048 3 390.75 25.6 -8.9 0.75 3047 + 3049 3 393.95 25.2 -10.9 1 3048 + 3050 3 393.15 24.5 -13.6 1.25 3049 + 3051 3 398.15 26.6 -11.2 1 3050 + 3052 3 398.85 23.6 -17.7 1 3051 + 3053 3 401.55 23.6 -16.1 1.25 3052 + 3054 3 407.65 22.5 -17.6 1 3053 + 3055 3 410.75 22.5 -20.9 0.75 3054 + 3056 3 402.65 20.2 -21.3 0.75 3054 + 3057 3 401.55 21 -16.1 0.5 3053 + 3058 3 401.75 29.1 -20.1 0.75 3052 + 3059 3 404.45 31 -24.3 0.5 3058 + 3060 3 401.75 31.8 -20.1 0.5 3058 + 3061 3 396.05 21.9 -11.2 0.75 3050 + 3062 3 399.35 20 -12.4 0.5 3061 + 3063 3 391.55 29.6 -14.4 0.5 3049 + 3064 3 390.15 29.6 -14.5 0.5 3063 + 3065 3 395.25 31.4 -15.8 0.5 3063 + 3066 3 388.55 24 -8.9 0.25 3048 + 3067 3 383.55 25.1 -5.8 0.5 3045 + 3068 3 386.35 23.4 -5.9 0.5 3067 + 3069 3 382.15 24.4 -5.8 0.25 3067 + 3070 3 383.95 30.8 -11 0.5 3044 + 3071 3 378.85 30.3 -6.3 0.5 3043 + 3072 3 380.55 29.4 -9.1 0.5 3071 + 3073 3 378.85 32 -6.3 0.5 3071 + 3074 3 372.85 26.3 -5.9 0.5 3042 + 3075 3 370.95 25.7 -2.3 0.5 3040 + 3076 3 364.15 33.5 -5.2 0.25 3038 + 3077 3 358.85 32.8 -3.2 0.75 3037 + 3078 3 358.05 36.5 -5.6 0.5 3077 + 3079 3 353.75 37.6 -5.4 0.5 3078 + 3080 3 360.95 37.5 -5.6 0.5 3078 + 3081 3 361.95 35.2 -4.2 0.5 3077 + 3082 3 355.55 27 -9.4 0.5 3000 + 3083 3 355.55 24.4 -9 0.5 3082 + 3084 3 356.15 23 -6.5 0.5 3083 + 3085 3 354.05 22.8 -9 0.5 3083 + 3086 3 352.45 27.1 -12 0.5 2999 + 3087 3 349.05 28.6 -5.2 1.5 2996 + 3088 3 350.05 28.6 -3.4 1.5 3087 + 3089 3 352.55 28.6 0.5 1.5 3088 + 3090 3 355.65 28.6 2.7 1.5 3089 + 3091 3 357.25 28.6 2.1 1.5 3090 + 3092 3 360.65 28.6 -0.7 1.5 3091 + 3093 3 362.95 28.6 0 1.5 3092 + 3094 3 365.25 27.1 3 1.5 3093 + 3095 3 366.95 28 2.1 1.75 3094 + 3096 3 366.95 27 0 1.25 3095 + 3097 3 370.35 30.6 1.4 1.5 3096 + 3098 3 372.85 32.2 0.2 1.25 3097 + 3099 3 374.45 33.9 0.8 1.25 3098 + 3100 3 376.95 33.8 -1.9 1.25 3099 + 3101 3 378.95 34.3 -2.5 1.25 3100 + 3102 3 381.65 35.4 -5.9 1.25 3101 + 3103 3 385.25 36.7 -6.8 1.75 3102 + 3104 3 386.45 37.4 -7.5 1.75 3103 + 3105 3 388.35 34.6 -7.4 1.5 3104 + 3106 3 390.55 36.7 -6.9 1.5 3105 + 3107 3 393.45 36.6 -13.3 1 3106 + 3108 3 394.15 39.4 -18.9 0.75 3107 + 3109 3 395.85 40.5 -18.2 0.75 3108 + 3110 3 397.75 41.6 -20.8 0.75 3109 + 3111 3 398.85 42.3 -22.9 0.75 3110 + 3112 3 401.65 42.3 -24.6 1 3111 + 3113 3 403.45 41.2 -30.1 1 3112 + 3114 3 407.75 41.2 -29.7 1 3113 + 3115 3 409.55 37.9 -32.2 1 3114 + 3116 3 410.85 34.7 -34.2 0.5 3115 + 3117 3 406.55 36.2 -32.2 0.5 3115 + 3118 3 403.45 38.3 -30.1 0.5 3113 + 3119 3 404.85 35.9 -30.9 0.5 3118 + 3120 3 400.75 35.8 -29.8 0.5 3118 + 3121 3 403.25 34.4 -29.8 0.5 3120 + 3122 3 399.35 35.8 -26.6 0.25 3120 + 3123 3 399.95 43.9 -24.6 0.5 3112 + 3124 3 398.85 38.3 -22.9 0.5 3111 + 3125 3 402.05 39.2 -22.9 0.25 3124 + 3126 3 399.75 36.5 -23.4 0.5 3124 + 3127 3 397.75 37.2 -20.8 0.5 3110 + 3128 3 395.65 36.8 -18.9 0.5 3108 + 3129 3 395.45 38 -14.2 0.75 3107 + 3130 3 401.35 38 -16.3 1 3129 + 3131 3 405.35 34.5 -19.2 1 3130 + 3132 3 406.15 35.7 -21 1 3131 + 3133 3 408.25 31.5 -26.8 1 3132 + 3134 3 410.35 28.9 -29.1 0.75 3133 + 3135 3 414.55 24.7 -29.2 0.75 3134 + 3136 3 408.05 27.4 -29.1 0.5 3134 + 3137 3 403.65 31.4 -19.1 0.5 3132 + 3138 3 404.95 30.7 -18.9 0.5 3137 + 3139 3 401.85 31.4 -20.7 0.25 3137 + 3140 3 398.65 34.2 -19.7 0.5 3130 + 3141 3 396.05 30 -22.3 0.5 3140 + 3142 3 394.75 33.1 -17.3 0.5 3140 + 3143 3 396.35 34.2 -14.2 0.25 3129 + 3144 3 392.25 31.7 -11.6 0.5 3106 + 3145 3 393.75 28.3 -10.1 0.5 3144 + 3146 3 389.25 28.8 -11.6 0.5 3144 + 3147 3 389.25 26.2 -11.6 0.5 3146 + 3148 3 388.35 31.3 -8.8 0.5 3105 + 3149 3 385.25 33.5 -6.8 0.5 3103 + 3150 3 380.15 30.3 -5.9 0.5 3101 + 3151 3 376.75 29.1 -3.5 0.5 3150 + 3152 3 380.95 30.3 -5.9 0.5 3150 + 3153 3 375.45 28.7 1.5 0.5 3099 + 3154 3 376.35 25.4 -2.1 0.5 3153 + 3155 3 372.55 26.8 1.5 0.5 3153 + 3156 3 371.65 27.3 1.4 0.5 3097 + 3157 3 368.85 24.6 2.2 1.25 3095 + 3158 3 371.05 22.3 -1.4 1.5 3157 + 3159 3 374.05 19.8 -0.7 1.25 3158 + 3160 3 375.75 22.1 3.4 1.25 3159 + 3161 3 376.95 22.5 -1.4 1.25 3160 + 3162 3 378.85 23.2 -1.7 1.25 3161 + 3163 3 383.85 24.1 -1 1.25 3162 + 3164 3 385.55 23.7 -4.7 1.25 3163 + 3165 3 387.15 22.9 -5.5 1 3164 + 3166 3 390.55 22.9 -7.8 1.25 3165 + 3167 3 396.85 19.1 -10.7 1.25 3166 + 3168 3 397.45 22 -14.6 0.75 3167 + 3169 3 400.25 22.4 -14.8 1 3168 + 3170 3 403.15 22.4 -18.2 1 3169 + 3171 3 405.15 22.4 -20 1 3170 + 3172 3 407.65 19.9 -22.5 1.25 3171 + 3173 3 411.45 18.4 -26.9 0.75 3172 + 3174 3 404.95 17.9 -22.5 0.5 3172 + 3175 3 405.15 25.1 -25.9 0.75 3171 + 3176 3 404.35 25.6 -24.5 0.5 3175 + 3177 3 401.55 27.8 -24.5 0.5 3176 + 3178 3 400.95 22.7 -24.5 0.5 3176 + 3179 3 409.45 27.6 -29.2 0.5 3175 + 3180 3 403.15 18.3 -18.2 0.5 3170 + 3181 3 393.75 23.1 -15.7 0.5 3168 + 3182 3 398.95 17.3 -13.9 1.25 3167 + 3183 3 401.15 16.7 -16.7 1 3182 + 3184 3 403.65 14 -17.7 1.25 3183 + 3185 3 404.55 13.1 -15.6 1.25 3184 + 3186 3 407.85 11.7 -17.5 1.25 3185 + 3187 3 408.55 10.9 -22 0.75 3186 + 3188 3 411.65 8 -24.9 0.75 3187 + 3189 3 409.75 4.4 -23.2 0.75 3188 + 3190 3 415.15 11.6 -28.2 0.5 3188 + 3191 3 406.15 9 -22 0.5 3187 + 3192 3 406.15 6.1 -22 0.5 3191 + 3193 3 404.55 9.4 -14.9 0.5 3186 + 3194 3 405.45 5.4 -13.7 0.5 3193 + 3195 3 409.55 5.4 -13.6 0.5 3194 + 3196 3 407.05 2.7 -16.4 0.5 3194 + 3197 3 406.55 17.1 -21.7 0.5 3185 + 3198 3 401.55 12.1 -20.1 0.5 3184 + 3199 3 402.65 6.2 -20.1 0.5 3198 + 3200 3 400.05 9.9 -20.1 0.5 3198 + 3201 3 400.05 14.3 -14 0.25 3183 + 3202 3 398.45 10.7 -15.6 0.25 3201 + 3203 3 400.55 8 -15.6 0.25 3202 + 3204 3 396.25 10.3 -16.5 0.25 3202 + 3205 3 398.25 14.3 -14 0.25 3201 + 3206 3 396.05 14.9 -17.3 0.5 3182 + 3207 3 392.65 14.7 -17.3 0.5 3206 + 3208 3 399.25 12.5 -14.9 0.25 3206 + 3209 3 391.55 18.6 -4.9 0.25 3166 + 3210 3 386.25 25.6 -7.7 0.5 3164 + 3211 3 387.55 19.8 -4.7 0.75 3163 + 3212 3 390.35 18.7 -5.4 1 3211 + 3213 3 392.55 17.8 -4.2 0.5 3212 + 3214 3 395.75 15.1 -7.4 0.5 3213 + 3215 3 397.65 13.3 -7.8 0.5 3214 + 3216 3 392.55 13.5 -7.4 0.5 3214 + 3217 3 390.35 14.9 -8.7 0.5 3212 + 3218 3 392.15 12.2 -7 0.5 3217 + 3219 3 388.45 13 -8.2 0.5 3217 + 3220 3 383.75 18.3 -5.2 0.5 3211 + 3221 3 378.85 17.3 -4.1 0.5 3162 + 3222 3 379.05 15.9 -4.1 0.5 3221 + 3223 3 382.85 14.2 -2.3 0.5 3222 + 3224 3 378.35 16.4 -2.9 0.5 3222 + 3225 3 376.25 17.3 -3.6 0.5 3161 + 3226 3 372.15 23.9 -2.5 0.5 3160 + 3227 3 374.05 18.5 -1.7 0.5 3159 + 3228 3 370.45 18 -7.1 0.5 3227 + 3229 3 375.85 16.2 -3.5 0.5 3227 + 3230 3 365.75 22.4 -4.7 0.5 3157 + 3231 3 362.55 23.4 -3.1 0.5 3093 + 3232 3 358.75 23.4 -3.1 0.5 3231 + 3233 3 358.15 24.1 -1.1 0.5 3091 + 3234 3 359.65 22.1 -1.4 0.5 3233 + 3235 3 355.65 22.9 -1.1 0.25 3233 + 3236 3 345.75 24.6 -0.2 0.25 3088 + 3237 3 343.45 36.3 -3.9 0.75 2995 + 3238 3 346.65 38 -3.7 1 3237 + 3239 3 350.05 40.3 -6.9 0.75 3238 + 3240 3 355.65 38.6 -8.2 0.75 3239 + 3241 3 352.75 37 -3.2 0.5 3239 + 3242 3 357.15 35.5 -3.2 0.5 3241 + 3243 3 360.65 37.2 -0.8 0.5 3242 + 3244 3 357.15 32.4 -3.3 0.5 3242 + 3245 3 352.75 34.6 -3.4 0.5 3241 + 3246 3 348.75 35.4 -9.1 0.5 3238 + 3247 3 337.15 35.7 -7.7 0.5 2993 + 3248 3 338.55 38.9 -7.7 0.5 3247 + 3249 3 338.55 41.6 -7.7 0.5 3248 + 3250 3 340.45 35.8 -7.7 0.25 3248 + 3251 3 329.15 27.7 -9.5 0.75 2992 + 3252 3 333.55 26 -10.3 0.75 3251 + 3253 3 336.45 26.7 -11 0.75 3252 + 3254 3 341.35 26.7 -5.5 0.75 3253 + 3255 3 342.35 24.1 -5.5 0.75 3254 + 3256 3 345.95 24.1 -3 0.75 3255 + 3257 3 349.05 25.5 1.1 0.75 3256 + 3258 3 352.75 21.7 -2.4 0.75 3257 + 3259 3 356.35 23.6 -2.7 0.5 3258 + 3260 3 359.45 23.6 -2.7 0.5 3259 + 3261 3 356.35 20 -2.7 0.5 3259 + 3262 3 354.25 19.4 -4.8 0.25 3258 + 3263 3 345.95 20.6 -0.9 0.5 3256 + 3264 3 342.35 20.9 -7 0.5 3255 + 3265 3 345.05 21.9 -9.1 0.5 3264 + 3266 3 349.65 22.6 -5.7 0.5 3265 + 3267 3 349.65 24.8 -5.5 0.5 3266 + 3268 3 352.45 20 -5.6 0.5 3266 + 3269 3 347.25 16.9 -9.1 0.5 3265 + 3270 3 344.45 17.1 -7 0.25 3264 + 3271 3 336.45 21.9 -13.2 0.5 3253 + 3272 3 334.55 18.9 -16.4 0.5 3271 + 3273 3 339.35 20.6 -19 0.5 3272 + 3274 3 341.45 15.7 -19 0.5 3273 + 3275 3 332.85 16.9 -16.4 0.5 3272 + 3276 3 338.85 23.6 -11.3 0.5 3271 + 3277 3 329.35 22 -15.4 0.5 3252 + 3278 3 329.35 19.2 -15.4 0.5 3277 + 3279 3 330.35 36.7 -19.1 0.5 2991 + 3280 3 331.55 39.5 -19.1 0.5 3279 + 3281 3 325.65 38.1 -14.9 0.25 3279 + 3282 3 322.35 38.8 -22.9 0.5 2990 + 3283 3 325.55 41 -22.9 0.5 3282 + 3284 3 320.25 40.2 -22.9 0.5 3282 + 3285 3 321.85 30.4 -18.5 0.5 2989 + 3286 3 311.25 39.7 -23.4 0.5 2988 + 3287 3 308.55 36.6 -29.1 0.5 2987 + 3288 3 308.45 38.1 -27.7 0.5 3287 + 3289 3 306.35 36.6 -29.1 0.5 3287 + 3290 3 308.05 35.3 -30 0.5 2986 + 3291 3 301.65 31.8 -29.6 0.5 2985 + 3292 3 299.15 33.3 -31.1 0.5 3291 + 3293 3 305.95 35.6 -28 0.5 3291 + 3294 3 302.25 37.8 -28 0.5 3293 + 3295 3 305.15 23.2 -34.2 0.5 2984 + 3296 3 306.65 25.3 -34.2 0.5 3295 + 3297 3 305.15 21.4 -34.2 0.25 3295 + 3298 3 299.95 31.4 -39.1 0.5 2983 + 3299 3 302.25 32.9 -39.1 0.25 3298 + 3300 3 296.55 31.4 -39.1 0.5 3298 + 3301 3 302.15 20.6 -37.3 0.5 2982 + 3302 3 306.25 17.9 -32.2 0.5 3301 + 3303 3 298.25 19.7 -33.7 0.5 3301 + 3304 3 293.15 28.5 -28.4 1.25 2981 + 3305 3 295.85 32.9 -29.7 1 3304 + 3306 3 298.05 34.8 -29.7 1 3305 + 3307 3 301.15 34.5 -30.1 0.75 3306 + 3308 3 304.65 33.3 -24.7 0.75 3307 + 3309 3 307.05 36.4 -26 0.5 3308 + 3310 3 310.35 37.9 -27.2 0.5 3309 + 3311 3 307.05 38 -24 0.25 3309 + 3312 3 305.05 29.5 -31.6 0.75 3307 + 3313 3 288.55 19 -43.8 0.5 2980 + 3314 3 284.75 21 -47.2 0.5 2978 + 3315 3 279.45 30.9 -51.5 0.5 2977 + 3316 3 281.95 32.5 -51.5 0.5 3315 + 3317 3 276.25 31.8 -51.5 0.25 3315 + 3318 3 276.35 30.3 -50.7 0.5 2976 + 3319 3 273.75 32.1 -50.5 0.5 3318 + 3320 3 276.75 34.5 -50.5 0.5 3319 + 3321 3 272.05 32.1 -51.4 0.5 3319 + 3322 3 270.15 19 -54.4 0.5 2975 + 3323 3 274.35 15.4 -56.5 0.5 3322 + 3324 3 275.65 13.2 -56.7 0.5 3323 + 3325 3 275.65 10.9 -55.2 0.5 3324 + 3326 3 266.55 17.6 -58.2 0.5 3322 + 3327 3 263.65 18.1 -58.2 0.5 3326 + 3328 3 253.15 22.4 -61 0.5 1809 + 3329 3 264.55 13 -60 0.5 1808 + 3330 3 267.35 16.6 -56.5 0.5 3329 + 3331 3 266.85 12.7 -57.8 0.5 3330 + 3332 3 270.35 14.8 -60.2 0.5 3331 + 3333 3 263.85 11.1 -54.5 0.5 3331 + 3334 3 269.05 18.2 -55.5 0.5 3330 + 3335 3 264.55 11.8 -61.4 0.25 3329 + 3336 3 251.65 12.2 -66 0.5 1807 + 3337 3 250.95 15.8 -66.2 0.5 3336 + 3338 3 248.85 18.7 -66.2 0.5 3337 + 3339 3 249.95 20.7 -68.2 0.5 3338 + 3340 3 253.25 23.7 -68.3 0.5 3339 + 3341 3 246.85 22.7 -65.2 0.5 3339 + 3342 3 249.25 12.2 -63.9 0.5 3336 + 3343 3 259.75 6 -62.5 0.5 1806 + 3344 3 259.45 0.7 -67.2 0.5 3343 + 3345 3 261.15 6.8 -62.5 0.25 3343 + 3346 3 251.15 2.7 -70.8 0.5 1805 + 3347 3 251.65 0.7 -72.3 0.5 3346 + 3348 3 251.65 -2.1 -73.6 0.5 3347 + 3349 3 246.95 0.7 -72.3 0.5 3347 + 3350 3 249.55 6.3 -70.2 0.5 3346 + 3351 3 247.15 2.7 -74.1 0.25 3350 + 3352 3 247.85 8.8 -72.4 0.25 3350 + 3353 3 259.05 -0.2 -64.1 0.5 1804 + 3354 3 259.05 3.2 -68.7 0.5 3353 + 3355 3 256.75 4.8 -66.1 0.5 3354 + 3356 3 260.75 -3.7 -67.7 0.25 3353 + 3357 3 246.45 -10.8 -76 0.5 1801 + 3358 3 254.45 -13.8 -78.7 2 1799 + 3359 3 256.15 -9.7 -80.2 2 3358 + 3360 3 259.15 -7.2 -77.2 2 3359 + 3361 3 260.45 -4.4 -70.5 2.25 3360 + 3362 3 264.35 -2.8 -72.8 2.25 3361 + 3363 3 266.15 -3.3 -69.3 2.5 3362 + 3364 3 267.35 -3.7 -68.2 2.75 3363 + 3365 3 267.35 -4.1 -68 2.5 3364 + 3366 3 267.35 -4.1 -68.2 1.5 3365 + 3367 3 270.45 -1.5 -71.7 1.5 3366 + 3368 3 272.35 0.2 -68.9 1.5 3367 + 3369 3 273.75 1.9 -71.5 1.5 3368 + 3370 3 274.45 4.6 -68 1.5 3369 + 3371 3 278.05 7 -68 1.5 3370 + 3372 3 277.15 9.9 -67.4 1.75 3371 + 3373 3 279.75 11.4 -69.1 1.75 3372 + 3374 3 277.85 13.9 -64 1.25 3373 + 3375 3 281.25 16.9 -65.9 1.5 3374 + 3376 3 283.35 19.2 -65.7 1.25 3375 + 3377 3 285.85 24.7 -62.4 1.5 3376 + 3378 3 288.95 27.7 -58.7 1.5 3377 + 3379 3 290.65 31.6 -57.7 1.5 3378 + 3380 3 292.35 32.8 -57.2 1.5 3379 + 3381 3 291.95 35.3 -51.9 1.5 3380 + 3382 3 297.15 37.8 -53.7 1.5 3381 + 3383 3 295.85 40.2 -53.1 1.5 3382 + 3384 3 295.85 39.1 -49.5 1.75 3383 + 3385 3 300.05 43 -49.4 2 3384 + 3386 3 303.75 45.1 -44.1 1.75 3385 + 3387 3 306.85 46.5 -46.5 2 3386 + 3388 3 308.55 45.4 -40.4 2 3387 + 3389 3 314.25 45.4 -39.5 2.25 3388 + 3390 3 316.75 46.5 -41.2 2 3389 + 3391 3 319.45 46.5 -36.7 1.75 3390 + 3392 3 323.15 45 -32.8 1.5 3391 + 3393 3 328.55 47.7 -30.5 1.75 3392 + 3394 3 333.45 46.1 -28.8 2.25 3393 + 3395 3 335.05 46.1 -31.1 2.25 3394 + 3396 3 337.95 48.3 -31.5 1.75 3395 + 3397 3 339.85 46.3 -27.1 1.75 3396 + 3398 3 344.45 48.5 -24.7 1.75 3397 + 3399 3 347.45 48.2 -23.9 1.75 3398 + 3400 3 348.75 48.7 -17.4 1.25 3399 + 3401 3 352.75 47.9 -17.4 1.25 3400 + 3402 3 355.95 51 -13.3 1 3401 + 3403 3 358.15 51.8 -13.7 1 3402 + 3404 3 359.25 53.9 -14.7 1 3403 + 3405 3 358.25 57.2 -17.5 1.5 3404 + 3406 3 361.25 59.9 -19.6 1.5 3405 + 3407 3 365.25 64 -24.7 1.5 3406 + 3408 3 365.25 65.9 -21.9 1 3407 + 3409 3 367.35 67.9 -22.3 1.25 3408 + 3410 3 371.15 70.5 -28 1.25 3409 + 3411 3 372.75 70.5 -30.6 1.25 3410 + 3412 3 374.85 67.4 -33 1.5 3411 + 3413 3 377.05 65.5 -29.9 1 3412 + 3414 3 381.85 64.5 -34.5 1.25 3413 + 3415 3 384.95 63.8 -34 1.5 3414 + 3416 3 386.35 61.6 -36.8 1.75 3415 + 3417 3 388.95 57.4 -34.7 1 3416 + 3418 3 390.65 54.7 -34.6 0.5 3417 + 3419 3 384.35 57.4 -33.2 0.5 3417 + 3420 3 391.05 64.7 -39.6 1 3416 + 3421 3 393.75 65.6 -36 0.75 3420 + 3422 3 392.75 59.2 -39.6 0.5 3420 + 3423 3 380.65 59.8 -34.1 0.75 3415 + 3424 3 377.55 61.2 -32.7 0.75 3423 + 3425 3 375.85 63.5 -32.7 0.75 3424 + 3426 3 384.65 57.4 -38.4 0.5 3423 + 3427 3 381.85 69.1 -37.3 0.75 3414 + 3428 3 380.35 70.8 -37.3 0.5 3427 + 3429 3 383.45 70.7 -33.9 0.5 3427 + 3430 3 377.25 72.7 -33.1 1 3412 + 3431 3 372.85 71.1 -36.5 0.75 3430 + 3432 3 369.35 74.7 -36.5 0.5 3431 + 3433 3 365.65 73 -32.9 0.5 3432 + 3434 3 369.35 76.9 -33.6 0.5 3432 + 3435 3 369.25 73 -36.3 0.5 3431 + 3436 3 377.25 75.6 -37.3 1 3430 + 3437 3 372.75 65 -31.4 0.75 3411 + 3438 3 364.45 69.4 -21.8 0.5 3409 + 3439 3 366.55 61 -26.8 1.25 3407 + 3440 3 374.15 63.8 -27.5 1 3439 + 3441 3 375.45 60.1 -28.9 1 3440 + 3442 3 377.25 61.3 -28.9 0.75 3441 + 3443 3 379.95 62.3 -25.9 1 3442 + 3444 3 382.05 61.1 -31 1 3443 + 3445 3 385.35 58.4 -26.4 0.75 3444 + 3446 3 385.35 56.5 -26.4 0.5 3445 + 3447 3 380.25 58.3 -26.4 0.25 3446 + 3448 3 386.95 57.2 -31.6 0.5 3446 + 3449 3 384.25 64.2 -33.3 0.75 3444 + 3450 3 380.95 59.2 -25.9 0.5 3443 + 3451 3 378.75 58.4 -28.9 0.25 3442 + 3452 3 373.65 58.6 -28.9 0.5 3441 + 3453 3 375.35 59.4 -29.6 0.5 3440 + 3454 3 370.85 57.9 -25.3 0.75 3439 + 3455 3 372.85 57.9 -27.6 0.5 3454 + 3456 3 366.75 55.8 -26.9 0.5 3454 + 3457 3 364.65 57.2 -18.4 0.5 3405 + 3458 3 367.95 58.5 -24.8 0.5 3457 + 3459 3 371.15 56.6 -20.6 0.5 3458 + 3460 3 367.95 59.8 -24.8 0.25 3458 + 3461 3 366.35 53.5 -18.1 0.25 3457 + 3462 3 355.35 55.2 -19.4 0.5 3404 + 3463 3 360.25 50.1 -17.8 0.25 3403 + 3464 3 352.75 52.7 -21.6 0.5 3402 + 3465 3 353.45 47.7 -14.4 0.75 3400 + 3466 3 355.85 47.7 -16.8 1 3465 + 3467 3 357.55 49.9 -13.4 1 3466 + 3468 3 360.65 52.1 -13.5 1 3467 + 3469 3 362.35 54.2 -16.9 1 3468 + 3470 3 365.25 56.3 -14.9 0.75 3469 + 3471 3 365.55 53.9 -15.5 0.75 3470 + 3472 3 369.15 55.5 -16.1 1 3471 + 3473 3 373.95 53.3 -20.5 1.25 3472 + 3474 3 376.75 51.9 -17.9 1.25 3473 + 3475 3 379.85 51.1 -24.7 1.25 3474 + 3476 3 383.05 52.9 -25 1.25 3475 + 3477 3 385.15 52.9 -29.7 1.25 3476 + 3478 3 388.25 50.5 -31.5 1 3477 + 3479 3 391.35 47.2 -32.8 0.75 3478 + 3480 3 398.15 43.2 -30.8 0.75 3479 + 3481 3 402.45 44 -34.3 0.75 3480 + 3482 3 403.95 42.7 -31.2 0.5 3481 + 3483 3 404.45 39.7 -34.3 0.5 3481 + 3484 3 399.85 38 -34.4 0.5 3480 + 3485 3 393.05 50 -32.8 0.5 3479 + 3486 3 390.25 55.7 -28.1 0.5 3478 + 3487 3 385.15 54.8 -29.7 0.5 3477 + 3488 3 377.85 47.8 -22.6 0.5 3475 + 3489 3 377.85 44.9 -25.3 0.5 3488 + 3490 3 374.55 47.8 -25.1 0.25 3488 + 3491 3 376.75 49.3 -19 0.5 3474 + 3492 3 371.25 59.2 -24.1 0.5 3472 + 3493 3 373.05 59.2 -24.9 0.75 3492 + 3494 3 376.85 59.2 -26.1 1 3493 + 3495 3 381.35 59.2 -30.3 0.75 3494 + 3496 3 385.35 54.2 -32.3 0.5 3495 + 3497 3 386.65 54.2 -33.5 0.5 3496 + 3498 3 388.45 57.5 -34.6 0.5 3497 + 3499 3 387.55 52.8 -33.5 0.25 3497 + 3500 3 382.75 61.5 -30.3 0.5 3495 + 3501 3 385.65 59.5 -33.4 0.5 3500 + 3502 3 382.75 63.5 -30.5 0.5 3500 + 3503 3 379.15 54.5 -29.1 0.5 3494 + 3504 3 367.65 60.2 -24.5 0.5 3492 + 3505 3 365.25 58 -24.5 0.5 3504 + 3506 3 367.65 61.5 -24.5 0.25 3504 + 3507 3 365.55 51 -21.3 0.5 3471 + 3508 3 368.35 51 -19.1 0.25 3507 + 3509 3 364.35 49.9 -24.1 0.5 3507 + 3510 3 365.25 59 -22.3 0.5 3470 + 3511 3 364.15 50.6 -15.2 0.5 3469 + 3512 3 365.65 50.6 -15.2 0.25 3511 + 3513 3 363.55 49.8 -15.2 0.5 3511 + 3514 3 363.15 48.4 -20.1 0.75 3468 + 3515 3 358.95 45.9 -19.6 0.5 3467 + 3516 3 355.85 46 -16.3 0.5 3466 + 3517 3 353.85 50.2 -21.6 0.75 3399 + 3518 3 356.75 46.8 -20.1 1 3517 + 3519 3 358.55 48 -19.6 1.25 3518 + 3520 3 358.95 44.1 -22.3 1.25 3519 + 3521 3 360.25 43.5 -21.3 1.5 3520 + 3522 3 367.75 39.7 -17.5 1.25 3521 + 3523 3 370.35 39.7 -19.7 1 3522 + 3524 3 375.75 39.2 -22.3 1 3523 + 3525 3 375.55 39.2 -21.4 1 3524 + 3526 3 378.85 42.4 -24.2 1 3525 + 3527 3 383.55 45.1 -24 1 3526 + 3528 3 387.95 41.2 -28.3 0.75 3527 + 3529 3 391.55 41.2 -29.7 0.5 3528 + 3530 3 395.95 40.6 -32 0.5 3529 + 3531 3 400.85 39.8 -30.1 0.75 3530 + 3532 3 403.45 40.5 -31.9 0.5 3531 + 3533 3 403.05 38.2 -30.1 0.5 3531 + 3534 3 395.95 45 -32 0.5 3530 + 3535 3 391.55 45.3 -29.7 0.5 3529 + 3536 3 385.25 40.8 -24 0.5 3527 + 3537 3 382.35 37.6 -24.2 0.5 3526 + 3538 3 383.95 39.2 -23.7 0.5 3537 + 3539 3 385.95 39.2 -23.6 0.5 3538 + 3540 3 387.35 35.6 -25.1 0.75 3539 + 3541 3 389.45 38.3 -25.1 0.5 3540 + 3542 3 385.95 40.4 -23.6 0.5 3539 + 3543 3 382.25 36.3 -23.7 0.25 3538 + 3544 3 379.05 36.3 -24.2 0.5 3537 + 3545 3 373.45 44 -26.9 0.5 3525 + 3546 3 373.65 38.3 -19.1 0.75 3523 + 3547 3 376.65 39.9 -20.4 0.75 3546 + 3548 3 377.85 36.8 -20.3 0.75 3547 + 3549 3 377.65 35.2 -16.2 0.5 3548 + 3550 3 376.35 31.9 -19.4 0.5 3549 + 3551 3 380.25 33.1 -19.4 0.5 3550 + 3552 3 375.25 30.1 -19.4 0.5 3550 + 3553 3 382.65 33 -21.1 0.5 3549 + 3554 3 386.05 32 -21.1 0.5 3553 + 3555 3 384.55 36.4 -21.1 0.25 3553 + 3556 3 374.55 35.5 -20.3 0.5 3548 + 3557 3 371.35 36.5 -16.8 0.5 3546 + 3558 3 369.85 34.9 -16.8 0.5 3557 + 3559 3 375.45 36 -16.8 0.5 3557 + 3560 3 364.15 47.7 -21.6 0.75 3521 + 3561 3 366.45 50.2 -18.9 0.75 3560 + 3562 3 368.05 48.6 -23 0.75 3561 + 3563 3 371.75 51.6 -25.5 1 3562 + 3564 3 373.15 51.6 -23.2 1.25 3563 + 3565 3 374.85 53 -26.5 1.25 3564 + 3566 3 374.65 53 -23.5 1.25 3565 + 3567 3 378.55 50.7 -24.7 1 3566 + 3568 3 381.65 50.1 -29.9 1.25 3567 + 3569 3 386.45 51.7 -30.7 1.25 3568 + 3570 3 388.25 45.9 -36.3 0.75 3569 + 3571 3 390.45 42.6 -35.6 0.5 3570 + 3572 3 386.55 40.4 -35.6 0.5 3571 + 3573 3 392.15 46.2 -36.3 0.5 3570 + 3574 3 394.55 45.1 -36.3 0.5 3573 + 3575 3 389.35 53.5 -31 1 3569 + 3576 3 391.95 50.9 -34.2 1 3575 + 3577 3 395.25 49.4 -38.8 1 3576 + 3578 3 398.95 48.5 -39.1 1.25 3577 + 3579 3 397.55 42.2 -38.7 0.75 3578 + 3580 3 397.55 41 -42.3 0.75 3579 + 3581 3 400.25 38.2 -42.3 0.5 3580 + 3582 3 401.55 41 -42.3 0.25 3580 + 3583 3 403.65 44.8 -43.9 1 3578 + 3584 3 402.45 43.3 -44.9 0.75 3583 + 3585 3 407.55 41.3 -48.3 0.5 3584 + 3586 3 402.45 40.8 -44.9 0.5 3584 + 3587 3 406.55 47.8 -42.6 0.5 3583 + 3588 3 396.15 52.6 -42.4 0.5 3577 + 3589 3 393.55 46.4 -37.3 0.5 3576 + 3590 3 381.65 47.8 -26.3 0.5 3568 + 3591 3 378.55 47.6 -27.7 0.5 3567 + 3592 3 375.65 46.4 -27.7 0.5 3591 + 3593 3 374.65 48.4 -24 0.25 3566 + 3594 3 373.15 47.7 -23.2 0.75 3564 + 3595 3 368.05 45.9 -22.9 0.5 3562 + 3596 3 368.85 44.5 -21.7 0.5 3595 + 3597 3 365.05 46.9 -22.9 0.5 3595 + 3598 3 356.45 42.6 -19.1 0.5 3520 + 3599 3 347.05 43.2 -26.4 0.75 3398 + 3600 3 349.85 41.5 -26.5 0.5 3599 + 3601 3 353.05 42.9 -30.1 0.5 3600 + 3602 3 349.95 39.3 -29.2 0.25 3601 + 3603 3 349.95 37.4 -29.2 0.5 3602 + 3604 3 354.15 39.2 -29.2 0.25 3602 + 3605 3 353.95 44.3 -30.1 0.25 3601 + 3606 3 347.65 39.8 -31.3 0.25 3600 + 3607 3 350.05 37.3 -31.3 0.5 3606 + 3608 3 345.65 38.6 -31.3 0.25 3606 + 3609 3 342.85 41.6 -31 0.25 3599 + 3610 3 339.85 43.5 -28 0.25 3397 + 3611 3 340.55 42.5 -27.5 0.25 3610 + 3612 3 343.25 40.4 -31.7 0.25 3611 + 3613 3 337.35 40.9 -27.5 0.25 3611 + 3614 3 342.05 43.5 -28 0.25 3610 + 3615 3 337.95 51.6 -30.8 0.25 3396 + 3616 3 335.05 43.6 -31.5 0.25 3395 + 3617 3 333.45 51.5 -35.1 0.5 3394 + 3618 3 329.75 51.5 -30.9 0.5 3393 + 3619 3 331.25 52.6 -33.5 0.5 3618 + 3620 3 335.15 53.3 -33.5 0.5 3619 + 3621 3 335.15 55.1 -33.5 0.5 3620 + 3622 3 332.85 54.3 -31.8 0.5 3619 + 3623 3 324.45 49.6 -40.7 0.5 3392 + 3624 3 326.65 49.6 -37.5 0.5 3623 + 3625 3 322.25 51.4 -37.6 0.5 3623 + 3626 3 320.55 52.2 -34.4 0.5 3391 + 3627 3 323.55 49.4 -37.9 0.5 3626 + 3628 3 321.35 53.7 -34.4 0.25 3626 + 3629 3 316.75 52.4 -41.4 0.25 3390 + 3630 3 313.25 53.6 -39.1 0.25 3629 + 3631 3 314.25 41.2 -38.5 0.5 3389 + 3632 3 316.35 39.1 -41.6 0.5 3631 + 3633 3 318.95 41.4 -37.5 0.5 3632 + 3634 3 320.65 43.4 -37.8 0.5 3633 + 3635 3 321.65 36.8 -42.4 0.25 3633 + 3636 3 316.35 36.7 -42.6 0.5 3632 + 3637 3 316.35 34.1 -43 0.5 3636 + 3638 3 313.05 52.9 -40.7 0.5 3388 + 3639 3 313.05 54.5 -42.9 0.5 3638 + 3640 3 315.15 56.2 -37.4 0.5 3639 + 3641 3 308.85 54.5 -41.1 0.25 3639 + 3642 3 304.95 50.6 -47.7 0.75 3387 + 3643 3 304.95 49.7 -47.6 0.75 3642 + 3644 3 306.35 54.4 -44.7 0.75 3643 + 3645 3 304.45 57 -43.7 0.75 3644 + 3646 3 306.75 58.7 -47 0.75 3645 + 3647 3 306.75 59.2 -44 0.5 3646 + 3648 3 310.55 60.1 -44.4 0.5 3647 + 3649 3 306.75 56.2 -44 0.25 3647 + 3650 3 303.05 60.7 -46.8 0.5 3646 + 3651 3 308.25 60.7 -46.8 0.5 3650 + 3652 3 301.95 61.9 -46.8 0.5 3650 + 3653 3 308.45 54.1 -43.7 0.5 3645 + 3654 3 302.75 54.4 -50.1 0.5 3644 + 3655 3 300.65 55.8 -50.1 0.5 3654 + 3656 3 302.35 49.7 -44.5 0.25 3643 + 3657 3 299.15 48.3 -46 0.25 3386 + 3658 3 304.65 39.7 -52.8 0.5 3385 + 3659 3 306.55 38.3 -54.8 0.5 3658 + 3660 3 308.45 41.8 -50.8 0.5 3659 + 3661 3 306.55 36.6 -56.3 0.5 3659 + 3662 3 301.35 37.6 -49.8 0.5 3384 + 3663 3 302.55 40.7 -51.5 0.25 3662 + 3664 3 301.35 36.9 -49.8 0.5 3662 + 3665 3 300.45 35.1 -55.2 0.5 3383 + 3666 3 295.55 30.8 -59.8 0.5 3381 + 3667 3 286.65 31.6 -59.5 0.5 3379 + 3668 3 283.55 27.7 -63 0.5 3378 + 3669 3 280.55 26.1 -65.3 0.25 3668 + 3670 3 279.45 25.1 -65.3 0.25 3669 + 3671 3 283.55 30 -63 0.5 3668 + 3672 3 286.95 16.4 -67.9 0.5 3376 + 3673 3 290.45 20.2 -66.9 0.5 3672 + 3674 3 288.15 15 -68.6 0.25 3672 + 3675 3 282.55 11.4 -64.7 0.5 3373 + 3676 3 285.15 12.7 -67 0.25 3675 + 3677 3 285.15 15.4 -67 0.25 3676 + 3678 3 286.95 10.2 -67 0.25 3676 + 3679 3 283.45 6.9 -67.8 0.25 3675 + 3680 3 280.05 4.1 -67.8 0.25 3679 + 3681 3 273.35 11.8 -68.7 0.5 3372 + 3682 3 273.35 12.8 -70.9 0.5 3681 + 3683 3 275.35 14.7 -71.7 0.5 3682 + 3684 3 271.25 17.3 -71.7 0.5 3683 + 3685 3 274.65 20.1 -75.8 0.5 3684 + 3686 3 271.95 17.3 -73.8 0.25 3684 + 3687 3 271.75 10.5 -70.9 0.25 3682 + 3688 3 272.95 3.3 -75.8 0.5 3370 + 3689 3 276.85 6.9 -71.7 0.5 3688 + 3690 3 271.25 5.5 -75.8 0.25 3688 + 3691 3 268.95 3.4 -70.8 0.75 3369 + 3692 3 267.65 6.5 -72.8 0.5 3691 + 3693 3 271.35 10.8 -76.7 0.5 3692 + 3694 3 264.75 6.5 -78.5 0.5 3692 + 3695 3 263.65 6.5 -75.9 0.25 3694 + 3696 3 268.25 1.6 -78.5 0.5 3694 + 3697 3 267.75 2.1 -71.8 0.25 3691 + 3698 3 273.95 -3.6 -65.3 0.5 3368 + 3699 3 270.75 -4.6 -68.5 1.75 3365 + 3700 3 272.45 -5.2 -66.1 1.25 3699 + 3701 3 274.45 -5 -66.8 1.25 3700 + 3702 3 276.35 -2.2 -65.3 1.5 3701 + 3703 3 278.05 -1.2 -64.3 1.25 3702 + 3704 3 278.05 1.9 -60.6 1.5 3703 + 3705 3 282.85 3.4 -55.9 1.5 3704 + 3706 3 281.25 5.4 -55.9 1.5 3705 + 3707 3 285.35 8.5 -53.9 1.25 3706 + 3708 3 287.35 10.1 -53.9 1.5 3707 + 3709 3 288.85 11.6 -55.8 1.5 3708 + 3710 3 291.55 13.2 -53.9 1.25 3709 + 3711 3 290.75 15.8 -52.3 1.25 3710 + 3712 3 293.95 15.4 -49.3 1.5 3711 + 3713 3 295.55 15.4 -44 1.5 3712 + 3714 3 298.65 14.7 -44 1.25 3713 + 3715 3 301.15 18.5 -45.9 2 3714 + 3716 3 302.35 19.5 -42.3 2.25 3715 + 3717 3 301.65 18.2 -45.2 2 3716 + 3718 3 303.85 20.6 -41.9 2 3717 + 3719 3 305.75 21.6 -43.7 2 3718 + 3720 3 307.15 23 -44.3 1.5 3719 + 3721 3 306.65 27.4 -42.2 1.5 3720 + 3722 3 309.45 30.7 -39.8 1.5 3721 + 3723 3 310.35 32.1 -40.9 1.5 3722 + 3724 3 311.85 35.2 -38.3 1.5 3723 + 3725 3 315.75 36.5 -40.8 1.5 3724 + 3726 3 317.55 37.5 -40.1 1.25 3725 + 3727 3 318.75 40.3 -37.1 1.25 3726 + 3728 3 320.45 41.6 -38.6 1.5 3727 + 3729 3 321.65 44.2 -39.9 1.25 3728 + 3730 3 323.45 46 -38.1 1.5 3729 + 3731 3 325.85 47.9 -36.4 1.25 3730 + 3732 3 327.65 50.7 -37.3 1.25 3731 + 3733 3 329.85 54.5 -36.6 1.25 3732 + 3734 3 333.65 56.8 -34.3 1.25 3733 + 3735 3 336.55 58.7 -33.6 1.25 3734 + 3736 3 338.45 60.5 -36.6 1.5 3735 + 3737 3 341.05 61.4 -36.7 1.25 3736 + 3738 3 345.45 64.6 -38.1 1.5 3737 + 3739 3 347.75 66.7 -36.6 1.5 3738 + 3740 3 350.85 68.5 -38.6 1.5 3739 + 3741 3 353.15 67.7 -40.3 1.25 3740 + 3742 3 357.75 70.6 -42.4 1.25 3741 + 3743 3 360.85 72.3 -42.8 1.25 3742 + 3744 3 362.95 72.3 -43.1 1 3743 + 3745 3 365.65 69.9 -42.4 1 3744 + 3746 3 368.85 70.5 -46.6 1 3745 + 3747 3 371.15 69.6 -46.4 1 3746 + 3748 3 373.45 71.4 -44 0.75 3747 + 3749 3 377.55 67.3 -48.3 0.5 3748 + 3750 3 380.35 68.6 -54.2 0.5 3749 + 3751 3 375.25 63.9 -48.3 0.5 3749 + 3752 3 374.65 73.9 -45.9 0.5 3748 + 3753 3 372.65 67.9 -46.4 0.5 3747 + 3754 3 366.85 67.6 -47.7 0.5 3745 + 3755 3 359.85 74.1 -43.1 0.5 3744 + 3756 3 358.85 68.6 -42.8 0.5 3743 + 3757 3 357.15 66.7 -42.8 0.5 3756 + 3758 3 361.85 67 -38.1 0.5 3756 + 3759 3 351.45 70.8 -39.3 0.5 3740 + 3760 3 352.55 72.7 -41.9 0.5 3759 + 3761 3 353.25 74.1 -41.2 0.5 3760 + 3762 3 355.25 75.3 -42 0.75 3761 + 3763 3 356.85 78.1 -43.3 0.75 3762 + 3764 3 359.15 79.5 -43.8 0.75 3763 + 3765 3 361.05 82.2 -49 1 3764 + 3766 3 362.95 81.6 -49.8 0.75 3765 + 3767 3 366.55 85 -48.2 0.5 3766 + 3768 3 362.75 85 -52.3 0.5 3767 + 3769 3 359.75 83.4 -49.3 0.5 3768 + 3770 3 358.05 85.8 -49.3 0.5 3769 + 3771 3 362.75 88 -49 0.5 3768 + 3772 3 369.05 83 -50.8 0.5 3767 + 3773 3 360.45 83.6 -49.8 0.5 3766 + 3774 3 357.95 84.5 -46.1 0.5 3765 + 3775 3 356.45 86.9 -45.9 0.5 3774 + 3776 3 359.95 86.9 -47.3 0.5 3775 + 3777 3 353.05 88.6 -44.8 0.5 3775 + 3778 3 355.25 84.5 -46.1 0.25 3774 + 3779 3 352.75 80.1 -42.6 0.5 3763 + 3780 3 351.75 81.6 -44.6 0.5 3779 + 3781 3 354.35 83.7 -44.6 0.5 3780 + 3782 3 349.55 82.2 -44.6 0.25 3780 + 3783 3 356.55 72.7 -37.9 0.5 3762 + 3784 3 357.65 74.4 -41.5 0.5 3783 + 3785 3 356.55 70.4 -37.9 0.5 3783 + 3786 3 353.85 69.8 -41.9 0.5 3760 + 3787 3 348.05 72.2 -39.8 0.5 3759 + 3788 3 350.95 62.2 -36.6 0.5 3739 + 3789 3 353.25 64.4 -36.1 0.5 3788 + 3790 3 355.55 60.6 -36.1 0.5 3789 + 3791 3 350.95 60.6 -36.6 0.5 3788 + 3792 3 343.85 57.2 -31.3 0.5 3737 + 3793 3 336.05 62.6 -34.4 0.5 3736 + 3794 3 337.35 65 -34.4 0.5 3793 + 3795 3 338.25 66.9 -34.4 0.5 3794 + 3796 3 334.15 66.1 -37.6 0.25 3794 + 3797 3 333.45 62.6 -37.1 0.5 3793 + 3798 3 331.95 60.5 -39.7 0.25 3735 + 3799 3 330.05 57.7 -34.2 0.5 3734 + 3800 3 331.45 60.9 -34.2 0.5 3799 + 3801 3 326.75 59.7 -37.7 0.25 3799 + 3802 3 328.75 55.7 -36.6 0.5 3733 + 3803 3 330.55 47.2 -37.3 0.25 3732 + 3804 3 331.55 49.7 -37.3 0.25 3803 + 3805 3 330.55 46 -37.3 0.25 3803 + 3806 3 325.15 41.8 -38.9 0.5 3730 + 3807 3 317.85 45.8 -37.8 0.5 3729 + 3808 3 314.45 44.5 -39.2 0.5 3728 + 3809 3 312.95 43.7 -39.2 0.5 3808 + 3810 3 314.45 46.6 -38.4 0.25 3808 + 3811 3 311.75 40.6 -43.2 0.75 3725 + 3812 3 314.25 42.7 -41.7 0.5 3811 + 3813 3 309.75 42.7 -44.2 0.5 3812 + 3814 3 314.25 44.1 -45.1 0.25 3812 + 3815 3 310.55 37.5 -45.4 0.5 3811 + 3816 3 312.65 31.3 -38.3 0.5 3724 + 3817 3 306.25 33.1 -40.9 0.5 3723 + 3818 3 304.85 35.1 -44.9 0.5 3817 + 3819 3 304.25 30.9 -40.9 0.5 3817 + 3820 3 311.25 27.4 -45.8 0.5 3721 + 3821 3 309.35 24.4 -45.8 0.5 3820 + 3822 3 307.95 25.2 -45.5 0.25 3821 + 3823 3 312.45 28.6 -45.8 0.5 3820 + 3824 3 309.55 19.6 -46.2 1 3719 + 3825 3 311.95 22.7 -46 1 3824 + 3826 3 313.45 22.7 -41.5 0.75 3825 + 3827 3 313.85 23.3 -43.8 0.75 3826 + 3828 3 315.45 22.1 -40.3 1 3827 + 3829 3 317.75 23.3 -38.8 0.75 3828 + 3830 3 320.45 20.8 -38.2 1 3829 + 3831 3 321.95 19.9 -33.8 0.75 3830 + 3832 3 324.75 21.6 -32.1 0.75 3831 + 3833 3 327.45 19.5 -32.4 0.75 3832 + 3834 3 326.85 19.2 -30.4 0.75 3833 + 3835 3 326.85 16.1 -33.4 0.75 3834 + 3836 3 330.75 15.5 -31.9 0.75 3835 + 3837 3 331.25 18.6 -31.2 0.75 3836 + 3838 3 334.55 15.6 -29.1 0.75 3837 + 3839 3 336.65 18.4 -25.4 0.5 3838 + 3840 3 338.15 17.2 -25.6 0.75 3839 + 3841 3 339.15 15.9 -23.3 0.5 3840 + 3842 3 339.05 15.2 -24.5 0.25 3840 + 3843 3 339.05 13.5 -24.5 0.25 3842 + 3844 3 334.05 19.9 -25.4 0.25 3839 + 3845 3 335.85 14.7 -27 0.5 3838 + 3846 3 336.85 14.5 -29.2 0.5 3845 + 3847 3 337.75 14.5 -26.1 0.25 3846 + 3848 3 333.95 13.3 -29.2 0.25 3846 + 3849 3 332.25 13.6 -27 0.5 3845 + 3850 3 331.25 20.7 -31 0.5 3837 + 3851 3 334.85 22.2 -28.8 0.5 3850 + 3852 3 335.85 20.7 -31.1 0.5 3851 + 3853 3 334.85 23.9 -28.8 0.25 3851 + 3854 3 330.75 13.9 -34.7 0.5 3836 + 3855 3 332.05 14.6 -31.8 0.5 3854 + 3856 3 330.75 12.5 -34.7 0.25 3854 + 3857 3 326.85 13.9 -37.3 0.5 3835 + 3858 3 329.05 21.4 -35.6 0.25 3833 + 3859 3 330.05 20.7 -35.3 0.25 3858 + 3860 3 329.05 24.3 -35.6 0.25 3858 + 3861 3 326.05 24.6 -30.9 0.5 3832 + 3862 3 323.45 17.9 -36.5 0.5 3831 + 3863 3 323.45 15.6 -40.5 0.5 3862 + 3864 3 323.45 13.5 -36 0.5 3863 + 3865 3 320.55 15.6 -40.9 0.5 3863 + 3866 3 321.85 25.5 -37.8 0.5 3830 + 3867 3 320.25 27.4 -37.8 0.25 3866 + 3868 3 317.85 25.8 -37.8 0.25 3867 + 3869 3 320.25 28.9 -37.8 0.25 3867 + 3870 3 324.05 26.6 -40.3 0.5 3866 + 3871 3 315.05 20 -44.1 0.25 3829 + 3872 3 317.95 18.6 -44.1 0.25 3871 + 3873 3 313.35 21.2 -44.1 0.25 3871 + 3874 3 316.75 26.3 -43.4 0.5 3828 + 3875 3 314.05 21.1 -46.5 0.25 3826 + 3876 3 315.65 19.3 -46.5 0.25 3875 + 3877 3 312.15 18.9 -46.5 0.25 3875 + 3878 3 312.05 16.8 -44.3 0.75 3824 + 3879 3 312.95 15.2 -43.9 0.75 3878 + 3880 3 315.15 14.3 -45.1 0.5 3879 + 3881 3 317.55 15.4 -42.4 0.5 3880 + 3882 3 319.35 12.9 -43.2 0.5 3881 + 3883 3 322.95 10.6 -41.1 0.5 3882 + 3884 3 319.35 10.3 -43.2 0.25 3882 + 3885 3 318.95 17.7 -41.8 0.5 3881 + 3886 3 315.15 11.4 -40.5 0.5 3880 + 3887 3 316.55 9.6 -42.8 0.5 3886 + 3888 3 312.15 11.4 -40.5 0.25 3886 + 3889 3 313.75 18.5 -43.9 0.5 3879 + 3890 3 307.25 17.5 -48.7 0.5 3718 + 3891 3 299.55 22.2 -49.2 0.5 3717 + 3892 3 297.45 21.8 -45.4 0.25 3716 + 3893 3 303.15 13 -44.3 0.5 3715 + 3894 3 305.15 9.7 -41.7 0.25 3893 + 3895 3 305.15 7.7 -44 0.25 3894 + 3896 3 307.75 12.5 -45.4 0.25 3894 + 3897 3 300.85 11.5 -44.3 0.25 3893 + 3898 3 296.75 11.9 -48.5 0.25 3713 + 3899 3 298.65 9.7 -46.3 0.25 3898 + 3900 3 293.45 11.8 -48 0.5 3711 + 3901 3 295.75 14 -47.7 0.5 3900 + 3902 3 294.45 10.3 -48 0.25 3900 + 3903 3 291.15 14.8 -53.8 0.25 3710 + 3904 3 291.85 7.8 -55.7 0.25 3709 + 3905 3 293.25 9.3 -53.7 0.25 3904 + 3906 3 291.85 6.5 -57.3 0.25 3904 + 3907 3 285.25 2.6 -56.6 0.5 3706 + 3908 3 287.65 4.8 -54.6 0.5 3907 + 3909 3 287.75 1.2 -54.8 0.5 3908 + 3910 3 289.55 2.3 -54.3 0.5 3909 + 3911 3 292.95 2.3 -52.9 0.5 3910 + 3912 3 295.35 3.5 -57.1 0.5 3911 + 3913 3 293.65 5.2 -53.5 0.5 3912 + 3914 3 297.75 7.4 -57.4 0.25 3913 + 3915 3 292.35 7.6 -52.8 0.25 3913 + 3916 3 296.75 0.3 -57.1 0.5 3912 + 3917 3 293.75 -1 -57.3 0.5 3911 + 3918 3 291.65 -2.3 -58.6 0.5 3910 + 3919 3 287.75 -0.4 -54.8 0.25 3909 + 3920 3 288.45 6 -54.6 0.25 3908 + 3921 3 287.25 0.2 -59.4 0.5 3907 + 3922 3 278.55 4.9 -61.8 0.5 3705 + 3923 3 283.25 -2.5 -60.8 0.5 3704 + 3924 3 281.55 -5.3 -62.7 0.5 3923 + 3925 3 285.55 -6.6 -62.7 0.5 3924 + 3926 3 285.45 -2.8 -56.4 0.25 3923 + 3927 3 280.15 -5.5 -63.7 0.5 3703 + 3928 3 282.35 -8.9 -63.7 0.5 3927 + 3929 3 285.25 -8.9 -65.5 0.5 3928 + 3930 3 282.35 -12.3 -65.9 0.5 3928 + 3931 3 276.15 -9.4 -65.5 0.5 3701 + 3932 3 272.65 -12.5 -63.2 0.5 3931 + 3933 3 271.85 -15.5 -66.3 0.5 3932 + 3934 3 277.15 -12.5 -63.2 0.25 3932 + 3935 3 276.75 -11.6 -69.1 0.5 3931 + 3936 3 272.45 -8.1 -68.7 0.5 3700 + 3937 3 267.95 -9.3 -72.5 0.25 3364 + 3938 3 268.65 -12.3 -74.8 0.25 3937 + 3939 3 266.15 -16.7 -74.6 0.25 3938 + 3940 3 270.65 -14.1 -77.4 0.25 3938 + 3941 3 268.75 -16.1 -73.7 0.25 3940 + 3942 3 272.05 -12.4 -77.4 0.25 3940 + 3943 3 264.55 -11.8 -73.4 0.25 3937 + 3944 3 263.15 1.4 -72.2 0.25 3363 + 3945 3 261.65 -1.4 -74.7 0.25 3944 + 3946 3 263.05 2.4 -75.7 0.25 3944 + 3947 3 264.35 -10 -75.1 0.25 3361 + 3948 3 266.85 -11.3 -75.1 0.25 3947 + 3949 3 264.35 -12.2 -75.1 0.25 3947 + 3950 3 266.05 -13.8 -75.1 0.25 3949 + 3951 3 261.25 -11.8 -75.1 0.25 3949 + 3952 3 261.55 -12.7 -78 0.25 3360 + 3953 3 258.95 -13.4 -76.1 0.25 3952 + 3954 3 262.15 -16.6 -76.5 0.25 3953 + 3955 3 263.65 -17.3 -76.2 0.25 3954 + 3956 3 263.35 -13.7 -76.5 0.25 3954 + 3957 3 257.55 -14.5 -78.6 0.25 3953 + 3958 3 263.85 -12.7 -75.3 0.25 3952 + 3959 3 264.85 -9.6 -75.2 0.25 3958 + 3960 3 265.05 -13.7 -74.8 0.25 3958 + 3961 3 255.55 -17.8 -79.9 0.25 3358 + 3962 3 257.45 -19.6 -80.8 0.25 3961 + 3963 3 259.05 -22 -80.8 0.25 3962 + 3964 3 257.55 -13.9 -79.9 0.25 3961 + 3965 3 242.95 -15.8 -81.2 0.5 1798 + 3966 3 241.05 -15.1 -81.5 0.5 3965 + 3967 3 243.45 -13.2 -85.7 0.5 3966 + 3968 3 244.35 -10.8 -82.6 0.25 3967 + 3969 3 238.95 -12.5 -86.3 0.5 3967 + 3970 3 239.25 -18.1 -81 0.25 3966 + 3971 3 233.35 -35.6 -93.4 0.5 1792 + 3972 3 235.35 -32.1 -91.7 0.5 3971 + 3973 3 236.05 -30.4 -91.7 0.5 3972 + 3974 3 238.15 -29.3 -90.3 0.25 3973 + 3975 3 232.95 -28.9 -92.3 0.5 3973 + 3976 3 231.45 -37.2 -93.4 0.25 3971 + 3977 3 230.45 -38.5 -93.4 0.25 3976 + 3978 3 227.25 -39.2 -88.4 1.5 128 + 3979 3 225.05 -37.6 -87.9 1.5 3978 + 3980 3 226.15 -33.7 -85.9 1.25 3979 + 3981 3 228.75 -29.1 -87 1.25 3980 + 3982 3 229.95 -24.1 -84.6 1 3981 + 3983 3 230.75 -20.1 -84.7 1.25 3982 + 3984 3 229.15 -16.6 -84.4 1.5 3983 + 3985 3 232.05 -13.6 -85.2 1.25 3984 + 3986 3 232.65 -10.4 -84.7 1.25 3985 + 3987 3 232.45 -5 -84.9 1 3986 + 3988 3 227.85 -1.2 -86.9 1.25 3987 + 3989 3 228.85 1.5 -84.9 1.25 3988 + 3990 3 226.65 6.1 -87.8 1.25 3989 + 3991 3 225.25 11.5 -88.3 1.5 3990 + 3992 3 224.25 14.9 -90.3 1.25 3991 + 3993 3 222.25 17.6 -91.7 1.5 3992 + 3994 3 218.85 22.4 -89.4 1.5 3993 + 3995 3 216.55 26.3 -94.1 1.5 3994 + 3996 3 213.85 31 -90.3 1.5 3995 + 3997 3 214.25 34.8 -92.9 1.75 3996 + 3998 3 214.25 37.4 -92.3 1.5 3997 + 3999 3 212.25 40.7 -93.4 1.5 3998 + 4000 3 211.15 44.1 -92.5 2 3999 + 4001 3 210.25 43.7 -92.5 2 4000 + 4002 3 207.35 45.3 -94.7 2 4001 + 4003 3 206.25 47.3 -91.2 2 4002 + 4004 3 206.25 50.1 -93.1 1.25 4003 + 4005 3 206.25 54 -93.5 1 4004 + 4006 3 204.15 56.2 -94.5 1.25 4005 + 4007 3 207.15 56.2 -91.2 1.75 4006 + 4008 3 207.15 58.4 -90.6 2 4007 + 4009 3 207.15 60.9 -92.6 2 4008 + 4010 3 203.85 60.9 -93.5 1.75 4009 + 4011 3 203.85 63.2 -93.5 2 4010 + 4012 3 203.85 63.2 -92.3 1.5 4011 + 4013 3 200.75 65.9 -89.4 1.5 4012 + 4014 3 200.25 65.4 -92.7 1.5 4013 + 4015 3 199.35 69.4 -91.9 1.5 4014 + 4016 3 202.05 73.1 -90.7 1.25 4015 + 4017 3 203.55 77.5 -87 1.5 4016 + 4018 3 204.75 82.1 -88.4 1.5 4017 + 4019 3 206.45 84.1 -86.9 1.5 4018 + 4020 3 204.35 87 -83.2 1.5 4019 + 4021 3 203.55 89.1 -85.2 1.5 4020 + 4022 3 203.55 90.5 -81.9 1.5 4021 + 4023 3 206.15 92 -80.4 1.5 4022 + 4024 3 206.15 93 -80.4 1.5 4023 + 4025 3 204.15 94.8 -82.6 1.5 4024 + 4026 3 208.65 97.5 -77.8 1.5 4025 + 4027 3 209.55 98.7 -80.2 1.5 4026 + 4028 3 207.15 102.1 -78.4 1.5 4027 + 4029 3 208.05 104.1 -74.9 1.5 4028 + 4030 3 210.45 107.5 -75.3 1.5 4029 + 4031 3 211.45 109.2 -71.9 1.5 4030 + 4032 3 209.55 112 -71 1.75 4031 + 4033 3 212.75 114.4 -69.9 1.75 4032 + 4034 3 213.75 116.4 -70.6 1.75 4033 + 4035 3 214.75 118.3 -69.6 1.75 4034 + 4036 3 215.55 119.8 -68.9 1.75 4035 + 4037 3 216.35 122.8 -68 2 4036 + 4038 3 218.15 124.4 -66.9 1.75 4037 + 4039 3 220.55 129.2 -67.5 1.5 4038 + 4040 3 222.15 128.2 -63.5 2.25 4039 + 4041 3 223.85 128.2 -64.4 1.75 4040 + 4042 3 225.95 132.9 -62.7 2 4041 + 4043 3 228.35 135.7 -62.3 2 4042 + 4044 3 228.45 137.9 -64.2 2 4043 + 4045 3 228.15 139.9 -66 2 4044 + 4046 3 230.85 138.1 -64.5 1.25 4045 + 4047 3 231.15 141.4 -63.6 1.5 4046 + 4048 3 233.85 139.8 -63.8 1.5 4047 + 4049 3 235.45 142.2 -64.6 2 4048 + 4050 3 239.95 144.3 -69.2 2 4049 + 4051 3 242.75 144.7 -69.3 1.75 4050 + 4052 3 247.45 144.7 -67.1 1.25 4051 + 4053 3 248.75 144.7 -67.1 1.25 4052 + 4054 3 252.05 143.3 -65.9 1.5 4053 + 4055 3 254.95 142.1 -65.9 1.75 4054 + 4056 3 258.05 144.4 -68 1.25 4055 + 4057 3 264.85 143.6 -74.6 1.5 4056 + 4058 3 268.35 147.3 -77.1 0.75 4057 + 4059 3 273.85 148.1 -80.7 0.75 4058 + 4060 3 278.75 148.7 -82.4 0.5 4059 + 4061 3 280.65 149.8 -82.4 0.5 4060 + 4062 3 279.75 144.1 -82.4 0.5 4060 + 4063 3 273.85 144.3 -80.7 0.5 4059 + 4064 3 270.05 149.5 -80.4 0.5 4058 + 4065 3 272.75 149.5 -79.6 0.5 4064 + 4066 3 266.75 151.3 -80.4 0.5 4064 + 4067 3 268.15 140.8 -75.2 0.75 4057 + 4068 3 272.35 140.8 -71.8 0.5 4067 + 4069 3 269.95 144.5 -75.2 0.5 4067 + 4070 3 257.65 140.5 -64.1 0.75 4055 + 4071 3 260.15 140.1 -68.4 0.5 4070 + 4072 3 262.55 141.8 -68.4 0.5 4071 + 4073 3 261.25 138.1 -68.4 0.25 4071 + 4074 3 252.75 146 -71.8 0.5 4054 + 4075 3 254.15 147.8 -71.6 0.5 4074 + 4076 3 255.25 149.8 -71.6 0.5 4075 + 4077 3 255.85 145.5 -71.6 0.25 4075 + 4078 3 248.75 148 -68.2 0.5 4053 + 4079 3 247.45 140.1 -69.4 0.5 4052 + 4080 3 243.35 139.2 -66.8 0.75 4051 + 4081 3 240.45 132.9 -71.1 0.5 4080 + 4082 3 240.45 129 -63.9 0.5 4081 + 4083 3 244.25 126.1 -63.9 0.5 4082 + 4084 3 246.45 134.3 -68.5 0.5 4080 + 4085 3 248.55 130.1 -68.8 0.5 4084 + 4086 3 237.95 149.1 -74.4 1 4050 + 4087 3 239.05 149.1 -72.7 0.75 4086 + 4088 3 235.35 149.1 -74.5 0.5 4087 + 4089 3 240.55 153 -76.9 0.5 4087 + 4090 3 236.15 151.3 -78.2 0.5 4089 + 4091 3 234.45 156.6 -77 0.5 4090 + 4092 3 235.05 149.7 -78.2 0.25 4090 + 4093 3 242.15 154.6 -76.9 0.5 4089 + 4094 3 241.85 151.2 -76.9 0.5 4086 + 4095 3 237.25 138.4 -64.7 0.5 4049 + 4096 3 239.25 138.4 -66.7 0.5 4095 + 4097 3 237.25 135.9 -67.6 0.5 4095 + 4098 3 229.75 142.3 -68.9 0.5 4047 + 4099 3 228.15 143.2 -65.1 0.75 4045 + 4100 3 225.95 144.6 -64.7 1 4099 + 4101 3 226.05 147.4 -69.5 1 4100 + 4102 3 226.75 150.3 -66.4 1 4101 + 4103 3 231.35 153 -75.8 1 4102 + 4104 3 232.65 155.5 -77 1 4103 + 4105 3 235.75 155.5 -74 0.75 4104 + 4106 3 236.65 154.7 -75.8 0.75 4105 + 4107 3 239.55 159 -81.1 0.5 4106 + 4108 3 243.25 158 -79.9 0.5 4107 + 4109 3 239.55 162.2 -81.1 0.5 4107 + 4110 3 238.75 152.8 -77.4 0.5 4106 + 4111 3 240.25 154.2 -77.3 0.5 4110 + 4112 3 240.45 154.4 -75.9 0.5 4111 + 4113 3 242.95 155.2 -80 0.5 4112 + 4114 3 241.25 157.6 -80 0.25 4113 + 4115 3 243.85 156.4 -80 0.25 4114 + 4116 3 239.65 157.6 -76.8 0.25 4114 + 4117 3 245.65 155.2 -77 0.5 4113 + 4118 3 237.35 154.8 -75.9 0.5 4112 + 4119 3 240.25 152.3 -77.3 0.5 4111 + 4120 3 235.45 151.1 -77.4 0.25 4110 + 4121 3 231.35 159.9 -74 0.5 4105 + 4122 3 234.45 161.7 -75.6 0.5 4121 + 4123 3 230.55 161.5 -74 0.25 4121 + 4124 3 228.05 158 -77 0.75 4104 + 4125 3 224.65 159.2 -78.3 0.75 4124 + 4126 3 222.35 156 -77.3 0.5 4125 + 4127 3 222.95 160.4 -78.3 0.5 4125 + 4128 3 226.25 153.8 -77 0.5 4124 + 4129 3 224.55 155.3 -77 0.25 4128 + 4130 3 226.25 151.9 -74.4 0.5 4128 + 4131 3 226.45 153 -75.8 0.25 4103 + 4132 3 231.55 150.3 -68.2 0.5 4102 + 4133 3 231.55 147.4 -71.7 0.5 4101 + 4134 3 222.35 145.9 -69.9 0.75 4100 + 4135 3 223.35 147.3 -75 0.75 4134 + 4136 3 223.35 151 -72.9 0.5 4135 + 4137 3 223.15 153.3 -74.1 0.5 4136 + 4138 3 223.15 156 -74.1 0.5 4137 + 4139 3 219.95 152.6 -72.9 0.5 4136 + 4140 3 217.75 148.1 -71.9 0.5 4135 + 4141 3 231.25 144.6 -68.2 0.5 4099 + 4142 3 231.75 135.5 -67.4 0.25 4044 + 4143 3 232.65 133.4 -69.6 0.75 4043 + 4144 3 221.75 138.4 -66 0.75 4042 + 4145 3 218.95 142 -71.2 0.75 4144 + 4146 3 218.35 145.3 -67.9 0.5 4145 + 4147 3 217.75 149.1 -67.6 0.5 4146 + 4148 3 215.55 150.6 -71 0.5 4147 + 4149 3 217.75 153.4 -72.2 0.5 4148 + 4150 3 213.25 150.6 -71.4 0.5 4148 + 4151 3 215.05 146.9 -67.6 0.5 4147 + 4152 3 216.65 146 -69.9 0.5 4146 + 4153 3 215.85 143.8 -67.5 0.5 4145 + 4154 3 226.65 126.6 -64.5 1 4041 + 4155 3 229.75 126.5 -67.3 1 4154 + 4156 3 233.65 130.3 -64.5 0.5 4155 + 4157 3 236.45 133.4 -67.2 0.5 4156 + 4158 3 238.45 131.3 -67.2 0.5 4157 + 4159 3 239.35 134.3 -67.2 0.5 4158 + 4160 3 236.45 134.9 -64 0.5 4157 + 4161 3 236.35 128.7 -67.5 0.5 4156 + 4162 3 237.85 131.4 -64.4 0.5 4161 + 4163 3 240.05 131.4 -68.5 0.5 4162 + 4164 3 237.85 126.4 -67.5 0.5 4161 + 4165 3 231.75 122.9 -63.6 0.5 4155 + 4166 3 234.65 124.7 -69.5 0.5 4165 + 4167 3 228.85 120.4 -68.6 0.5 4165 + 4168 3 224.85 124.8 -70.2 0.5 4154 + 4169 3 218.05 135.2 -69.5 0.5 4040 + 4170 3 219.85 137.1 -69.5 0.5 4169 + 4171 3 215.95 138.7 -69.8 0.5 4170 + 4172 3 217.55 141.5 -69.1 0.5 4171 + 4173 3 214.55 142.4 -69.1 0.5 4172 + 4174 3 217.35 141.9 -69.1 0.5 4173 + 4175 3 212.85 142.4 -68 0.25 4173 + 4176 3 212.85 139.7 -69.8 0.25 4171 + 4177 3 215.65 133.3 -69.5 0.25 4169 + 4178 3 215.55 131.8 -66.6 0.5 4039 + 4179 3 214.35 131.9 -72.7 0.5 4178 + 4180 3 214.95 134.2 -74.2 0.5 4179 + 4181 3 216.35 136 -74.2 0.5 4180 + 4182 3 212.95 138.5 -74.3 0.5 4181 + 4183 3 211.65 134.8 -74.2 0.25 4180 + 4184 3 215.05 130 -72.7 0.25 4179 + 4185 3 213.25 129.8 -72.7 0.25 4184 + 4186 3 215.95 130.6 -72.7 0.25 4184 + 4187 3 214.15 128.9 -66.6 0.5 4178 + 4188 3 215.75 125.7 -73 0.5 4038 + 4189 3 217.55 127.7 -72.6 0.5 4188 + 4190 3 213.35 128.5 -76.9 0.5 4189 + 4191 3 216.65 129.1 -72.6 0.5 4189 + 4192 3 214.25 123.5 -73 0.5 4188 + 4193 3 213.05 122.7 -68.4 0.5 4037 + 4194 3 210.05 122.7 -72.1 0.5 4193 + 4195 3 216.85 125.9 -68.4 0.25 4193 + 4196 3 218.15 117.1 -71.6 0.5 4036 + 4197 3 218.75 117.1 -72 0.5 4196 + 4198 3 218.85 119.9 -72 0.5 4197 + 4199 3 220.45 118.7 -69.8 0.5 4198 + 4200 3 218.85 121.7 -72 0.25 4198 + 4201 3 219.45 115.3 -72.5 0.25 4197 + 4202 3 217.35 114.7 -75 0.5 4035 + 4203 3 216.05 113.5 -75.7 0.25 4202 + 4204 3 216.05 111.4 -75.7 0.25 4203 + 4205 3 218.55 117.6 -75 0.25 4202 + 4206 3 208.25 118.6 -70.6 0.25 4034 + 4207 3 206.15 118.6 -70.9 0.25 4206 + 4208 3 214.75 109.2 -77.2 0.5 4031 + 4209 3 215.75 110.2 -77.7 0.5 4208 + 4210 3 217.45 110.2 -77.7 0.5 4209 + 4211 3 217.45 111.8 -79.8 0.25 4210 + 4212 3 218.85 107.2 -75.1 0.25 4210 + 4213 3 216.85 105.9 -74.8 0.25 4208 + 4214 3 216.85 104.4 -74.8 0.25 4213 + 4215 3 213.45 103.2 -74.8 0.25 4214 + 4216 3 213.45 102 -79 0.25 4215 + 4217 3 212.25 100.9 -79 0.25 4216 + 4218 3 213.45 99.8 -79 0.25 4216 + 4219 3 218.35 104.4 -74.8 0.25 4214 + 4220 3 213.65 105 -74.8 0.25 4213 + 4221 3 206.25 102.1 -82.5 0.5 4028 + 4222 3 205.45 104 -84 0.25 4221 + 4223 3 203.55 105.4 -84 0.25 4222 + 4224 3 201.25 102.7 -82.3 0.25 4223 + 4225 3 203.15 102.1 -83 0.25 4221 + 4226 3 213.05 100.8 -75.2 0.5 4027 + 4227 3 212.75 103.5 -79.5 0.25 4226 + 4228 3 216.45 105.8 -75.1 0.25 4227 + 4229 3 211.65 103.5 -79.5 0.25 4227 + 4230 3 216.25 100.8 -78.9 0.5 4226 + 4231 3 216.25 102.4 -79.4 0.5 4230 + 4232 3 218.25 100.1 -78.4 0.5 4231 + 4233 3 217.95 104.3 -79.4 0.25 4231 + 4234 3 216.85 98 -78.9 0.25 4230 + 4235 3 216.85 94.9 -80.2 0.25 4234 + 4236 3 204.45 99.1 -84.2 0.5 4026 + 4237 3 210.05 91.7 -82.8 0.5 4025 + 4238 3 211.75 95.3 -84.3 0.25 4237 + 4239 3 213.35 96.6 -84.3 0.25 4238 + 4240 3 213.35 93.8 -84.3 0.25 4239 + 4241 3 214.75 98 -83.4 0.25 4239 + 4242 3 210.25 89.3 -85.7 0.25 4237 + 4243 3 213.45 92.5 -85 0.25 4242 + 4244 3 210.25 87.8 -85.7 0.25 4242 + 4245 3 209.05 90.5 -80.7 0.25 4024 + 4246 3 211.25 88.9 -80.6 0.25 4245 + 4247 3 209.05 94.3 -81.2 0.25 4245 + 4248 3 200.55 94.5 -82.4 0.25 4023 + 4249 3 198.45 95.9 -83.5 0.25 4248 + 4250 3 198.35 92.9 -87.2 0.25 4249 + 4251 3 197.35 90.9 -87.2 0.25 4250 + 4252 3 197.75 96.7 -83.5 0.25 4249 + 4253 3 201.15 90.5 -87.6 0.25 4022 + 4254 3 208.65 87.7 -86.5 0.5 4020 + 4255 3 210.85 84.4 -89.3 0.25 4254 + 4256 3 213.15 82.1 -87.1 0.25 4255 + 4257 3 210.85 87.8 -89.3 0.25 4255 + 4258 3 210.05 89.3 -83.2 0.25 4254 + 4259 3 208.65 80.2 -90.5 0.5 4019 + 4260 3 209.95 78.4 -85.9 0.5 4259 + 4261 3 211.55 78.4 -87.4 0.5 4260 + 4262 3 207.15 76.2 -85.9 0.25 4260 + 4263 3 197.95 80.2 -88.8 0.25 4017 + 4264 3 199.75 83.3 -91.4 0.5 4263 + 4265 3 194.35 85.9 -88.9 0.5 4264 + 4266 3 192.15 88.3 -93.4 0.5 4265 + 4267 3 194.95 91.9 -91.5 0.25 4266 + 4268 3 190.95 90.2 -93.4 0.25 4266 + 4269 3 192.25 85.6 -89.1 0.25 4265 + 4270 3 200.65 86.6 -90.8 0.5 4264 + 4271 3 197.85 88.8 -90.8 0.5 4270 + 4272 3 196.65 80.2 -91.1 0.25 4263 + 4273 3 193.95 81.2 -90.3 0.25 4272 + 4274 3 192.75 82.4 -90.3 0.25 4273 + 4275 3 194.75 78.2 -91.1 0.25 4272 + 4276 3 198.75 74.1 -95.7 0.25 4016 + 4277 3 197.05 69.2 -93.5 0.5 4015 + 4278 3 192.55 71.5 -90.8 0.25 4277 + 4279 3 188.85 75.3 -94.2 0.25 4278 + 4280 3 191.35 77.9 -94.3 0.25 4279 + 4281 3 185.85 71.5 -90.9 0.25 4279 + 4282 3 197.25 72.6 -92.1 0.5 4277 + 4283 3 197.25 75 -97.4 0.25 4282 + 4284 3 194.85 76.6 -97.4 0.25 4283 + 4285 3 194.85 70.1 -96.8 0.25 4282 + 4286 3 205.45 65.8 -95.4 0.25 4014 + 4287 3 206.95 67.1 -95.4 0.25 4286 + 4288 3 206.85 69.4 -93 0.25 4287 + 4289 3 206.85 70.9 -93 0.25 4288 + 4290 3 208.55 65.3 -92.7 0.25 4287 + 4291 3 209.75 63.2 -91.8 1.25 4011 + 4292 3 212.25 64 -92 1 4291 + 4293 3 211.95 65.4 -88.4 1 4292 + 4294 3 211.95 67.2 -86.2 1 4293 + 4295 3 211.95 70.4 -87.8 1.25 4294 + 4296 3 215.85 72.4 -83.8 1 4295 + 4297 3 217.65 72.4 -82.8 1 4296 + 4298 3 218.85 74.4 -82.1 1 4297 + 4299 3 217.85 75.4 -78.1 1 4298 + 4300 3 218.95 77.9 -80 1.75 4299 + 4301 3 218.95 77.2 -72.3 1.5 4300 + 4302 3 222.65 79.1 -68.8 1.25 4301 + 4303 3 223.25 79.8 -72.7 1.25 4302 + 4304 3 226.15 83.2 -69 1.25 4303 + 4305 3 226.95 84.3 -70.1 1.25 4304 + 4306 3 227.75 87.1 -66.9 1 4305 + 4307 3 225.95 88.9 -69.8 1.25 4306 + 4308 3 225.95 92.1 -65.2 1.25 4307 + 4309 3 228.65 94.6 -67.8 1.25 4308 + 4310 3 227.45 96.7 -65.6 1.25 4309 + 4311 3 227.05 101 -65.6 1.25 4310 + 4312 3 227.05 103.7 -61.6 1 4311 + 4313 3 229.25 105.9 -62.4 1.25 4312 + 4314 3 229.25 107.4 -61.2 1.25 4313 + 4315 3 230.75 109.7 -61.1 1.25 4314 + 4316 3 232.95 112.1 -61.3 1.75 4315 + 4317 3 234.15 112.1 -56.9 1.25 4316 + 4318 3 236.15 116.3 -55.5 0.75 4317 + 4319 3 239.55 119.2 -53.6 0.75 4318 + 4320 3 240.65 121.9 -53.5 0.75 4319 + 4321 3 240.65 123.4 -53.5 1.25 4320 + 4322 3 242.35 125.3 -54.1 1.25 4321 + 4323 3 244.15 127.4 -57 1.25 4322 + 4324 3 245.65 128.6 -57.1 2 4323 + 4325 3 248.85 130.3 -56.7 1.25 4324 + 4326 3 248.85 132.7 -57.7 0.75 4325 + 4327 3 253.95 134.2 -53.9 1.25 4326 + 4328 3 254.45 133.2 -54.4 0.75 4327 + 4329 3 255.85 136.8 -56.5 0.75 4328 + 4330 3 258.35 136.5 -59.5 0.75 4329 + 4331 3 256.85 138.9 -56.6 0.75 4330 + 4332 3 256.85 140.7 -60.7 0.75 4331 + 4333 3 263.05 139.3 -61.1 0.5 4332 + 4334 3 262.15 143.3 -64.2 0.5 4333 + 4335 3 254.45 142 -57.7 0.5 4332 + 4336 3 262.35 137 -56.8 0.5 4331 + 4337 3 259.55 135.1 -62.4 0.5 4330 + 4338 3 261.25 136.9 -62.4 0.25 4337 + 4339 3 259.55 133.3 -62.4 0.5 4337 + 4340 3 257.05 133.3 -55.3 0.75 4328 + 4341 3 260.05 129.4 -57.6 0.75 4340 + 4342 3 260.45 127.9 -56.6 0.5 4341 + 4343 3 261.35 133 -59.5 0.25 4341 + 4344 3 263.55 133 -56.3 0.25 4343 + 4345 3 255.55 129.5 -54.1 0.25 4340 + 4346 3 250.85 137 -59.8 0.75 4327 + 4347 3 252.65 140.1 -56.3 0.5 4346 + 4348 3 248.05 138.1 -60.1 0.5 4346 + 4349 3 253.15 129.1 -57.9 0.5 4326 + 4350 3 255.25 131.3 -54.5 0.5 4349 + 4351 3 257.05 127.6 -57.8 0.5 4350 + 4352 3 254.25 126.8 -54.9 0.5 4349 + 4353 3 255.45 127.5 -55.4 0.5 4352 + 4354 3 252.55 123.9 -54.1 0.25 4352 + 4355 3 252.35 125.5 -62 0.75 4325 + 4356 3 257.05 123.9 -62.7 0.75 4355 + 4357 3 252.35 121.8 -58.6 0.5 4355 + 4358 3 243.15 132.4 -63.2 0.5 4324 + 4359 3 244.85 135 -66.6 0.75 4358 + 4360 3 241.05 137 -62.4 0.5 4359 + 4361 3 243.65 138.8 -66.8 0.25 4360 + 4362 3 239.35 137.2 -62.4 0.25 4360 + 4363 3 240.25 133.5 -67.1 0.5 4358 + 4364 3 236.75 124.2 -59.6 0.5 4321 + 4365 3 236.75 126.2 -61.7 0.5 4364 + 4366 3 233.95 121.7 -59.6 0.25 4364 + 4367 3 236.35 119 -53.5 0.25 4320 + 4368 3 238.65 113.3 -58.6 0.75 4317 + 4369 3 241.25 116.1 -55.6 0.75 4368 + 4370 3 243.35 117.7 -61.8 0.5 4369 + 4371 3 246.45 119.3 -57.6 0.5 4370 + 4372 3 245.25 114.7 -61.8 0.5 4370 + 4373 3 242.75 112.6 -59.3 0.5 4369 + 4374 3 229.05 114.3 -61.3 0.5 4316 + 4375 3 231.25 117.1 -59.5 0.5 4374 + 4376 3 231.25 118.3 -58.2 0.5 4375 + 4377 3 228.55 119.4 -58.2 0.5 4376 + 4378 3 226.55 118.3 -58.5 0.25 4376 + 4379 3 227.75 115.1 -63.8 0.25 4374 + 4380 3 224.65 105.7 -64.4 0.5 4314 + 4381 3 223.45 109.5 -61.7 0.5 4380 + 4382 3 223.45 111.7 -67 0.5 4381 + 4383 3 224.65 113.6 -67.3 0.5 4382 + 4384 3 219.65 111.7 -64.4 0.25 4382 + 4385 3 224.35 101.4 -65.8 0.5 4312 + 4386 3 222.25 103.9 -67 0.25 4385 + 4387 3 231.45 101 -65.9 0.5 4311 + 4388 3 233.25 102.8 -65.9 0.5 4387 + 4389 3 237.25 98.8 -62.9 0.5 4388 + 4390 3 239.35 98.1 -67.3 0.5 4389 + 4391 3 244.55 95.9 -68.3 0.5 4390 + 4392 3 241.75 103 -67.3 0.25 4390 + 4393 3 233.75 104.8 -66.2 0.5 4388 + 4394 3 235.15 102.4 -66.7 0.5 4393 + 4395 3 236.05 107.7 -65.5 0.5 4393 + 4396 3 224.45 96.7 -69.8 0.5 4310 + 4397 3 231.15 92.5 -70.4 0.5 4309 + 4398 3 223.65 93.8 -73.3 0.25 4308 + 4399 3 229.65 90 -68.6 0.5 4307 + 4400 3 229.05 91.8 -66.1 0.5 4399 + 4401 3 233.65 90.9 -66.4 0.5 4400 + 4402 3 235.45 93.8 -65.2 0.5 4401 + 4403 3 229.05 93.5 -66.1 0.5 4400 + 4404 3 231.15 87.6 -68.6 0.25 4399 + 4405 3 222.15 87.1 -69.9 0.5 4306 + 4406 3 221.75 84.3 -77.1 0.5 4305 + 4407 3 219.75 86.1 -77.1 0.5 4406 + 4408 3 228.05 80.1 -71.8 0.25 4304 + 4409 3 229.35 83.3 -71.8 0.25 4408 + 4410 3 226.45 80.3 -71.7 0.25 4408 + 4411 3 225.25 77.4 -73.1 0.25 4303 + 4412 3 220.15 80.4 -81 1.75 4300 + 4413 3 217.75 82.8 -81.1 1.5 4412 + 4414 3 219.15 86.7 -77.8 1.5 4413 + 4415 3 220.15 91.1 -79 1.25 4414 + 4416 3 218.45 93.6 -78.7 1.25 4415 + 4417 3 222.25 95.9 -78.7 1.25 4416 + 4418 3 223.95 97.9 -74 1.5 4417 + 4419 3 225.75 100.7 -74.8 1.5 4418 + 4420 3 226.65 99.3 -74.6 1.5 4419 + 4421 3 228.75 104.6 -70.2 1.25 4420 + 4422 3 226.95 109.6 -66.1 1.25 4421 + 4423 3 230.05 114.4 -68.3 1.25 4422 + 4424 3 232.05 118.1 -66.1 1.25 4423 + 4425 3 229.95 119.7 -67.5 1.75 4424 + 4426 3 234.15 121.2 -67.5 1.75 4425 + 4427 3 232.55 122.1 -63.8 1.75 4426 + 4428 3 232.55 123.4 -66.1 1.75 4427 + 4429 3 236.75 126.7 -65.4 1.75 4428 + 4430 3 234.75 127.5 -66.4 1.75 4429 + 4431 3 236.45 130.5 -61.2 1.75 4430 + 4432 3 237.15 133 -64.3 1.75 4431 + 4433 3 238.75 136.4 -64.4 1.75 4432 + 4434 3 241.25 138.7 -65.3 1.75 4433 + 4435 3 243.15 140.5 -65 2.5 4434 + 4436 3 246.45 142.9 -60.6 2 4435 + 4437 3 244.95 145.4 -57.9 1.75 4436 + 4438 3 245.45 143.5 -64.5 1.5 4437 + 4439 3 250.35 147.8 -62 1.25 4438 + 4440 3 252.65 146.9 -64.8 0.75 4439 + 4441 3 253.95 151.3 -69.3 1 4440 + 4442 3 256.25 153.7 -73.9 1 4441 + 4443 3 258.25 151.7 -73.5 0.5 4442 + 4444 3 263.35 154.2 -73.6 0.5 4443 + 4445 3 262.25 149.7 -73.5 0.5 4443 + 4446 3 256.25 157.3 -71.5 0.5 4442 + 4447 3 253.65 146.5 -63.6 0.75 4440 + 4448 3 256.95 148.2 -63.6 0.25 4447 + 4449 3 257.75 144.7 -63.6 0.5 4447 + 4450 3 250.35 150.7 -62 0.75 4439 + 4451 3 245.95 146.7 -61.8 1 4438 + 4452 3 245.95 149 -65.6 0.75 4451 + 4453 3 245.95 150.6 -65.4 0.5 4452 + 4454 3 247.55 152.2 -68.6 0.5 4453 + 4455 3 241.85 150.6 -67.4 0.5 4453 + 4456 3 241.15 149 -62.1 0.5 4452 + 4457 3 252.05 145.4 -57.6 1.25 4437 + 4458 3 254.65 146.3 -57.6 1.25 4457 + 4459 3 258.75 143.7 -57 1.25 4458 + 4460 3 261.45 143 -58.9 1.25 4459 + 4461 3 265.65 144.1 -62.6 1.25 4460 + 4462 3 267.35 143.6 -67.3 1.5 4461 + 4463 3 274.15 145.8 -69.5 1.25 4462 + 4464 3 276.95 145.8 -70.8 1 4463 + 4465 3 283.05 145.8 -67.6 0.75 4464 + 4466 3 278.85 151.7 -73.7 0.5 4464 + 4467 3 269.75 147.7 -73.4 0.75 4463 + 4468 3 265.85 149.6 -68.8 0.5 4467 + 4469 3 268.55 152.2 -68.8 0.5 4468 + 4470 3 262.85 152.2 -68.6 0.5 4468 + 4471 3 267.25 144.1 -73.4 0.5 4467 + 4472 3 273.65 140.3 -63 1 4462 + 4473 3 276.05 140.3 -63.1 0.75 4472 + 4474 3 276.05 137.8 -64.1 0.5 4473 + 4475 3 280.05 136.1 -61.7 0.5 4474 + 4476 3 278.85 141.3 -64.1 0.5 4474 + 4477 3 277.95 143.7 -63.1 0.5 4473 + 4478 3 262.75 139.7 -59.4 0.75 4460 + 4479 3 266.75 140.8 -57.8 0.75 4478 + 4480 3 266.75 138.6 -59.5 0.5 4479 + 4481 3 271.45 137.7 -61.5 0.5 4480 + 4482 3 266.75 135.8 -59.5 0.25 4480 + 4483 3 268.05 142.4 -57.8 0.5 4479 + 4484 3 269.15 140.8 -57.8 0.5 4483 + 4485 3 263.95 136.2 -59.4 0.5 4478 + 4486 3 258.75 145.3 -60.4 0.75 4459 + 4487 3 260.05 147.9 -61.9 0.5 4486 + 4488 3 254.75 149 -60.4 0.5 4486 + 4489 3 254.65 148.9 -59.6 0.75 4458 + 4490 3 253.65 140.9 -58.8 0.5 4457 + 4491 3 249.85 138.6 -54.9 0.75 4436 + 4492 3 252.95 139.8 -49.4 1 4491 + 4493 3 253.75 139.2 -54.3 1 4492 + 4494 3 258.65 140.9 -52.2 1 4493 + 4495 3 262.35 140.4 -56.5 0.75 4494 + 4496 3 257.35 137.4 -55.6 0.5 4494 + 4497 3 253.75 137.7 -54.3 0.25 4493 + 4498 3 255.85 136.7 -54.3 0.25 4497 + 4499 3 252.45 137.7 -54.3 0.25 4497 + 4500 3 251.95 143 -57.5 0.5 4492 + 4501 3 250.85 135.4 -55.2 0.25 4491 + 4502 3 239.25 143.4 -63.5 1.25 4435 + 4503 3 241.15 144 -64.1 1.25 4502 + 4504 3 241.15 147.9 -66.9 0.75 4503 + 4505 3 241.15 149.8 -64.6 0.5 4504 + 4506 3 242.75 148.9 -67.4 0.5 4505 + 4507 3 242.75 147.2 -68 0.5 4506 + 4508 3 244.85 151.9 -68.1 0.5 4506 + 4509 3 240.65 147.8 -68.6 0.5 4505 + 4510 3 244.75 149 -68.6 0.25 4509 + 4511 3 244.05 145 -68.6 0.5 4509 + 4512 3 237.95 146.8 -65.4 0.5 4504 + 4513 3 236.55 146.7 -66.5 0.5 4503 + 4514 3 240.15 139.9 -65.8 0.5 4502 + 4515 3 236.75 144.3 -65.9 0.25 4514 + 4516 3 235.85 139.9 -64.1 0.5 4514 + 4517 3 244.45 136.4 -64.4 0.5 4433 + 4518 3 242.25 133 -60.8 0.25 4432 + 4519 3 233.35 126.7 -68.7 0.5 4431 + 4520 3 235.65 123.5 -69.9 0.5 4519 + 4521 3 231.35 130.3 -66.8 0.5 4519 + 4522 3 239.75 127.5 -68 0.5 4430 + 4523 3 243.95 129 -65 0.5 4522 + 4524 3 247.35 129 -63.1 0.5 4523 + 4525 3 244.95 124.8 -65 0.25 4523 + 4526 3 237.85 122.6 -69.6 0.5 4522 + 4527 3 232.05 125 -65.5 0.5 4429 + 4528 3 230.05 129.2 -62.5 0.25 4527 + 4529 3 229.55 122.4 -65.5 0.5 4527 + 4530 3 238.75 120.2 -66.5 0.5 4428 + 4531 3 235.85 117.8 -62 0.5 4427 + 4532 3 229.05 122.4 -66.9 0.75 4426 + 4533 3 227.25 122.4 -71.6 0.5 4532 + 4534 3 227.45 124.7 -72.7 0.25 4533 + 4535 3 225.45 119.4 -72.3 0.5 4533 + 4536 3 233.85 111.8 -66.2 0.75 4424 + 4537 3 226.55 114.4 -71.6 0.5 4423 + 4538 3 225.75 116 -69.4 0.5 4537 + 4539 3 224.25 114.4 -67.4 0.5 4537 + 4540 3 224.15 104.6 -76.9 0.75 4421 + 4541 3 224.25 106.9 -72.2 0.5 4540 + 4542 3 221.75 101.5 -76.9 0.5 4540 + 4543 3 219.65 104.9 -73.5 0.25 4542 + 4544 3 222.95 104.2 -73.5 0.25 4543 + 4545 3 218.15 103.8 -73.5 0.25 4543 + 4546 3 221.75 99.6 -73.8 0.25 4542 + 4547 3 227.05 97.8 -74.8 0.5 4420 + 4548 3 230.35 101.4 -74 0.5 4547 + 4549 3 233.75 97.4 -70.6 0.5 4548 + 4550 3 231.95 104.2 -74 0.25 4548 + 4551 3 231.75 95.1 -70.6 0.5 4547 + 4552 3 222.25 102.8 -75.6 0.25 4419 + 4553 3 218.55 98.3 -79.4 0.5 4417 + 4554 3 217.05 99.8 -78.3 0.5 4553 + 4555 3 220.55 101.3 -77.7 0.5 4554 + 4556 3 223.15 98.1 -77.4 0.5 4555 + 4557 3 221.55 103 -78.5 0.25 4555 + 4558 3 214.75 97.9 -79.3 0.5 4554 + 4559 3 223.65 86.5 -82.8 0.5 4415 + 4560 3 215.45 86.7 -77.8 0.5 4414 + 4561 3 214.05 88.2 -79.7 0.5 4560 + 4562 3 215.85 90.4 -82.1 0.5 4561 + 4563 3 211.25 90.4 -80 0.25 4562 + 4564 3 208.45 88.5 -82.5 0.25 4563 + 4565 3 211.25 92.3 -82.5 0.25 4563 + 4566 3 212.75 93.6 -82.5 0.25 4565 + 4567 3 212.95 84.9 -78.9 0.25 4561 + 4568 3 222.75 82.8 -80.1 0.5 4413 + 4569 3 225.05 81.7 -83 0.5 4568 + 4570 3 223.05 87.2 -77.6 0.5 4568 + 4571 3 221.55 70.8 -81.7 0.5 4298 + 4572 3 221.55 69.5 -81.7 0.5 4571 + 4573 3 225.25 72.9 -85.3 0.5 4572 + 4574 3 221.55 67.9 -81.7 0.25 4572 + 4575 3 215.85 73.7 -90.1 0.5 4296 + 4576 3 215.85 76.5 -90 0.5 4575 + 4577 3 216.75 77.2 -91.3 0.5 4576 + 4578 3 218.05 74.4 -91.9 0.5 4577 + 4579 3 219.95 77.6 -90.8 0.25 4578 + 4580 3 218.95 72.6 -92 0.5 4578 + 4581 3 216.75 78.8 -88.5 0.5 4577 + 4582 3 213.55 80.3 -90 0.5 4581 + 4583 3 217.95 77.5 -91.6 0.25 4581 + 4584 3 212.85 77.5 -91.3 0.5 4576 + 4585 3 210.95 74.6 -91.2 0.5 4584 + 4586 3 212.85 73.7 -90.1 0.25 4575 + 4587 3 217.75 67.2 -85.8 0.5 4294 + 4588 3 219.95 66.4 -85.1 0.5 4587 + 4589 3 221.45 66.4 -82.4 0.5 4588 + 4590 3 221.45 68.6 -83 0.5 4589 + 4591 3 223.35 69.5 -85.4 0.5 4590 + 4592 3 223.95 70.4 -83.4 0.5 4591 + 4593 3 221.85 71.7 -82.4 0.5 4592 + 4594 3 226.05 73.3 -85.4 0.5 4593 + 4595 3 225.45 75.3 -85.5 0.5 4594 + 4596 3 220.35 71.7 -82.4 0.25 4593 + 4597 3 226.25 68.4 -85.5 0.25 4592 + 4598 3 224.55 67.4 -85.4 0.5 4591 + 4599 3 222.25 64.2 -88.1 0.5 4598 + 4600 3 222.25 62.5 -90.1 0.5 4599 + 4601 3 226.25 66.5 -85 0.5 4598 + 4602 3 222.55 63.3 -82.3 0.25 4589 + 4603 3 214.95 62.6 -89.8 0.5 4293 + 4604 3 216.85 59.4 -94.1 0.5 4603 + 4605 3 218.35 57.8 -93.5 0.5 4604 + 4606 3 218.45 61.1 -93.7 0.25 4604 + 4607 3 216.75 64.3 -89.8 0.25 4603 + 4608 3 211.65 59 -96 0.25 4292 + 4609 3 206.95 67 -90.2 0.25 4291 + 4610 3 208.15 70.8 -90.9 0.25 4609 + 4611 3 206.05 67 -90.2 0.25 4609 + 4612 3 201.25 60.9 -89.3 0.25 4009 + 4613 3 199.65 62.8 -93.2 0.25 4612 + 4614 3 197.65 62.5 -97.1 0.25 4613 + 4615 3 199.65 59.3 -93.2 0.25 4613 + 4616 3 203.65 57.8 -97.4 0.25 4006 + 4617 3 201.15 60.4 -99.2 0.25 4616 + 4618 3 199.05 63.4 -97.4 0.25 4617 + 4619 3 197.25 62.2 -93.4 0.25 4618 + 4620 3 199.05 65.2 -97.4 0.25 4618 + 4621 3 201.15 62.4 -95.7 0.25 4617 + 4622 3 202.35 48.9 -91.4 0.5 4003 + 4623 3 199.65 52.7 -93.4 0.75 4622 + 4624 3 202.15 55.4 -96.1 0.5 4623 + 4625 3 196.35 50.4 -97.9 0.5 4623 + 4626 3 194.25 53.4 -99 0.5 4625 + 4627 3 196.35 48.7 -97.9 0.25 4625 + 4628 3 201.35 45.7 -94.3 0.25 4622 + 4629 3 202.85 43.9 -96.2 0.25 4628 + 4630 3 198.75 42.6 -97.9 0.25 4629 + 4631 3 199.45 48.5 -96.5 0.25 4628 + 4632 3 216.75 46.1 -89.1 0.75 4000 + 4633 3 216.45 44 -87.7 0.75 4632 + 4634 3 220.75 46.2 -83.3 0.75 4633 + 4635 3 223.85 45.5 -82.7 0.75 4634 + 4636 3 222.65 48.8 -82 1 4635 + 4637 3 226.05 50.7 -81 0.75 4636 + 4638 3 226.65 51 -79.9 1 4637 + 4639 3 224.95 53.7 -79.4 0.75 4638 + 4640 3 228.35 58.1 -80 1 4639 + 4641 3 229.05 60.1 -77 0.75 4640 + 4642 3 227.55 60.1 -76.7 0.75 4641 + 4643 3 230.55 62.9 -77 0.75 4642 + 4644 3 232.05 64.5 -77.1 0.75 4643 + 4645 3 234.95 67.6 -73.5 1 4644 + 4646 3 236.35 69.2 -73 1.25 4645 + 4647 3 237.35 68.7 -73 1 4646 + 4648 3 235.85 71.7 -72.5 1 4647 + 4649 3 238.85 74.9 -67.7 0.75 4648 + 4650 3 241.15 74.9 -66.5 1.25 4649 + 4651 3 239.35 78.6 -65.6 1 4650 + 4652 3 239.35 79.9 -67.9 1 4651 + 4653 3 241.65 81 -66.9 0.75 4652 + 4654 3 241.65 83.2 -64.8 0.75 4653 + 4655 3 245.05 84.5 -64.7 1 4654 + 4656 3 246.05 87.1 -64.4 1.25 4655 + 4657 3 245.55 89.7 -63.3 1 4656 + 4658 3 245.55 91.5 -58.9 1 4657 + 4659 3 247.35 94.3 -55.9 1 4658 + 4660 3 245.55 93.7 -57.9 1 4659 + 4661 3 246.65 97.5 -58.1 1 4660 + 4662 3 248.05 98.3 -58.1 1 4661 + 4663 3 245.35 101.3 -57.7 1 4662 + 4664 3 247.75 103.1 -52.6 1 4663 + 4665 3 248.95 104.6 -52.3 0.75 4664 + 4666 3 248.95 104.6 -55.1 0.5 4665 + 4667 3 247.85 109.6 -60.5 0.5 4666 + 4668 3 246.35 110.8 -55.5 0.5 4667 + 4669 3 251.85 109.6 -60.5 0.25 4667 + 4670 3 244.05 110.5 -57.8 0.5 4666 + 4671 3 248.25 104.6 -54.1 0.5 4665 + 4672 3 252.65 105.9 -53.3 0.5 4671 + 4673 3 252.65 109.6 -52.1 0.5 4672 + 4674 3 251.85 113.2 -55.2 0.5 4673 + 4675 3 252.65 111.9 -58.4 0.5 4674 + 4676 3 249.85 115.1 -52.6 0.5 4675 + 4677 3 245.35 115.1 -55 0.5 4676 + 4678 3 245.35 118 -54.1 0.5 4677 + 4679 3 244.05 112.6 -55.6 0.25 4677 + 4680 3 249.75 110.3 -59.9 0.5 4675 + 4681 3 248.45 110.3 -57.6 0.5 4680 + 4682 3 245.65 114 -56 0.5 4681 + 4683 3 248.45 108.7 -57.6 0.25 4681 + 4684 3 256.35 117.5 -56.4 0.5 4674 + 4685 3 253.75 102.6 -60 0.5 4672 + 4686 3 255.85 104.5 -59 0.25 4685 + 4687 3 258.25 101.6 -59 0.25 4686 + 4688 3 255.45 100.1 -60.1 0.25 4685 + 4689 3 251.95 100 -54.5 0.25 4671 + 4690 3 253.15 98.7 -52.6 0.25 4689 + 4691 3 253.95 100 -51.7 0.25 4689 + 4692 3 250.05 96.1 -59.5 0.5 4662 + 4693 3 243.45 92.6 -58.6 0.25 4660 + 4694 3 249.45 90.9 -62.2 0.5 4659 + 4695 3 251.85 92.7 -63.4 0.25 4694 + 4696 3 252.45 87 -65.8 0.25 4694 + 4697 3 241.65 94.9 -59 0.5 4658 + 4698 3 240.65 97.7 -55.9 0.5 4697 + 4699 3 242.35 100.3 -57 0.5 4698 + 4700 3 243.75 102.8 -58.6 0.5 4699 + 4701 3 239.85 105.5 -57.1 0.5 4700 + 4702 3 238.75 104.7 -55.3 0.5 4701 + 4703 3 236.85 108.7 -59.2 0.5 4702 + 4704 3 234.65 107 -60.1 0.25 4703 + 4705 3 236.85 110.7 -57.8 0.5 4703 + 4706 3 236.55 103.7 -58.6 0.25 4702 + 4707 3 243.15 107.2 -57.1 0.25 4701 + 4708 3 241.85 101.6 -56.9 0.5 4700 + 4709 3 245.15 104.4 -56.6 0.5 4708 + 4710 3 244.75 99.8 -56.9 0.25 4708 + 4711 3 238.75 96.5 -62 0.5 4698 + 4712 3 249.05 89.7 -59.8 0.75 4657 + 4713 3 250.55 87.5 -62.7 0.5 4712 + 4714 3 253.75 85.1 -62.4 0.75 4713 + 4715 3 257.05 87 -61.2 0.5 4714 + 4716 3 253.85 84.2 -61.2 0.5 4715 + 4717 3 258.05 81.3 -63.3 0.5 4716 + 4718 3 258.45 87 -61.2 0.5 4715 + 4719 3 253.75 82.7 -63.7 0.5 4714 + 4720 3 255.05 79.8 -61.5 0.5 4719 + 4721 3 248.65 82.7 -64 0.5 4719 + 4722 3 253.65 89.3 -62.7 0.25 4713 + 4723 3 252.85 92.5 -60.7 0.5 4712 + 4724 3 248.35 87.1 -70 0.5 4656 + 4725 3 247.75 80.5 -68.8 0.5 4655 + 4726 3 240.35 86.3 -66.6 0.5 4654 + 4727 3 238.45 87.6 -65.8 0.75 4726 + 4728 3 237.85 83.2 -69 0.5 4727 + 4729 3 235.05 79.1 -69.8 0.5 4728 + 4730 3 237.05 75.3 -68.4 0.5 4729 + 4731 3 232.85 77.4 -72.8 0.5 4729 + 4732 3 235.55 83.2 -69.2 0.5 4728 + 4733 3 232.35 82.3 -69.2 0.5 4732 + 4734 3 233.45 87.2 -71.3 0.25 4732 + 4735 3 242.25 91.4 -69.1 0.5 4727 + 4736 3 238.15 97.6 -67.7 0.5 4735 + 4737 3 245.35 81 -66 0.5 4653 + 4738 3 237.25 79.9 -71.6 0.25 4652 + 4739 3 236.35 81 -71.6 0.25 4738 + 4740 3 234.95 79.9 -71.6 0.25 4738 + 4741 3 245.85 77.4 -68.8 0.25 4651 + 4742 3 244.35 72.4 -71.9 0.5 4650 + 4743 3 245.45 73.2 -72.5 0.5 4742 + 4744 3 245.45 69.5 -68 0.5 4743 + 4745 3 247.25 69.4 -71.6 0.5 4744 + 4746 3 245.45 65.9 -73.9 0.5 4744 + 4747 3 247.15 75.2 -70.9 0.25 4743 + 4748 3 241.45 70.4 -69.7 0.5 4742 + 4749 3 235.45 77.7 -70.6 0.5 4649 + 4750 3 241.35 65.8 -72.3 0.5 4648 + 4751 3 232.65 68.7 -71.2 0.5 4647 + 4752 3 232.55 71 -73.1 0.5 4751 + 4753 3 230.55 77.2 -74.2 0.5 4752 + 4754 3 228.45 69.9 -80.1 0.5 4751 + 4755 3 238.05 64.9 -75.3 0.5 4646 + 4756 3 240.75 61.6 -77.4 0.5 4755 + 4757 3 233.65 63.6 -75.3 0.25 4755 + 4758 3 232.05 66.5 -79.2 0.5 4644 + 4759 3 233.05 60.9 -79.5 0.5 4642 + 4760 3 234.55 58.5 -79.5 0.5 4759 + 4761 3 231.45 56.2 -83.1 0.5 4760 + 4762 3 234.85 53.5 -81.5 0.25 4761 + 4763 3 229.75 54.5 -83.1 0.25 4761 + 4764 3 236.25 58.5 -79.2 0.25 4760 + 4765 3 233.05 62.6 -79.5 0.25 4759 + 4766 3 226.25 62.6 -82.2 0.5 4641 + 4767 3 226.25 65.5 -80.8 0.5 4766 + 4768 3 229.15 50.8 -81.1 0.5 4639 + 4769 3 231.15 52.9 -83.4 0.5 4768 + 4770 3 233.05 52.9 -80 0.25 4769 + 4771 3 231.15 57.5 -85.8 0.5 4769 + 4772 3 230.15 49.8 -83.9 0.25 4768 + 4773 3 221.75 51.8 -87 0.5 4638 + 4774 3 219.15 53.7 -92.1 0.5 4773 + 4775 3 219.15 56.9 -91 0.5 4774 + 4776 3 217.15 50.5 -90.5 0.25 4774 + 4777 3 226.55 48 -84.1 0.5 4637 + 4778 3 229.75 45.9 -83.8 0.5 4777 + 4779 3 231.25 43.6 -86.3 0.5 4778 + 4780 3 234.45 41.2 -84.5 0.25 4779 + 4781 3 229.75 42.2 -85.9 0.5 4778 + 4782 3 226.45 42.2 -84.1 0.5 4781 + 4783 3 225.15 42.1 -84.1 0.5 4782 + 4784 3 232.05 41 -85.9 0.25 4781 + 4785 3 226.15 44.3 -86.4 0.25 4635 + 4786 3 221.85 44 -88.7 0.5 4634 + 4787 3 226.05 39.3 -89.6 0.5 4786 + 4788 3 219.65 40.3 -91.6 0.5 4786 + 4789 3 216.75 49.6 -89.7 0.5 4632 + 4790 3 216.75 52.1 -91.5 0.5 4789 + 4791 3 216.75 52.4 -91.9 0.5 4790 + 4792 3 213.15 56.5 -88 0.5 4791 + 4793 3 214.85 59 -90 0.5 4792 + 4794 3 214.85 60.4 -88.7 0.5 4793 + 4795 3 214.85 62.7 -91.6 0.5 4794 + 4796 3 210.35 59.1 -88.7 0.25 4794 + 4797 3 211.25 56.5 -88 0.25 4792 + 4798 3 212.45 53.8 -91.9 0.25 4791 + 4799 3 212.05 52.1 -93.4 0.25 4790 + 4800 3 210.95 53.8 -93.4 0.25 4799 + 4801 3 217.15 38.5 -89.9 0.5 3998 + 4802 3 218.95 37.1 -87.5 0.5 4801 + 4803 3 222.55 37.1 -87.2 0.5 4802 + 4804 3 223.65 38.8 -87.4 0.5 4803 + 4805 3 226.55 38.9 -86 0.5 4804 + 4806 3 227.45 36.2 -85.7 0.25 4805 + 4807 3 226.55 41 -89.9 0.25 4805 + 4808 3 222.45 33.8 -91.8 0.25 4803 + 4809 3 222.45 32 -91.8 0.25 4808 + 4810 3 222.45 30.3 -92.5 0.25 4809 + 4811 3 218.05 40.4 -89.9 0.25 4801 + 4812 3 207.85 32.9 -92.1 0.5 3997 + 4813 3 205.45 30.2 -93.1 0.5 4812 + 4814 3 205.65 27.1 -92.6 0.5 4813 + 4815 3 209.25 27 -95.7 0.25 4813 + 4816 3 211.65 25.1 -95.7 0.25 4815 + 4817 3 223.15 26.2 -92.5 0.5 3994 + 4818 3 222.85 29.8 -88.1 0.5 4817 + 4819 3 225.15 29.8 -88.1 0.5 4818 + 4820 3 228.25 30.6 -89.2 0.5 4819 + 4821 3 232.05 26.8 -85.4 0.5 4820 + 4822 3 233.85 25.2 -85.1 0.5 4821 + 4823 3 235.15 28.1 -85.6 0.5 4822 + 4824 3 237.65 26.9 -83.8 0.25 4823 + 4825 3 232.25 30.8 -87.7 0.25 4823 + 4826 3 234.05 23.4 -85.1 0.25 4822 + 4827 3 229.95 34.1 -86.1 0.5 4820 + 4828 3 231.45 37.2 -84.7 0.5 4827 + 4829 3 233.05 39.2 -85.5 0.5 4828 + 4830 3 232.75 34.7 -84.7 0.25 4828 + 4831 3 226.35 36.6 -87 0.25 4827 + 4832 3 226.35 28.4 -92.4 0.5 4819 + 4833 3 229.35 23.4 -89.8 0.25 4832 + 4834 3 233.25 19 -85.2 0.25 4833 + 4835 3 223.05 23 -89.2 0.25 4832 + 4836 3 226.35 19.9 -89.2 0.25 4835 + 4837 3 219.75 32 -88.1 0.25 4818 + 4838 3 225.85 23 -92.3 0.25 4817 + 4839 3 225.85 19.8 -89 0.25 4838 + 4840 3 225.85 16 -89 0.25 4839 + 4841 3 227.45 26.2 -92.3 0.25 4838 + 4842 3 230.15 14.9 -87.5 0.25 3992 + 4843 3 233.05 14.9 -88.8 0.25 4842 + 4844 3 234.95 11.7 -88.8 0.25 4843 + 4845 3 231.85 9.7 -86.5 0.25 4842 + 4846 3 226.55 -16.6 -86 0.5 3984 + 4847 3 224.55 -15 -86.9 0.5 4846 + 4848 3 222.45 -14.8 -89.1 0.5 4847 + 4849 3 218.75 -14.8 -89.9 0.75 4848 + 4850 3 218.35 -18.8 -91.6 0.5 4849 + 4851 3 217.05 -12.3 -90.2 0.25 4849 + 4852 3 222.45 -10.3 -86.9 0.25 4848 + 4853 3 220.15 -5.7 -89.4 0.25 4852 + 4854 3 228.15 -11.9 -90 0.25 4847 + 4855 3 225.15 -10.9 -90 0.25 4854 + 4856 3 230.25 -9.6 -90 0.25 4854 + 4857 3 226.55 -21.1 -88.9 0.25 4846 + 4858 3 224.05 -27.8 -90.4 0.25 3981 + 4859 3 220.85 -27.8 -88.2 0.25 4858 + 4860 3 223.35 -35.5 -88.7 0.5 3979 + 4861 3 218.95 -35.5 -92.7 0.5 4860 + 4862 3 216.95 -40.4 -95.7 0.5 4861 + 4863 3 215.45 -43.2 -97.1 0.5 4862 + 4864 3 217.35 -33.8 -93.5 0.25 4861 + 4865 3 215.45 -33.8 -95 0.25 4864 + 4866 3 212.35 -30.5 -94.5 0.25 4865 + 4867 3 227.25 -46.8 -83.6 0.5 127 + 4868 3 230.65 -50 -80 0.5 4867 + 4869 3 230.15 -55.6 -79.9 0.5 4868 + 4870 3 232.95 -57.9 -77.7 0.5 4869 + 4871 3 234.85 -61.4 -76.7 0.5 4870 + 4872 3 239.65 -61.3 -72.1 0.5 4871 + 4873 3 242.15 -64.7 -74.5 0.5 4872 + 4874 3 242.15 -67.7 -73.7 0.5 4873 + 4875 3 246.45 -70.6 -69.3 0.25 4874 + 4876 3 246.85 -73.4 -69.5 0.25 4875 + 4877 3 247.65 -76.3 -69.5 0.25 4876 + 4878 3 248.65 -70.6 -71.9 0.25 4875 + 4879 3 237.75 -66.3 -75 0.25 4871 + 4880 3 237.75 -71 -74.5 0.25 4879 + 4881 3 240.25 -74.6 -74.5 0.25 4880 + 4882 3 235.15 -77.9 -71.8 0.25 4881 + 4883 3 232.35 -82.5 -76.3 0.25 4882 + 4884 3 231.05 -85.8 -77.6 0.25 4883 + 4885 3 232.85 -94 -78.3 0.25 4884 + 4886 3 228.35 -89.5 -73.1 0.25 4884 + 4887 3 238.95 -79 -72.8 0.25 4881 + 4888 3 238.85 -86.9 -74.2 0.25 4887 + 4889 3 226.55 -57.2 -82.9 0.5 4869 + 4890 3 224.45 -57.2 -83.5 0.5 4889 + 4891 3 224.05 -55.6 -83.5 0.5 4890 + 4892 3 221.35 -50.2 -86.9 0.5 4891 + 4893 3 222.95 -61.1 -82.1 0.25 4890 + 4894 3 221.35 -58.7 -82.1 0.25 4893 + 4895 3 222.95 -62.6 -82.1 0.25 4893 + 4896 3 210.85 -48.7 -91.5 0.5 125 + 4897 3 207.45 -52.6 -91 0.5 4896 + 4898 3 201.45 -53.6 -94.7 0.75 4897 + 4899 3 199.55 -56.7 -93 0.5 4898 + 4900 3 197.75 -53.6 -94.6 0.5 4898 + 4901 3 220.35 -54.6 -87.9 0.75 124 + 4902 3 222.35 -58.2 -84 0.75 4901 + 4903 3 222.55 -62 -85.3 0.5 4902 + 4904 3 222.55 -65.5 -82.7 0.75 4903 + 4905 3 226.85 -71.3 -80.2 0.5 4904 + 4906 3 228.05 -77.8 -84.7 0.5 4905 + 4907 3 230.15 -82.8 -79.8 0.5 4906 + 4908 3 224.75 -88.4 -85.7 0.5 4907 + 4909 3 232.05 -86.3 -81.2 0.5 4907 + 4910 3 222.15 -75.9 -80.2 0.25 4905 + 4911 3 222.15 -80.3 -81 0.25 4910 + 4912 3 217.95 -63.5 -84.5 0.5 4903 + 4913 3 220.15 -68.6 -83.3 0.25 4912 + 4914 3 216.15 -75.6 -86.5 0.25 4913 + 4915 3 220.15 -77.1 -83.3 0.25 4913 + 4916 3 215.95 -56.8 -95.1 0.5 123 + 4917 3 208.15 -60.5 -91.5 0.5 120 + 4918 3 208.35 -62 -93.3 0.5 4917 + 4919 3 208.35 -63.6 -91.7 0.5 4918 + 4920 3 211.65 -66.8 -90.5 0.5 4919 + 4921 3 215.15 -69.8 -89 0.5 4920 + 4922 3 215.05 -71.4 -89 0.5 4921 + 4923 3 212.55 -75.8 -85.6 0.5 4922 + 4924 3 210.15 -77.2 -89.1 0.5 4923 + 4925 3 205.05 -79.8 -88 0.5 4924 + 4926 3 199.55 -77.9 -91.6 0.5 4925 + 4927 3 196.25 -77.9 -92 0.5 4926 + 4928 3 198.55 -85.9 -93.7 0.5 4926 + 4929 3 201.75 -83.2 -86.6 0.25 4925 + 4930 3 197.95 -84.8 -86.6 0.25 4929 + 4931 3 211.35 -75.8 -85.6 0.25 4923 + 4932 3 220.15 -74.6 -91.9 0.25 4922 + 4933 3 205.95 -65.9 -91.7 0.5 4919 + 4934 3 210.65 -69.9 -90.4 0.5 4933 + 4935 3 210.15 -68.9 -88.7 0.5 4934 + 4936 3 213.75 -71.2 -88.7 0.25 4935 + 4937 3 210.05 -73 -91.9 0.5 4934 + 4938 3 203.85 -68.2 -95.3 0.5 4933 + 4939 3 207.85 -71.3 -97.1 0.5 4938 + 4940 3 205.35 -72.8 -97.1 0.5 4939 + 4941 3 200.05 -56 -95.9 0.5 119 + 4942 3 201.25 -51.7 -94.5 0.5 4941 + 4943 3 202.55 -48.3 -95 0.5 4942 + 4944 3 202.75 -45.1 -94.3 0.5 4943 + 4945 3 205.75 -46.3 -94.9 0.25 4943 + 4946 3 183.95 -60.6 -101.5 2 114 + 4947 3 187.25 -56.4 -101.9 1.25 4946 + 4948 3 189.45 -52.6 -100.6 1.5 4947 + 4949 3 190.25 -49.4 -101.3 1.75 4948 + 4950 3 191.15 -47.2 -103 1.75 4949 + 4951 3 192.75 -45.1 -104.8 1.5 4950 + 4952 3 192.75 -40.5 -103.5 1.25 4951 + 4953 3 197.75 -34.7 -101.4 1 4952 + 4954 3 197.85 -30.3 -99.1 1.25 4953 + 4955 3 201.55 -23.2 -100.7 1.25 4954 + 4956 3 200.85 -17.9 -97.5 1.5 4955 + 4957 3 204.05 -15.3 -100.1 1.25 4956 + 4958 3 202.65 -12.9 -97.4 1.25 4957 + 4959 3 206.75 -5 -96.3 1.25 4958 + 4960 3 207.45 3.3 -95.8 1.25 4959 + 4961 3 208.65 13.2 -99 1.5 4960 + 4962 3 205.55 15.9 -95.7 1.25 4961 + 4963 3 206.55 20.7 -99.3 1.25 4962 + 4964 3 204.25 21.8 -97.7 1.5 4963 + 4965 3 203.05 27 -96.5 1.5 4964 + 4966 3 198.95 35.9 -98.7 1.75 4965 + 4967 3 194.35 43.3 -98.5 2 4966 + 4968 3 190.35 50 -100 2 4967 + 4969 3 184.75 57.4 -99.8 2 4968 + 4970 3 180.95 61.2 -100.8 2 4969 + 4971 3 180.45 63.7 -100.2 2.25 4970 + 4972 3 176.55 69.5 -96.5 2 4971 + 4973 3 176.55 71.6 -95.5 1.25 4972 + 4974 3 177.65 73.8 -93.7 1.25 4973 + 4975 3 179.45 77.5 -92 1.25 4974 + 4976 3 179.45 78.6 -92.6 1.25 4975 + 4977 3 179.45 81 -89 1.25 4976 + 4978 3 181.65 85.3 -90.3 1.25 4977 + 4979 3 183.55 90.5 -87.8 1.5 4978 + 4980 3 182.25 93.5 -83.7 1.75 4979 + 4981 3 185.45 97.7 -80.1 1.5 4980 + 4982 3 185.95 100.4 -78.1 1.75 4981 + 4983 3 188.65 104 -80.3 1.75 4982 + 4984 3 190.35 107.2 -79.6 1.75 4983 + 4985 3 189.15 107.2 -76.5 1.75 4984 + 4986 3 190.65 110 -77.9 1.75 4985 + 4987 3 189.65 111.1 -77.7 1.75 4986 + 4988 3 191.85 113.8 -74.8 1.75 4987 + 4989 3 190.55 113.8 -73.7 1.75 4988 + 4990 3 189.65 116.5 -73.5 1.75 4989 + 4991 3 189.95 118.4 -76.1 1.75 4990 + 4992 3 188.55 120.9 -75.1 1.5 4991 + 4993 3 187.55 122.1 -72.2 2 4992 + 4994 3 188.95 120.1 -73 1.5 4993 + 4995 3 188.65 119.6 -70.4 1.25 4994 + 4996 3 184.85 124.9 -70.7 1.25 4995 + 4997 3 182.85 127.1 -70.2 1 4996 + 4998 3 180.85 131.4 -69.5 1.75 4997 + 4999 3 179.75 133.3 -69.4 1.5 4998 + 5000 3 182.25 136.9 -66.4 1 4999 + 5001 3 182.95 139.6 -64.9 1.25 5000 + 5002 3 186.75 139.6 -64.7 1 5001 + 5003 3 185.35 143.1 -64.5 1.5 5002 + 5004 3 188.05 145.1 -61.5 1.25 5003 + 5005 3 188.25 145.9 -60.9 1.25 5004 + 5006 3 185.95 150.6 -61.2 1.25 5005 + 5007 3 185.95 151.8 -58.8 1.25 5006 + 5008 3 186.85 154.5 -59.2 1.25 5007 + 5009 3 183.25 157.8 -60.2 1.25 5008 + 5010 3 184.55 159.1 -61.7 1.25 5009 + 5011 3 182.45 161.1 -62.6 1 5010 + 5012 3 182.45 163.2 -65.1 1 5011 + 5013 3 183.35 165.6 -60.8 1 5012 + 5014 3 184.85 167.3 -61.2 1.25 5013 + 5015 3 183.75 169.2 -62.2 1.75 5014 + 5016 3 185.75 171.1 -63 1.75 5015 + 5017 3 185.45 171.9 -62.8 1.75 5016 + 5018 3 185.45 174.2 -62.7 1.5 5017 + 5019 3 187.35 176.5 -58.9 1.5 5018 + 5020 3 186.55 179.8 -57.2 0.75 5019 + 5021 3 188.35 181.1 -58.8 0.75 5020 + 5022 3 189.55 182.5 -59.5 0.75 5021 + 5023 3 189.55 182 -64.4 1 5022 + 5024 3 191.55 184.8 -66.3 1 5023 + 5025 3 189.85 187.8 -66.2 0.75 5024 + 5026 3 190.05 188.7 -65.9 0.75 5025 + 5027 3 186.25 192.2 -73.3 0.5 5026 + 5028 3 184.15 192.2 -73.9 0.5 5027 + 5029 3 181.45 194.4 -77.1 0.5 5028 + 5030 3 179.25 194.4 -77.1 0.25 5029 + 5031 3 178.55 197.2 -77.1 0.25 5030 + 5032 3 177.65 192.4 -75.1 0.25 5030 + 5033 3 190.25 193.2 -75.5 0.5 5027 + 5034 3 195.05 192.2 -77.7 0.5 5033 + 5035 3 193.75 191.5 -75.8 0.25 5033 + 5036 3 187.15 188.7 -68.4 0.5 5026 + 5037 3 183.35 190.1 -68.5 0.5 5036 + 5038 3 181.45 188.2 -68.5 0.25 5037 + 5039 3 183.85 185.6 -68.6 0.5 5036 + 5040 3 193.75 189 -66.4 0.5 5025 + 5041 3 195.35 191.5 -68.2 0.5 5040 + 5042 3 195.55 186.9 -66.4 0.25 5040 + 5043 3 195.35 180.3 -62.4 0.5 5023 + 5044 3 199.05 179.8 -58.7 0.5 5043 + 5045 3 200.35 182.5 -61 0.5 5044 + 5046 3 198.35 178.3 -58.7 0.25 5044 + 5047 3 184.05 183.9 -66.4 0.5 5022 + 5048 3 180.85 184.8 -67.4 0.5 5047 + 5049 3 179.05 185.4 -66.2 0.5 5048 + 5050 3 179.05 187.1 -68.3 0.5 5049 + 5051 3 184.05 179.5 -68.9 0.5 5047 + 5052 3 184.35 181.1 -61.3 0.5 5021 + 5053 3 191.35 178.7 -58.4 0.5 5019 + 5054 3 197.55 179.6 -55.7 0.5 5053 + 5055 3 198.85 181.7 -57.1 0.5 5054 + 5056 3 198.65 181.6 -61.9 0.5 5055 + 5057 3 196.15 183.8 -59.5 0.25 5056 + 5058 3 199.45 186.4 -62.4 0.5 5057 + 5059 3 194.95 183.8 -59.5 0.25 5057 + 5060 3 198.75 181.6 -59.4 0.5 5056 + 5061 3 195.25 182.3 -57.1 0.5 5055 + 5062 3 199.25 176.2 -60.5 0.5 5054 + 5063 3 198.45 174.3 -57.7 0.5 5062 + 5064 3 201.55 179.5 -61.3 0.25 5062 + 5065 3 194.25 174.6 -53.6 0.25 5053 + 5066 3 196.35 174.6 -53.6 0.25 5065 + 5067 3 194.25 174.9 -53.6 0.25 5065 + 5068 3 182.05 175.6 -65.2 0.5 5018 + 5069 3 184.35 177.4 -65.6 0.5 5068 + 5070 3 179.55 176.7 -68.8 0.5 5069 + 5071 3 179.55 180.4 -71 0.25 5070 + 5072 3 179.55 181.7 -70.7 0.25 5071 + 5073 3 177.05 175.3 -68.8 0.5 5070 + 5074 3 185.35 179.7 -65.6 0.25 5069 + 5075 3 180.55 170.7 -65.1 0.5 5068 + 5076 3 190.45 173.5 -60.5 0.5 5017 + 5077 3 193.65 168.8 -58.1 0.5 5076 + 5078 3 196.15 169.6 -58.1 0.5 5077 + 5079 3 191.75 169.1 -60 0.25 5076 + 5080 3 186.95 166.5 -64.2 0.75 5016 + 5081 3 190.65 166.5 -61.1 0.5 5080 + 5082 3 194.35 163.5 -64.5 0.5 5081 + 5083 3 197.35 159 -60.6 0.5 5082 + 5084 3 198.05 157.2 -60.6 0.5 5083 + 5085 3 196.65 155 -60.6 0.5 5084 + 5086 3 199.65 157.2 -60.6 0.25 5084 + 5087 3 197.25 165 -61.2 0.25 5082 + 5088 3 200.35 162.5 -61.2 0.25 5087 + 5089 3 193.05 168.1 -61.1 0.25 5081 + 5090 3 187.85 162.8 -68.2 0.5 5080 + 5091 3 184.75 164.5 -68.2 0.25 5090 + 5092 3 190.35 161.9 -68.2 0.5 5090 + 5093 3 179.15 168.1 -61.9 0.5 5015 + 5094 3 176.55 170.7 -61.4 0.5 5093 + 5095 3 174.85 168.4 -61.4 0.25 5094 + 5096 3 175.95 166.5 -61.4 0.5 5095 + 5097 3 172.55 171.2 -58.7 0.25 5095 + 5098 3 180.45 167.3 -59.8 0.25 5014 + 5099 3 180.15 164 -65.1 0.5 5012 + 5100 3 176.65 161 -61.5 0.5 5099 + 5101 3 176.65 165.7 -64.6 0.5 5100 + 5102 3 173.55 167.9 -66.5 0.5 5101 + 5103 3 175.65 169.5 -61.9 0.5 5102 + 5104 3 176.65 171.1 -59.8 0.5 5103 + 5105 3 178.35 172.1 -59.8 0.5 5104 + 5106 3 173.95 173.2 -59.8 0.5 5104 + 5107 3 170.45 167.9 -66.1 0.25 5102 + 5108 3 173.25 161 -61.6 0.25 5100 + 5109 3 171.25 162.9 -61.6 0.25 5108 + 5110 3 177.05 164.9 -61.9 0.25 5099 + 5111 3 181.45 159.1 -62.6 0.5 5010 + 5112 3 183.15 153.9 -65 0.5 5009 + 5113 3 183.15 152.9 -65 0.5 5112 + 5114 3 180.55 154.1 -67.4 0.25 5113 + 5115 3 183.15 151.6 -65 0.25 5113 + 5116 3 191.05 157.5 -59.2 0.5 5008 + 5117 3 195.15 160.6 -58.2 0.75 5116 + 5118 3 198.35 162.1 -62.3 0.5 5117 + 5119 3 197.35 155.5 -64.6 0.5 5117 + 5120 3 198.25 153.3 -64.6 0.5 5119 + 5121 3 200.15 153.4 -64.6 0.25 5120 + 5122 3 196.15 153.6 -64.6 0.25 5120 + 5123 3 195.65 154.1 -62.5 0.25 5119 + 5124 3 190.75 153.8 -64.4 0.5 5116 + 5125 3 182.25 151.8 -64.3 0.5 5007 + 5126 3 190.05 150.6 -65 0.5 5006 + 5127 3 192.25 146.8 -66.3 0.5 5126 + 5128 3 191.15 146.8 -66.3 0.5 5127 + 5129 3 191.15 144.1 -65.5 0.25 5128 + 5130 3 192.95 144.6 -68.4 0.25 5129 + 5131 3 196.85 140.2 -66 0.25 5130 + 5132 3 197.75 145.6 -66.5 0.25 5130 + 5133 3 195.05 148.6 -66.3 0.25 5128 + 5134 3 191.75 142.7 -68.5 0.5 5005 + 5135 3 182.85 147.1 -69.7 0.5 5004 + 5136 3 180.75 146.6 -69.4 0.5 5135 + 5137 3 177.75 146.6 -69.4 0.5 5136 + 5138 3 182.15 142.4 -59.1 0.25 5003 + 5139 3 182.95 141.2 -72.8 0.5 5001 + 5140 3 178.15 143.3 -72.8 0.5 5139 + 5141 3 175.65 141.8 -70.6 0.25 5140 + 5142 3 176.85 145.5 -68.9 0.5 5140 + 5143 3 174.85 146.3 -70.3 0.5 5142 + 5144 3 176.05 137.3 -65.7 0.75 4999 + 5145 3 175.15 139.9 -69.1 1.25 5144 + 5146 3 175.95 139.9 -65.5 0.75 5145 + 5147 3 172.15 144.9 -68.6 0.75 5146 + 5148 3 172.15 144.6 -66.3 0.75 5147 + 5149 3 172.15 148.4 -67.7 1 5148 + 5150 3 173.95 150.1 -62.9 0.75 5149 + 5151 3 174.75 153.5 -61.8 0.75 5150 + 5152 3 176.05 156.4 -64.7 0.75 5151 + 5153 3 174.95 155.8 -62 0.5 5152 + 5154 3 177.45 158.3 -64.7 0.5 5153 + 5155 3 179.85 156.2 -65.6 0.5 5154 + 5156 3 179.45 157.8 -65.6 0.5 5155 + 5157 3 180.75 153.6 -67.4 0.5 5155 + 5158 3 177.05 155.2 -66 0.5 5153 + 5159 3 176.15 154.3 -66 0.5 5158 + 5160 3 179.45 151.5 -66 0.5 5159 + 5161 3 179.65 155.2 -66 0.25 5158 + 5162 3 172.65 158.2 -62 0.25 5152 + 5163 3 170.95 154.3 -70.2 0.5 5151 + 5164 3 169.55 151.9 -70.2 0.5 5163 + 5165 3 175.85 148.3 -71.1 0.5 5150 + 5166 3 167.85 148 -67.4 0.5 5149 + 5167 3 165.95 151.7 -64.9 0.5 5166 + 5168 3 166.85 153.5 -64.9 0.5 5167 + 5169 3 163.85 148.4 -67 0.25 5167 + 5170 3 170.85 144.6 -72.7 0.5 5148 + 5171 3 170.85 142.9 -72.7 0.5 5170 + 5172 3 169.35 144 -72.7 0.5 5171 + 5173 3 169.35 141.3 -73.7 0.5 5172 + 5174 3 172.95 141.3 -71.2 0.5 5173 + 5175 3 167.85 140.5 -73.7 0.5 5173 + 5176 3 173.55 142.1 -72.7 0.25 5171 + 5177 3 171.45 139.9 -67.1 0.5 5145 + 5178 3 171.95 137.9 -68.7 0.5 5177 + 5179 3 166.85 140.4 -68.3 0.75 5178 + 5180 3 167.05 141.3 -74.3 0.75 5179 + 5181 3 162.15 142.5 -75.4 0.5 5180 + 5182 3 164.45 137.1 -71.6 0.25 5180 + 5183 3 168.85 136 -71.8 0.5 5178 + 5184 3 186.15 132.4 -66.9 0.5 4998 + 5185 3 189.65 130.7 -70.4 0.5 5184 + 5186 3 191.35 128.9 -70.9 0.5 5185 + 5187 3 195.05 128.9 -73.7 0.5 5186 + 5188 3 196.15 125.1 -71.1 0.5 5187 + 5189 3 191.35 126 -74 0.5 5186 + 5190 3 190.45 123.4 -71.2 0.25 5189 + 5191 3 187.35 124.8 -74 0.5 5189 + 5192 3 188.45 134.1 -73.4 0.5 5185 + 5193 3 191.45 134.1 -69 0.25 5192 + 5194 3 188.75 135.5 -72 0.5 5192 + 5195 3 184.15 122.2 -75 0.5 4995 + 5196 3 181.95 121.3 -78.8 0.5 5195 + 5197 3 178.85 124.5 -76.5 0.5 5196 + 5198 3 181.35 126.3 -76.5 0.5 5197 + 5199 3 180.15 120.9 -78.8 0.25 5196 + 5200 3 192.05 124.6 -69.7 1.25 4993 + 5201 3 191.55 128.7 -68.3 1.25 5200 + 5202 3 193.95 130.2 -67 1.25 5201 + 5203 3 195.05 136.4 -64.4 1.5 5202 + 5204 3 195.75 136.4 -61.8 1.25 5203 + 5205 3 196.15 140.8 -61.9 1.25 5204 + 5206 3 194.45 142.1 -63.2 1.25 5205 + 5207 3 195.55 144.6 -61.6 1.25 5206 + 5208 3 196.45 146 -59.2 1.25 5207 + 5209 3 196.45 147 -61.6 1.25 5208 + 5210 3 194.35 150.1 -57.9 1.5 5209 + 5211 3 197.35 150.7 -57.6 1.5 5210 + 5212 3 196.25 154 -54.9 1.75 5211 + 5213 3 197.95 158.2 -57.7 1.75 5212 + 5214 3 200.85 158.3 -57.8 1.75 5213 + 5215 3 199.55 163.1 -57.8 1.75 5214 + 5216 3 201.55 162.4 -57.7 1.75 5215 + 5217 3 202.75 167.1 -59.1 2 5216 + 5218 3 204.45 167.6 -57.4 2.25 5217 + 5219 3 209.35 169.2 -59.7 1.5 5218 + 5220 3 210.45 169.6 -60.7 1.25 5219 + 5221 3 213.15 168.7 -59.5 1.75 5220 + 5222 3 214.15 169.1 -62.2 2 5221 + 5223 3 218.65 173.4 -63.6 1.75 5222 + 5224 3 223.25 174.2 -62.6 1 5223 + 5225 3 225.95 172.7 -70.1 1 5224 + 5226 3 225.95 176.5 -70.3 1 5225 + 5227 3 229.65 178.2 -71.2 0.75 5226 + 5228 3 229.65 177.9 -74.1 1 5227 + 5229 3 235.05 182 -75.9 0.5 5228 + 5230 3 234.35 176.2 -77.2 0.5 5228 + 5231 3 238.15 174.9 -74.5 0.5 5230 + 5232 3 236.95 172.3 -77.2 0.5 5230 + 5233 3 232.15 172.7 -67.2 0.5 5226 + 5234 3 231.85 172.7 -67.8 0.5 5233 + 5235 3 236.45 175.5 -69.6 0.25 5234 + 5236 3 235.55 172.8 -67.8 0.25 5234 + 5237 3 224.05 169.5 -67.1 0.5 5224 + 5238 3 221.45 167.8 -62.9 0.75 5223 + 5239 3 219.15 164.7 -61.5 0.75 5238 + 5240 3 219.35 162.3 -61.6 0.5 5239 + 5241 3 222.15 160.8 -61.6 0.5 5240 + 5242 3 217.05 164.7 -59.9 0.5 5239 + 5243 3 215.65 166.1 -59.9 0.5 5242 + 5244 3 222.95 169 -63.7 0.5 5238 + 5245 3 224.65 166.2 -63.7 0.5 5244 + 5246 3 216.15 163.2 -58.8 0.25 5222 + 5247 3 211.35 164.4 -64.7 0.5 5221 + 5248 3 209.35 164.4 -63.6 0.25 5247 + 5249 3 214.35 162.7 -65.6 0.25 5247 + 5250 3 206.75 163.8 -66.6 0.5 5220 + 5251 3 203.65 164.7 -66.6 0.5 5250 + 5252 3 205.25 167.3 -66.6 0.25 5250 + 5253 3 205.25 170.2 -59.6 1.25 5218 + 5254 3 205.25 173.7 -61.9 1 5253 + 5255 3 203.15 175.8 -59.7 1 5254 + 5256 3 204.55 175.7 -63.5 1.25 5255 + 5257 3 207.95 178.2 -64.3 1.75 5256 + 5258 3 209.35 177.4 -64.8 1.25 5257 + 5259 3 211.95 178.7 -66.7 0.75 5258 + 5260 3 211.95 181 -65.2 0.75 5259 + 5261 3 214.55 183 -68.4 1 5260 + 5262 3 218.55 182.1 -72.2 1.25 5261 + 5263 3 220.65 184.5 -71.5 1.25 5262 + 5264 3 220.25 185.7 -79.8 0.75 5263 + 5265 3 222.05 184.2 -80.8 0.5 5264 + 5266 3 221.25 187.8 -82 0.5 5265 + 5267 3 223.35 192 -85.8 0.5 5266 + 5268 3 218.25 190 -87.3 0.5 5266 + 5269 3 226.95 182.6 -83.2 0.5 5265 + 5270 3 216.65 188.2 -84.9 0.5 5264 + 5271 3 223.25 180.8 -80.5 0.5 5263 + 5272 3 225.85 176.3 -76.9 0.5 5271 + 5273 3 218.45 176.5 -73.5 0.5 5261 + 5274 3 221.55 177.5 -73 0.5 5273 + 5275 3 224.25 172.9 -73 0.5 5274 + 5276 3 218.45 173.4 -73.5 0.5 5273 + 5277 3 209.15 182.2 -70.4 0.5 5260 + 5278 3 214.55 177.1 -65.2 0.5 5259 + 5279 3 215.95 173.8 -69.6 0.5 5278 + 5280 3 212.35 173.9 -65.6 0.5 5258 + 5281 3 208.25 172 -65.6 0.5 5280 + 5282 3 213.95 174.9 -65.6 0.5 5280 + 5283 3 205.55 181.2 -62.7 1.25 5257 + 5284 3 207.25 181.5 -71 1.5 5283 + 5285 3 204.05 183.7 -70.9 1.25 5284 + 5286 3 206.05 186.2 -69.6 1.25 5285 + 5287 3 206.05 188 -71.1 1.25 5286 + 5288 3 206.05 189.2 -69.9 1.25 5287 + 5289 3 207.85 190.6 -77.8 0.5 5288 + 5290 3 212.95 190.6 -75.2 0.5 5289 + 5291 3 208.15 194.1 -82 0.25 5289 + 5292 3 206.05 195.4 -82 0.25 5291 + 5293 3 203.35 192 -77.5 0.5 5288 + 5294 3 199.35 193.2 -79.7 0.5 5293 + 5295 3 206.15 192 -77.5 0.5 5293 + 5296 3 199.45 188 -75.2 0.25 5287 + 5297 3 202.25 185.1 -73.3 0.5 5285 + 5298 3 199.75 181.4 -73.3 0.25 5297 + 5299 3 200.85 186.1 -69.7 0.25 5297 + 5300 3 212.15 181.5 -68 0.5 5284 + 5301 3 200.75 180.3 -70 0.5 5283 + 5302 3 198.35 180.3 -66.2 0.5 5301 + 5303 3 205.15 177.3 -61.6 0.75 5256 + 5304 3 201.35 176.1 -67.1 0.5 5303 + 5305 3 199.95 176.1 -66.1 0.75 5304 + 5306 3 197.45 176.6 -69.1 0.5 5305 + 5307 3 198.85 176 -65.4 0.5 5306 + 5308 3 195.85 178 -65.4 0.5 5307 + 5309 3 194.15 173.8 -66.1 0.25 5307 + 5310 3 201.65 181 -67.5 0.5 5304 + 5311 3 202.25 172.6 -69.1 0.5 5303 + 5312 3 200.45 167.8 -61.7 0.5 5217 + 5313 3 198.35 167.4 -59.3 0.75 5312 + 5314 3 195.95 165.7 -62.8 0.75 5313 + 5315 3 196.25 169.7 -63.2 0.75 5314 + 5316 3 197.65 163.7 -58 0.25 5312 + 5317 3 208.75 159.5 -60.2 0.5 5216 + 5318 3 212.15 154.1 -58.9 0.5 5317 + 5319 3 207.95 155 -63.1 0.5 5317 + 5320 3 211.45 153.9 -60.1 0.5 5319 + 5321 3 199.05 163.1 -61.9 0.5 5215 + 5322 3 195.95 164.7 -61.9 0.5 5321 + 5323 3 194.65 160.4 -61.9 0.5 5321 + 5324 3 202.75 158.3 -60 0.5 5214 + 5325 3 206.85 157.2 -58.9 0.5 5324 + 5326 3 201.95 150.5 -63 0.5 5212 + 5327 3 204.25 150.3 -60.9 0.5 5326 + 5328 3 201.95 151.1 -57.5 0.5 5211 + 5329 3 203.65 153.1 -58.7 0.5 5328 + 5330 3 202.75 147.9 -58.4 0.25 5328 + 5331 3 200.15 147.4 -61.1 0.5 5209 + 5332 3 202.55 145.8 -64.5 0.5 5331 + 5333 3 202.25 147.3 -61.8 0.25 5331 + 5334 3 192.75 147.8 -66.2 0.5 5208 + 5335 3 191.55 150.1 -65.7 0.5 5334 + 5336 3 188.35 152.8 -64.6 0.5 5335 + 5337 3 194.25 149.8 -66.5 0.25 5335 + 5338 3 190.45 144.2 -68.8 0.25 5334 + 5339 3 190.85 145.3 -65.5 0.5 5207 + 5340 3 191.65 142.6 -65.3 0.5 5339 + 5341 3 189.95 146.7 -68.2 0.25 5339 + 5342 3 190.85 142.1 -67.3 0.5 5206 + 5343 3 199.85 140.8 -63.3 0.5 5205 + 5344 3 202.05 142.7 -63.3 0.5 5343 + 5345 3 198.25 135.2 -61.8 0.5 5203 + 5346 3 198.35 138.6 -61.1 0.5 5345 + 5347 3 199.95 141.4 -58.5 0.5 5346 + 5348 3 200.75 144.1 -60 0.5 5347 + 5349 3 203.25 144.9 -58.5 0.5 5348 + 5350 3 204.45 143.3 -60.8 0.5 5349 + 5351 3 205.55 142.6 -60.9 0.5 5350 + 5352 3 206.85 142.9 -64.9 0.5 5351 + 5353 3 209.45 139.3 -64 0.5 5352 + 5354 3 205.65 136.6 -65.7 0.5 5353 + 5355 3 211.35 137.9 -64 0.25 5353 + 5356 3 203.75 140.2 -63.2 0.25 5351 + 5357 3 206.75 146.4 -60.8 0.5 5350 + 5358 3 200.75 147.6 -56.8 0.5 5349 + 5359 3 204.35 149.5 -56.8 0.5 5358 + 5360 3 205.15 148.8 -58.2 0.5 5359 + 5361 3 204.25 151.9 -59.8 0.5 5360 + 5362 3 207.95 153.8 -58.9 0.5 5361 + 5363 3 207.05 156.1 -56.7 0.5 5362 + 5364 3 208.25 147.8 -62.7 0.5 5361 + 5365 3 206.75 145.8 -63.5 0.25 5364 + 5366 3 209.45 144.5 -63.5 0.25 5365 + 5367 3 210.45 147.5 -62.7 0.5 5364 + 5368 3 207.25 146.9 -59.5 0.5 5360 + 5369 3 198.15 144.1 -61.1 0.25 5348 + 5370 3 201.95 132.9 -68.2 0.5 5345 + 5371 3 189.35 134 -72 0.5 5202 + 5372 3 188.95 134.8 -68.8 0.5 5371 + 5373 3 187.45 136.8 -72.9 0.5 5372 + 5374 3 188.25 139.2 -71.5 0.5 5373 + 5375 3 185.15 138.6 -74.4 0.5 5373 + 5376 3 184.35 135.9 -68.8 0.5 5372 + 5377 3 186.05 131 -67.2 0.5 5371 + 5378 3 197.15 128.7 -65.5 0.5 5201 + 5379 3 195.75 126.3 -67.6 0.5 5378 + 5380 3 199.95 127.2 -63.8 0.5 5379 + 5381 3 202.35 128.2 -68.7 0.25 5380 + 5382 3 201.65 124.6 -67.8 0.25 5380 + 5383 3 198.85 123.8 -70.5 0.25 5379 + 5384 3 194.65 118 -76.1 0.5 4991 + 5385 3 197.75 117 -72.4 0.5 5384 + 5386 3 196.35 121.7 -75.2 0.25 5384 + 5387 3 194.65 118.5 -73.5 0.5 4990 + 5388 3 196.05 120.7 -71.5 0.5 5387 + 5389 3 201.65 119.1 -71 0.5 5388 + 5390 3 205.35 117 -75.1 0.5 5389 + 5391 3 207.65 118.5 -75.2 0.5 5390 + 5392 3 207.55 116 -71.4 0.5 5391 + 5393 3 210.95 113.1 -71.4 0.25 5392 + 5394 3 206.35 113.7 -71.4 0.25 5392 + 5395 3 205.35 115.7 -75.1 0.5 5390 + 5396 3 198.85 123.1 -71.5 0.25 5388 + 5397 3 195.95 116.3 -75.7 0.25 4989 + 5398 3 197.55 114.1 -75.7 0.25 5397 + 5399 3 184.75 114.4 -75.2 0.5 4987 + 5400 3 183.95 115.3 -75.2 0.5 5399 + 5401 3 181.95 117.4 -76.9 0.5 5400 + 5402 3 181.25 118.2 -76.8 0.75 5401 + 5403 3 179.55 120.9 -79.1 0.5 5402 + 5404 3 177.35 124.2 -77.4 0.5 5403 + 5405 3 175.45 127.2 -73.3 0.5 5404 + 5406 3 174.05 129 -74.5 0.5 5405 + 5407 3 175.95 129 -73.3 0.5 5406 + 5408 3 172.55 134 -72.4 0.5 5407 + 5409 3 171.75 135.6 -76 0.5 5408 + 5410 3 173.75 136.5 -76 0.5 5409 + 5411 3 168.95 139.2 -72.8 0.5 5410 + 5412 3 166.85 141.9 -75.2 0.5 5411 + 5413 3 174.35 138.9 -75.8 0.5 5410 + 5414 3 170.25 135.6 -76 0.5 5409 + 5415 3 177.25 129 -73.3 0.5 5407 + 5416 3 171.85 129.7 -78.7 0.5 5406 + 5417 3 171.85 131.9 -78 0.5 5416 + 5418 3 170.55 127.3 -76.8 0.5 5416 + 5419 3 170.55 125.3 -76.8 0.25 5418 + 5420 3 180.25 123.8 -77.4 0.25 5404 + 5421 3 177.45 118.7 -78.1 0.5 5403 + 5422 3 184.95 121.6 -79.2 0.5 5402 + 5423 3 180.75 115 -76.9 0.5 5401 + 5424 3 184.65 113.6 -80.1 0.5 5400 + 5425 3 185.95 109.4 -81.7 0.25 5424 + 5426 3 187.65 107.3 -81.7 0.25 5425 + 5427 3 180.55 113.6 -81.2 0.5 5424 + 5428 3 179.25 110.8 -81.2 0.25 5427 + 5429 3 188.55 113.7 -75.2 0.25 5399 + 5430 3 193.45 107.7 -78 0.25 4986 + 5431 3 196.45 106.5 -78 0.25 5430 + 5432 3 193.45 106 -78 0.25 5430 + 5433 3 193.75 107 -82.3 0.25 4985 + 5434 3 196.45 104.5 -82.3 0.25 5433 + 5435 3 198.85 102.8 -82.3 0.25 5434 + 5436 3 185.35 107.7 -82.1 0.25 4984 + 5437 3 183.65 110.8 -82.1 0.25 5436 + 5438 3 181.75 112.7 -78.1 0.25 5437 + 5439 3 180.25 114 -83.1 0.25 5438 + 5440 3 179.05 111 -84.6 0.25 5439 + 5441 3 180.25 115.5 -83.1 0.25 5439 + 5442 3 186.95 114.9 -78.1 0.25 5438 + 5443 3 185.35 104.1 -83.8 0.25 4983 + 5444 3 183.85 105.3 -84.6 0.25 5443 + 5445 3 183.15 106.1 -80.9 0.25 4982 + 5446 3 178.75 110 -80.9 0.5 5445 + 5447 3 179.85 109.9 -82.9 0.5 5446 + 5448 3 176.15 111.2 -81 0.5 5447 + 5449 3 174.45 111.2 -81.5 0.5 5448 + 5450 3 171.25 111.2 -84.8 0.5 5449 + 5451 3 176.75 115.1 -83.3 0.25 5449 + 5452 3 175.65 106.4 -84.3 0.25 5447 + 5453 3 181.95 113.5 -79.6 0.25 5446 + 5454 3 178.75 97.4 -85.4 0.5 4980 + 5455 3 176.35 100.6 -85.4 0.5 5454 + 5456 3 174.85 103.4 -88.4 0.5 5455 + 5457 3 172.05 103.4 -84.1 0.5 5456 + 5458 3 167.75 105 -84.3 0.5 5457 + 5459 3 165.75 106.4 -84.3 0.5 5458 + 5460 3 172.05 100.9 -85.8 0.5 5457 + 5461 3 174.85 108.8 -88.4 0.5 5456 + 5462 3 180.45 100.8 -85.4 0.5 5455 + 5463 3 181.55 99.2 -85.4 0.5 5462 + 5464 3 175.65 94.3 -87.8 0.25 4979 + 5465 3 176.35 97.2 -87.8 0.25 5464 + 5466 3 173.15 92 -87.8 0.25 5464 + 5467 3 175.85 84.2 -91.7 0.25 4977 + 5468 3 173.95 86.6 -91.6 0.25 5467 + 5469 3 171.75 88.9 -91.6 0.25 5468 + 5470 3 170.35 89.2 -91.6 0.25 5469 + 5471 3 171.25 89.8 -91.6 0.25 5470 + 5472 3 168.75 85.9 -91.6 0.25 5470 + 5473 3 172.55 84.2 -91.7 0.25 5467 + 5474 3 171.05 84.9 -91.7 0.25 5473 + 5475 3 174.05 80.6 -93.9 0.25 5473 + 5476 3 181.55 72 -94.2 0.25 4976 + 5477 3 173.35 75 -97.8 1.25 4972 + 5478 3 169.55 79.1 -100.4 1.5 5477 + 5479 3 166.35 82.2 -97.8 1.5 5478 + 5480 3 164.75 83.2 -97.6 1.5 5479 + 5481 3 163.95 87.9 -99.2 1.25 5480 + 5482 3 160.45 92.5 -97.6 1.5 5481 + 5483 3 157.35 100.4 -92.9 1.25 5482 + 5484 3 156.85 107.8 -93.6 1.5 5483 + 5485 3 157.95 111.2 -89.6 1.25 5484 + 5486 3 151.65 117.6 -87.4 1.25 5485 + 5487 3 148.05 119.7 -87.4 2 5486 + 5488 3 148.05 122.2 -86.7 1.75 5487 + 5489 3 145.85 122.7 -84.6 1.5 5488 + 5490 3 140.75 126.6 -86.4 1.75 5489 + 5491 3 140.95 129.4 -84.4 1.5 5490 + 5492 3 140.25 131.5 -85.8 1.5 5491 + 5493 3 140.25 135.6 -85.4 1.25 5492 + 5494 3 140.75 139.9 -86 2 5493 + 5495 3 140.65 141.4 -83.3 1.75 5494 + 5496 3 140.65 145.4 -82.7 1.5 5495 + 5497 3 141.75 149.3 -81.8 2.25 5496 + 5498 3 141.85 153.8 -76.4 2.5 5497 + 5499 3 144.15 154.6 -76.7 2.5 5498 + 5500 3 143.35 158.6 -75 2.75 5499 + 5501 3 149.65 158.6 -76.8 1 5500 + 5502 3 151.95 158.6 -73 1.75 5501 + 5503 3 150.55 160.7 -76.2 2 5502 + 5504 3 153.65 162.9 -75.5 1 5503 + 5505 3 153.35 164.7 -71.6 1.75 5504 + 5506 3 153.35 165.2 -74 2 5505 + 5507 3 156.25 168.9 -73.1 1.75 5506 + 5508 3 155.35 170.8 -74 1.25 5507 + 5509 3 155.35 172.6 -74.3 1.25 5508 + 5510 3 157.55 174.3 -70.6 1.5 5509 + 5511 3 155.85 177.9 -69.3 1.25 5510 + 5512 3 157.95 182.2 -70.1 1.25 5511 + 5513 3 160.05 183.4 -70.5 1.25 5512 + 5514 3 163.75 182.7 -73.4 1.5 5513 + 5515 3 165.15 182.7 -69.7 0.75 5514 + 5516 3 166.95 182.7 -71.1 0.75 5515 + 5517 3 168.35 185.2 -72.6 1.25 5516 + 5518 3 168.95 186.7 -72.6 1.25 5517 + 5519 3 170.25 185.9 -72.9 0.75 5518 + 5520 3 171.55 188.2 -72.1 0.75 5519 + 5521 3 172.55 189.7 -71.3 0.75 5520 + 5522 3 174.35 192 -71.2 0.5 5521 + 5523 3 174.25 191.8 -72.2 0.75 5522 + 5524 3 176.35 195.1 -78.5 0.75 5523 + 5525 3 176.65 195.1 -75.9 0.5 5524 + 5526 3 180.45 195.1 -77.9 0.5 5525 + 5527 3 183.85 193.7 -78.3 0.5 5526 + 5528 3 175.25 200.8 -81.3 0.5 5525 + 5529 3 173.05 196.3 -78 0.5 5524 + 5530 3 170.35 197.6 -78 0.5 5529 + 5531 3 170.85 192.4 -78 0.25 5529 + 5532 3 178.55 191.8 -77.8 0.5 5523 + 5533 3 181.05 190.8 -77.7 0.25 5532 + 5534 3 180.05 189.2 -77.8 0.5 5532 + 5535 3 175.15 189.1 -75.9 0.5 5522 + 5536 3 180.25 187 -75.1 0.5 5535 + 5537 3 175.15 184.1 -78.4 0.5 5535 + 5538 3 169.05 191.6 -73.5 0.5 5521 + 5539 3 166.95 192.4 -73.5 0.5 5538 + 5540 3 172.05 184.2 -73.4 0.5 5518 + 5541 3 171.65 183.3 -73.1 0.25 5540 + 5542 3 175.95 179.1 -74.4 0.25 5541 + 5543 3 178.75 177.2 -72.2 0.25 5542 + 5544 3 173.15 177.6 -74.4 0.25 5542 + 5545 3 171.65 179.1 -73.1 0.25 5541 + 5546 3 169.15 181.2 -71 0.5 5516 + 5547 3 169.15 179.2 -74.3 0.5 5546 + 5548 3 162.75 187 -72.2 1 5514 + 5549 3 163.95 189.8 -75.8 0.5 5548 + 5550 3 163.95 193.1 -75 1.25 5549 + 5551 3 162.55 194.8 -75.8 1.25 5550 + 5552 3 165.35 197.7 -78.5 0.5 5551 + 5553 3 157.75 194.8 -80.9 0.5 5551 + 5554 3 157.65 183.7 -74.6 0.75 5513 + 5555 3 158.05 187.3 -71.9 0.5 5554 + 5556 3 158.05 190.1 -73.7 0.5 5555 + 5557 3 154.35 180 -78.6 0.5 5554 + 5558 3 162.25 177.2 -74.6 0.5 5512 + 5559 3 162.25 175 -74.6 0.5 5558 + 5560 3 167.35 172.5 -76.3 0.5 5559 + 5561 3 171.75 169.6 -76.5 0.25 5560 + 5562 3 169.15 170.2 -76.3 0.25 5560 + 5563 3 165.95 178.4 -71.6 0.5 5559 + 5564 3 167.45 175.1 -71.6 0.25 5563 + 5565 3 166.75 179.7 -71.6 0.25 5563 + 5566 3 164.45 180.1 -74.6 0.5 5558 + 5567 3 160.75 172.5 -70.8 0.25 5510 + 5568 3 152.15 174.5 -72.4 0.75 5509 + 5569 3 152.15 173 -76.2 0.75 5568 + 5570 3 149.35 170.3 -77.2 0.5 5569 + 5571 3 147.55 171 -77.2 0.5 5570 + 5572 3 154.45 171.3 -74.8 0.5 5569 + 5573 3 151.15 177.8 -73.7 0.5 5568 + 5574 3 162.85 168.7 -69.4 0.5 5508 + 5575 3 166.15 170.3 -71.9 0.5 5574 + 5576 3 168.45 170.5 -71.7 0.5 5575 + 5577 3 172.75 168 -74.2 0.5 5576 + 5578 3 171.45 173.9 -74.1 0.5 5576 + 5579 3 165.55 166.8 -71.8 0.25 5574 + 5580 3 152.35 169.5 -75.7 0.5 5507 + 5581 3 150.65 169.5 -75.7 0.5 5580 + 5582 3 148.85 168.3 -77 0.25 5581 + 5583 3 150.65 165.4 -75.7 0.25 5581 + 5584 3 159.05 164 -76.2 0.75 5506 + 5585 3 163.45 166.3 -77.5 0.5 5584 + 5586 3 162.25 160 -75.9 0.25 5584 + 5587 3 160.95 162.3 -78.1 0.5 5505 + 5588 3 158.75 158.7 -81.4 0.5 5504 + 5589 3 159.75 158 -81.4 0.5 5588 + 5590 3 162.55 155.8 -80.6 0.5 5589 + 5591 3 163.65 160.9 -80.2 0.5 5589 + 5592 3 156.95 157.6 -74.1 0.5 5503 + 5593 3 161.15 156.3 -77 0.5 5592 + 5594 3 162.95 154.3 -76.5 0.5 5593 + 5595 3 154.65 154.7 -79.7 0.5 5502 + 5596 3 155.65 152.8 -83 0.5 5595 + 5597 3 157.35 148.4 -83.5 0.5 5596 + 5598 3 152.65 151.2 -83.6 0.5 5596 + 5599 3 143.35 161.6 -76.1 1.25 5500 + 5600 3 142.05 164.3 -76.2 1 5599 + 5601 3 141.05 167.9 -75.1 1.25 5600 + 5602 3 143.25 168.2 -73.1 1 5601 + 5603 3 141.15 170.3 -74.8 1.25 5602 + 5604 3 137.25 175.2 -74.2 1.25 5603 + 5605 3 136.15 176 -73.2 1.25 5604 + 5606 3 136.75 177.7 -75 0.75 5605 + 5607 3 139.05 180.5 -75.6 0.75 5606 + 5608 3 140.15 181.7 -72.8 1 5607 + 5609 3 140.95 184.6 -72.7 0.75 5608 + 5610 3 140.05 187.6 -75.9 0.75 5609 + 5611 3 142.35 191 -76.3 0.5 5610 + 5612 3 143.95 189.6 -76.3 0.75 5611 + 5613 3 148.15 192.8 -76.2 0.5 5612 + 5614 3 148.15 196.2 -76.8 0.75 5613 + 5615 3 150.05 189.5 -76.2 0.25 5613 + 5616 3 147.05 186.5 -76.7 0.25 5612 + 5617 3 148.85 185 -78.2 0.25 5616 + 5618 3 149.45 183.7 -76.7 0.25 5617 + 5619 3 150.25 188.2 -78.2 0.25 5617 + 5620 3 140.65 181 -71 0.5 5608 + 5621 3 145.75 179.8 -71.3 0.5 5620 + 5622 3 146.25 177.5 -74.7 0.5 5621 + 5623 3 149.65 179.5 -74.7 0.5 5622 + 5624 3 144.95 175.5 -76 0.25 5621 + 5625 3 144.75 183.9 -71 0.5 5620 + 5626 3 134.15 179.2 -73.8 0.5 5605 + 5627 3 133.65 181.5 -74.5 0.5 5626 + 5628 3 134.55 185.5 -77.7 0.5 5627 + 5629 3 136.85 181.5 -76.9 0.25 5627 + 5630 3 131.85 178.7 -77 0.25 5626 + 5631 3 129.15 177.2 -77 0.25 5630 + 5632 3 130.45 180.9 -77 0.25 5630 + 5633 3 134.55 172.1 -75.4 0.5 5604 + 5634 3 135.75 171.1 -78.3 0.5 5633 + 5635 3 134.75 168.4 -78.3 0.5 5634 + 5636 3 138.35 170 -78.3 0.25 5635 + 5637 3 137.15 166.9 -80.6 0.25 5636 + 5638 3 135.75 167 -79.7 0.25 5637 + 5639 3 141.25 162.7 -82.2 0.25 5638 + 5640 3 134.35 163.8 -79.3 0.25 5638 + 5641 3 138.75 169.3 -80.6 0.25 5637 + 5642 3 141.65 166.6 -80.9 0.25 5641 + 5643 3 139.45 169.8 -77.1 0.25 5636 + 5644 3 134.15 167.1 -78.3 0.25 5635 + 5645 3 133.55 168.9 -79.8 0.25 5634 + 5646 3 133.35 173.1 -74.4 0.5 5633 + 5647 3 129.55 173.3 -76.4 0.5 5646 + 5648 3 130.75 171.4 -74.4 0.25 5646 + 5649 3 142.55 171 -74.8 0.5 5602 + 5650 3 145.35 169 -72.2 0.5 5649 + 5651 3 142.55 172.9 -76.1 0.5 5649 + 5652 3 139.95 164.3 -75.3 0.5 5600 + 5653 3 136.85 164.3 -75.3 0.5 5652 + 5654 3 146.55 153.9 -83.8 0.5 5499 + 5655 3 146.65 146.7 -82.8 0.5 5498 + 5656 3 149.75 147.1 -81.4 0.5 5655 + 5657 3 148.95 145.9 -81.4 0.5 5656 + 5658 3 152.75 141.3 -84.3 0.5 5657 + 5659 3 152.95 139.7 -86.6 0.5 5658 + 5660 3 145.45 143.1 -84.7 0.25 5657 + 5661 3 152.35 149.7 -84.7 0.5 5656 + 5662 3 143.95 145.2 -80.9 0.5 5655 + 5663 3 136.55 151.9 -77.9 0.5 5497 + 5664 3 134.65 155.8 -79 0.75 5663 + 5665 3 130.55 159.9 -74 0.5 5664 + 5666 3 130.45 162.1 -74.4 0.75 5665 + 5667 3 130.45 163 -74.5 0.75 5666 + 5668 3 128.65 165.2 -73.2 0.75 5667 + 5669 3 128.25 166.4 -76 0.75 5668 + 5670 3 125.05 167.7 -74.1 0.75 5669 + 5671 3 123.55 170.7 -77 0.5 5670 + 5672 3 122.05 171.6 -77 0.5 5671 + 5673 3 121.45 174.9 -74.3 0.25 5672 + 5674 3 121.75 174 -74.3 0.25 5673 + 5675 3 121.75 179 -74.3 0.25 5674 + 5676 3 119.15 175.5 -74.3 0.25 5674 + 5677 3 116.05 170.9 -75.2 0.25 5672 + 5678 3 123.35 164.5 -78.4 0.25 5670 + 5679 3 126.75 164.5 -78.4 0.25 5678 + 5680 3 121.95 163.1 -78.4 0.25 5678 + 5681 3 133.55 164.4 -76.9 0.25 5667 + 5682 3 135.05 162.7 -76.9 0.25 5681 + 5683 3 134.25 166.2 -76.9 0.25 5681 + 5684 3 125.65 158.7 -78.3 0.5 5666 + 5685 3 125.55 157.3 -78.3 0.5 5684 + 5686 3 123.45 159.8 -77.6 0.5 5685 + 5687 3 138.45 158 -79 0.5 5664 + 5688 3 135.05 149.3 -80.7 0.5 5496 + 5689 3 133.75 149.5 -80.7 0.5 5688 + 5690 3 131.95 151.3 -80.5 0.5 5689 + 5691 3 123.95 157.8 -82.1 0.25 5690 + 5692 3 123.55 151.3 -78.1 0.25 5690 + 5693 3 121.35 149.5 -79.6 0.25 5692 + 5694 3 131.95 144.9 -84.5 0.5 5689 + 5695 3 130.55 145.3 -84.5 0.5 5694 + 5696 3 128.35 145.3 -82.5 0.5 5695 + 5697 3 125.25 139.8 -83.8 0.5 5696 + 5698 3 126.05 146 -82.5 0.5 5696 + 5699 3 132.95 142.8 -85.8 0.25 5695 + 5700 3 145.15 136.8 -85.8 0.5 5494 + 5701 3 149.05 136.8 -86 0.5 5700 + 5702 3 145.45 139.8 -84.6 0.5 5700 + 5703 3 142.95 142 -88.1 0.25 5702 + 5704 3 134.85 134.6 -85.6 0.75 5492 + 5705 3 132.05 138.3 -84 0.75 5704 + 5706 3 130.55 138.3 -84 0.75 5705 + 5707 3 127.15 138.8 -86.4 0.75 5706 + 5708 3 123.65 137.6 -85.2 0.75 5707 + 5709 3 119.75 138.4 -84 0.5 5708 + 5710 3 117.55 141.1 -82.4 1.25 5709 + 5711 3 114.45 146.6 -78.8 0.5 5710 + 5712 3 111.55 150 -82 0.5 5711 + 5713 3 114.45 151.5 -77.9 0.5 5711 + 5714 3 112.75 137.6 -83.9 0.75 5710 + 5715 3 110.65 132.7 -84.3 0.5 5714 + 5716 3 104.85 126.4 -87.7 0.5 5715 + 5717 3 107.05 135.8 -83 0.25 5715 + 5718 3 102.55 132.9 -85.8 0.25 5717 + 5719 3 104.75 138.8 -83 0.25 5717 + 5720 3 122.75 135.5 -84.1 0.25 5708 + 5721 3 123.65 132.8 -87.3 0.5 5720 + 5722 3 122.65 128.6 -90.2 0.5 5721 + 5723 3 119.65 134.7 -87.3 0.25 5721 + 5724 3 131.55 135 -86.7 0.25 5706 + 5725 3 130.45 132.1 -88.7 0.25 5724 + 5726 3 128.75 135 -89.9 0.25 5724 + 5727 3 142.55 131.8 -83.1 0.25 5491 + 5728 3 148.05 125.4 -88 0.25 5489 + 5729 3 145.75 125 -88 0.25 5728 + 5730 3 141.05 118.7 -90.7 0.5 5487 + 5731 3 136.15 119.7 -90.5 0.25 5730 + 5732 3 144.55 114.7 -91.9 0.25 5730 + 5733 3 161.55 110.2 -90.4 0.5 5484 + 5734 3 162.55 112.5 -89.9 0.75 5733 + 5735 3 165.05 112.5 -88.8 0.75 5734 + 5736 3 163.35 114.8 -90.3 0.5 5735 + 5737 3 165.85 116.8 -90 0.75 5736 + 5738 3 164.15 118 -90 0.75 5737 + 5739 3 163.95 117.3 -86 0.5 5738 + 5740 3 163.65 122 -86.9 0.5 5739 + 5741 3 161.55 125.3 -86.6 0.5 5740 + 5742 3 161.75 124.5 -87.8 0.5 5741 + 5743 3 161.75 129.3 -85.5 0.5 5742 + 5744 3 159.25 133.5 -81.3 0.5 5743 + 5745 3 158.25 137.6 -78.5 0.5 5744 + 5746 3 160.35 140.3 -77 0.5 5745 + 5747 3 160.35 141.8 -77 0.5 5746 + 5748 3 160.35 141.1 -76.2 0.5 5747 + 5749 3 161.35 145.5 -78.2 0.5 5748 + 5750 3 161.55 147.3 -75 0.5 5749 + 5751 3 164.05 149.3 -76 0.5 5750 + 5752 3 164.65 152.8 -77.3 0.5 5751 + 5753 3 160.25 149.7 -76 0.25 5751 + 5754 3 166.35 144 -75.3 0.25 5750 + 5755 3 158.55 146.9 -81 0.5 5749 + 5756 3 159.55 148.7 -81 0.25 5755 + 5757 3 157.55 144.4 -80.2 0.25 5755 + 5758 3 163.65 141 -76.2 0.5 5748 + 5759 3 165.05 137.2 -78.3 0.5 5758 + 5760 3 169.25 135.7 -80.7 0.5 5759 + 5761 3 165.05 140.8 -77.9 0.25 5759 + 5762 3 161.25 137.5 -76.2 0.25 5758 + 5763 3 155.95 142 -81.2 0.25 5747 + 5764 3 155.85 137.4 -77.3 0.25 5745 + 5765 3 153.05 137.4 -85.9 0.25 5764 + 5766 3 153.05 134.6 -85.9 0.25 5765 + 5767 3 150.95 137.4 -85.9 0.25 5765 + 5768 3 162.45 130.3 -84.6 0.25 5744 + 5769 3 156.65 128.6 -85.5 0.25 5743 + 5770 3 155.35 129.5 -84.2 0.25 5769 + 5771 3 156.65 132.6 -86.1 0.25 5769 + 5772 3 156.65 128 -89.4 0.25 5742 + 5773 3 169.05 120.1 -87.1 0.5 5739 + 5774 3 169.75 123.5 -81.1 0.5 5773 + 5775 3 170.85 123.2 -83.5 0.25 5774 + 5776 3 170.85 128.7 -83.5 0.5 5775 + 5777 3 172.05 131.8 -81.8 0.5 5776 + 5778 3 169.05 129.8 -81.3 0.5 5776 + 5779 3 172.65 122.1 -83.5 0.25 5775 + 5780 3 160.35 119.7 -87 0.25 5738 + 5781 3 167.65 113.9 -90 0.25 5737 + 5782 3 164.75 109.1 -93.1 0.25 5735 + 5783 3 158.35 114.5 -90.6 0.25 5734 + 5784 3 159.45 116.8 -94.8 0.25 5783 + 5785 3 161.75 116.8 -94.8 0.25 5784 + 5786 3 157.25 118.2 -94.8 0.25 5784 + 5787 3 155.95 114.7 -93.4 0.25 5783 + 5788 3 150.75 99.7 -96.2 0.5 5483 + 5789 3 147.95 103.4 -96.2 0.75 5788 + 5790 3 140.15 104.7 -94.2 1 5789 + 5791 3 136.35 103.4 -97.2 0.75 5790 + 5792 3 132.15 103.7 -97 0.5 5791 + 5793 3 127.35 105.6 -93.6 0.5 5792 + 5794 3 116.65 107.6 -94.7 0.5 5793 + 5795 3 108.35 114.4 -91 0.25 5794 + 5796 3 107.85 119.8 -92.4 0.25 5795 + 5797 3 104.25 112.7 -91.8 0.25 5795 + 5798 3 106.05 107.1 -92.7 0.5 5794 + 5799 3 132.15 98.5 -96.5 0.25 5792 + 5800 3 132.85 94.2 -96.5 0.25 5799 + 5801 3 137.95 108.4 -95.8 0.5 5790 + 5802 3 132.85 112.9 -91.7 0.5 5801 + 5803 3 128.25 115.6 -88.7 0.5 5802 + 5804 3 125.65 119.7 -89.1 0.5 5803 + 5805 3 125.75 115.6 -91.3 0.25 5803 + 5806 3 130.55 110.4 -91.7 0.25 5802 + 5807 3 165.95 93.3 -97.6 0.5 5482 + 5808 3 159.65 84 -99.7 0.5 5480 + 5809 3 153.35 74 -103.9 0.5 5808 + 5810 3 149.15 77.9 -104.7 0.5 5809 + 5811 3 145.45 77.3 -105.2 0.25 5810 + 5812 3 145.65 82.2 -101.9 0.25 5810 + 5813 3 155.85 72.7 -103 0.25 5809 + 5814 3 164.95 75.1 -102.9 0.5 5478 + 5815 3 161.35 70 -104.2 0.5 5814 + 5816 3 158.05 64.5 -106.2 0.5 5815 + 5817 3 152.35 60.2 -106.6 0.5 5816 + 5818 3 159.95 70 -104.2 0.25 5815 + 5819 3 187.15 68.6 -100.3 0.5 4971 + 5820 3 174.65 63.8 -100.8 0.5 4970 + 5821 3 170.55 59.8 -103.8 0.5 5820 + 5822 3 168.85 58.1 -103.4 0.5 5821 + 5823 3 170.15 52.5 -105.9 0.5 5822 + 5824 3 168.85 49.1 -105.9 0.25 5823 + 5825 3 166.65 59.2 -105.2 0.5 5822 + 5826 3 195.75 52.7 -97.1 0.25 4968 + 5827 3 199.95 50.4 -97.1 0.25 5826 + 5828 3 204.25 52.6 -97.1 0.25 5827 + 5829 3 202.25 49.5 -96.9 0.25 5827 + 5830 3 195.85 34.5 -101.9 0.5 4966 + 5831 3 192.25 31.4 -99.9 0.5 5830 + 5832 3 188.25 32.5 -100.6 0.5 5831 + 5833 3 185.45 30.6 -103.4 0.5 5832 + 5834 3 182.25 33.8 -103.4 0.5 5833 + 5835 3 178.45 36 -105.4 0.5 5834 + 5836 3 176.15 33.3 -106.1 0.5 5835 + 5837 3 174.55 33.9 -110.3 0.5 5836 + 5838 3 171.65 32 -109.7 0.25 5837 + 5839 3 177.75 29.5 -108.5 0.25 5836 + 5840 3 178.45 38.1 -106.1 0.25 5835 + 5841 3 183.75 28.6 -107.7 0.25 5833 + 5842 3 199.35 20.1 -98.4 0.5 4963 + 5843 3 197.35 19.3 -103.2 0.5 5842 + 5844 3 197.35 15.2 -103.5 0.5 5843 + 5845 3 193.05 17.2 -104.4 0.25 5844 + 5846 3 193.05 20 -104.4 0.25 5845 + 5847 3 190.45 12.6 -104.4 0.25 5845 + 5848 3 200.25 9.2 -101.4 0.25 5844 + 5849 3 195.15 19.3 -103.2 0.25 5843 + 5850 3 212.95 10.1 -95.5 0.25 4961 + 5851 3 215.25 6.7 -95.5 0.25 5850 + 5852 3 199.15 -6.7 -101.5 0.5 4957 + 5853 3 199.15 -1.9 -104.6 0.5 5852 + 5854 3 194.55 2.2 -106.6 0.5 5853 + 5855 3 190.85 7 -107.4 0.5 5854 + 5856 3 186.85 9.5 -104 0.5 5855 + 5857 3 183.45 15.3 -107.1 0.5 5856 + 5858 3 178.65 15.3 -109.9 0.5 5857 + 5859 3 174.65 18 -111.9 0.5 5858 + 5860 3 170.05 20.5 -111.9 0.5 5859 + 5861 3 175.35 11.1 -110.4 0.5 5858 + 5862 3 186.65 5 -108.1 0.25 5856 + 5863 3 189.25 3 -107.4 0.25 5855 + 5864 3 197.25 -8.5 -101.5 0.5 5852 + 5865 3 193.35 -12.5 -104.5 0.5 5864 + 5866 3 187.85 -9 -106.8 0.5 5865 + 5867 3 193.35 -16 -104.5 0.5 5865 + 5868 3 197.25 -14 -101.5 0.5 5864 + 5869 3 200.85 -15.5 -103.4 0.5 5868 + 5870 3 207.95 -22.2 -96.1 0.5 4956 + 5871 3 209.15 -27.8 -93.7 0.5 5870 + 5872 3 212.05 -34.2 -96.2 0.5 5871 + 5873 3 209.55 -36.9 -96.2 0.5 5872 + 5874 3 210.05 -40.9 -97.2 0.5 5873 + 5875 3 210.05 -44.2 -97.2 0.5 5874 + 5876 3 206.75 -36.9 -96.2 0.5 5873 + 5877 3 205.25 -38.9 -94.8 0.25 5876 + 5878 3 204.05 -26.8 -94.3 0.25 5870 + 5879 3 193.45 -31.2 -104.3 0.5 4953 + 5880 3 194.65 -51.1 -101.8 0.5 4951 + 5881 3 186.55 -42.4 -103.9 0.25 4950 + 5882 3 188.05 -39.2 -104.1 0.25 5881 + 5883 3 186.55 -33.9 -107.1 0.25 5882 + 5884 3 184.15 -29 -105.3 0.75 5883 + 5885 3 184.15 -28.1 -107.4 0.75 5884 + 5886 3 181.45 -23.5 -107.2 0.5 5885 + 5887 3 179.15 -20.6 -107.5 0.5 5886 + 5888 3 177.45 -13.8 -110.6 0.75 5887 + 5889 3 176.45 -10.8 -111.2 0.75 5888 + 5890 3 176.15 -6.1 -112.7 0.75 5889 + 5891 3 175.55 -5.2 -109.8 1 5890 + 5892 3 169.25 -0.5 -112.3 1 5891 + 5893 3 164.95 1.1 -113.4 0.75 5892 + 5894 3 165.05 8.4 -111.2 1 5893 + 5895 3 162.15 11.1 -111.4 1 5894 + 5896 3 159.45 14.1 -110.7 0.75 5895 + 5897 3 157.25 18.9 -110.6 0.5 5896 + 5898 3 155.05 24.1 -110.7 1 5897 + 5899 3 151.45 30.1 -110.5 0.5 5898 + 5900 3 151.45 33.7 -111.4 0.75 5899 + 5901 3 147.85 36.3 -110.8 0.75 5900 + 5902 3 147.85 43.5 -113.1 0.75 5901 + 5903 3 140.75 50.5 -112.4 1 5902 + 5904 3 137.45 55.8 -108.3 0.5 5903 + 5905 3 136.95 61.5 -107.2 0.75 5904 + 5906 3 131.25 72.4 -103.5 0.5 5905 + 5907 3 131.25 73.7 -104.6 0.5 5906 + 5908 3 127.75 81.3 -102.9 0.25 5907 + 5909 3 122.15 88 -101.1 0.25 5908 + 5910 3 116.15 92.2 -97.5 0.25 5909 + 5911 3 112.85 91 -97.5 0.25 5910 + 5912 3 115.65 84.9 -99.3 0.25 5909 + 5913 3 123.65 73.7 -106 0.25 5907 + 5914 3 124.45 62.2 -108.9 0.5 5905 + 5915 3 139.05 48.2 -112.4 0.5 5903 + 5916 3 134.15 48.2 -113 0.5 5915 + 5917 3 137.15 42.7 -110.5 0.5 5915 + 5918 3 144.25 36.3 -114.3 0.25 5901 + 5919 3 140.15 30.7 -114.3 0.25 5918 + 5920 3 159.65 29.1 -109.4 0.5 5898 + 5921 3 160.85 34 -109.4 0.5 5920 + 5922 3 160.85 38.9 -108.6 0.5 5921 + 5923 3 156.25 45 -108.4 0.25 5922 + 5924 3 163.95 31.3 -111.3 0.25 5921 + 5925 3 159.65 9.6 -113.1 0.25 5895 + 5926 3 159.65 7.8 -111.7 0.25 5925 + 5927 3 154.35 3 -111.7 0.25 5926 + 5928 3 157.65 12.1 -113.1 0.25 5925 + 5929 3 177.25 -1.9 -107.7 0.25 5891 + 5930 3 177.55 -0.6 -107.7 0.25 5929 + 5931 3 181.15 -1.2 -107.7 0.25 5930 + 5932 3 177.55 4.6 -110.2 0.25 5930 + 5933 3 181.75 -9.5 -111.2 0.25 5889 + 5934 3 185.85 -11.6 -111.2 0.25 5933 + 5935 3 187.15 -27 -107.5 0.5 5885 + 5936 3 189.35 -27.5 -107.8 0.5 5935 + 5937 3 182.25 -30.7 -105.3 0.75 5884 + 5938 3 175.75 -29.8 -108.4 0.5 5937 + 5939 3 172.35 -31.7 -108.4 0.5 5938 + 5940 3 169.55 -31.7 -109.4 0.5 5939 + 5941 3 166.25 -28.5 -112 0.25 5940 + 5942 3 164.85 -29.3 -111.2 0.25 5941 + 5943 3 164.85 -23.1 -111.8 0.25 5942 + 5944 3 159.85 -26.3 -112.2 0.25 5942 + 5945 3 169.65 -25.5 -110.5 0.25 5941 + 5946 3 167.35 -33.3 -110.6 0.25 5940 + 5947 3 167.35 -37.1 -110.6 0.25 5946 + 5948 3 178.65 -34.7 -104.9 0.25 5937 + 5949 3 177.15 -38.9 -105.6 0.25 5948 + 5950 3 176.05 -41.9 -108.3 0.5 5949 + 5951 3 179.65 -43.2 -108.3 0.5 5950 + 5952 3 178.85 -47.1 -106.7 0.5 5951 + 5953 3 177.95 -50.4 -108.6 0.5 5952 + 5954 3 179.25 -58.7 -106.2 0.5 5953 + 5955 3 175.05 -58.9 -108.3 0.25 5954 + 5956 3 172.55 -62.4 -108.3 0.25 5955 + 5957 3 177.95 -61.7 -101.9 0.5 5954 + 5958 3 182.95 -51.5 -108.6 0.25 5953 + 5959 3 182.35 -41.7 -106 0.25 5951 + 5960 3 177.05 -44.7 -105.9 0.25 5950 + 5961 3 172.45 -45.9 -106.9 0.25 5960 + 5962 3 181.65 -36.5 -105.6 0.25 5949 + 5963 2 6.65 -183.6 -62.1 2.5 80 + 5964 2 2.55 -182.9 -63.7 0.75 5963 + 5965 2 -1.85 -182.9 -63.9 0.75 5964 + 5966 2 -6.15 -182.9 -62.6 0.5 5965 + 5967 2 5.25 -179.7 -65.3 0.75 5963 + 5968 2 7.65 -178.3 -66.1 0.5 5967 + 5969 2 -48.55 -190.9 -53 2.5 72 + 5970 2 -56.65 -189 -48.1 2.25 5969 + 5971 2 -60.95 -189 -50.1 2.25 5970 + 5972 2 -63.85 -189.5 -52.3 2 5971 + 5973 2 -68.25 -187.9 -53.5 2.5 5972 + 5974 2 -68.25 -187.9 -53.4 2.5 5973 + 5975 2 -69.95 -185.5 -54.3 3.25 5974 + 5976 2 -73.75 -187.5 -54.3 2.25 5975 + 5977 2 -78.35 -188.6 -55.6 2 5976 + 5978 2 -83.65 -188.6 -57.3 2.75 5977 + 5979 2 -88.15 -188.6 -59 2.75 5978 + 5980 2 -95.55 -187.5 -58 3 5979 + 5981 2 -100.15 -187.8 -61.4 2.75 5980 + 5982 2 -100.95 -187.8 -62.7 2.5 5981 + 5983 2 -110.45 -189.4 -62.7 3.25 5982 + 5984 2 -115.45 -189.4 -67.8 3.25 5983 + 5985 2 -120.35 -188.4 -68.7 3.25 5984 + 5986 2 -127.05 -187.5 -71.3 3.25 5985 + 5987 2 -127.05 -187.5 -71.4 2 5986 + 5988 2 -131.25 -186.8 -71.3 1.25 5987 + 5989 2 -130.25 -191.4 -82.2 1 5988 + 5990 2 -133.35 -190.1 -82.2 1 5989 + 5991 2 -136.25 -191.7 -84.1 1 5990 + 5992 2 -140.45 -191.7 -88.1 1.25 5991 + 5993 2 -144.75 -189.4 -86.6 1.75 5992 + 5994 2 -147.45 -189.4 -90.1 1.5 5993 + 5995 2 -152.25 -186.3 -90.5 1 5994 + 5996 2 -155.55 -183.4 -90.5 1 5995 + 5997 2 -158.65 -179.9 -93.2 0.25 5996 + 5998 2 -160.45 -177.5 -93.2 0.5 5997 + 5999 2 -163.05 -178.9 -91.4 0.5 5998 + 6000 2 -166.35 -175.6 -90.3 0.5 5999 + 6001 2 -171.15 -172.7 -89.7 0.25 6000 + 6002 2 -175.95 -172.1 -90.5 0.25 6001 + 6003 2 -178.05 -170.7 -90.2 0.25 6002 + 6004 2 -178.55 -168.9 -90.4 0.25 6003 + 6005 2 -180.35 -170.8 -90.2 0.25 6003 + 6006 2 -173.65 -176.6 -93.8 0.25 6001 + 6007 2 -176.25 -176.6 -93.8 0.25 6006 + 6008 2 -168.75 -175.6 -93.5 0.25 6000 + 6009 2 -171.35 -178.6 -93.5 0.25 6008 + 6010 2 -161.75 -178.1 -92.4 0.25 5999 + 6011 2 -166.95 -177.3 -92.4 0.25 6010 + 6012 2 -168.55 -177.3 -91.8 0.25 6011 + 6013 2 -169.85 -178 -91.8 0.25 6012 + 6014 2 -172.15 -180.6 -94.5 0.25 6013 + 6015 2 -170.55 -175.9 -91.8 0.25 6012 + 6016 2 -164.85 -180.5 -92.4 0.25 6010 + 6017 2 -160.35 -182 -95.6 0.25 5997 + 6018 2 -165.55 -180.3 -95.6 0.25 6017 + 6019 2 -154.05 -180.4 -91.3 0.5 5996 + 6020 2 -153.65 -179 -92.5 0.25 6019 + 6021 2 -156.45 -178.6 -94.9 0.25 6020 + 6022 2 -157.35 -179 -92.5 0.25 6020 + 6023 2 -155.55 -177.4 -92.5 0.25 6022 + 6024 2 -158.05 -181.1 -92.5 0.25 6022 + 6025 2 -158.75 -179.6 -92.9 0.5 6019 + 6026 2 -154.65 -190.5 -87.7 1 5994 + 6027 2 -157.95 -193.7 -88.3 1 6026 + 6028 2 -162.25 -194.6 -88.2 1 6027 + 6029 2 -165.75 -194.6 -85.5 1.25 6028 + 6030 2 -169.05 -193.2 -85.3 0.75 6029 + 6031 2 -175.15 -188 -85.2 0.75 6030 + 6032 2 -177.15 -189.4 -84.4 0.5 6031 + 6033 2 -180.05 -191.6 -87.8 0.5 6032 + 6034 2 -177.25 -188.1 -85.7 0.5 6032 + 6035 2 -182.05 -189.1 -88.2 0.5 6034 + 6036 2 -176.35 -184.6 -87.9 0.5 6031 + 6037 2 -171.45 -182.1 -87.9 0.5 6036 + 6038 2 -175.85 -183.2 -83.1 0.5 6036 + 6039 2 -172.75 -195.5 -87.5 0.5 6030 + 6040 2 -168.05 -198.1 -82 0.75 6029 + 6041 2 -171.15 -196.1 -81.4 0.5 6040 + 6042 2 -173.55 -195.1 -81.4 0.5 6041 + 6043 2 -173.35 -200.5 -78.4 0.5 6041 + 6044 2 -169.65 -200.8 -82.6 0.5 6040 + 6045 2 -137.25 -186.2 -85.3 0.25 5990 + 6046 2 -139.65 -184.5 -85.3 0.25 6045 + 6047 2 -137.75 -188.8 -72.5 1 5988 + 6048 2 -146.35 -188.8 -71.7 1 6047 + 6049 2 -149.05 -187 -71.7 1 6048 + 6050 2 -152.15 -186.8 -72.6 0.75 6049 + 6051 2 -156.15 -190.6 -71.6 0.75 6050 + 6052 2 -161.55 -190.7 -71.6 0.75 6051 + 6053 2 -163.85 -190.5 -76.5 0.75 6052 + 6054 2 -171.15 -194.5 -76.6 0.5 6053 + 6055 2 -174.95 -195.6 -75.8 0.5 6054 + 6056 2 -176.45 -197.7 -75.8 0.5 6055 + 6057 2 -178.35 -193.9 -75.8 0.25 6056 + 6058 2 -181.45 -192.4 -75.8 0.25 6057 + 6059 2 -179.95 -199.6 -75.8 0.25 6056 + 6060 2 -169.45 -188.1 -72.5 0.25 6053 + 6061 2 -174.75 -189.9 -72.5 0.25 6060 + 6062 2 -177.95 -185.4 -75.2 0.25 6061 + 6063 2 -182.15 -183.4 -76.4 0.25 6062 + 6064 2 -185.55 -181.4 -76.4 0.25 6063 + 6065 2 -176.15 -191.3 -75.2 0.25 6061 + 6066 2 -172.95 -191.6 -72.5 0.25 6060 + 6067 2 -151.75 -192.4 -74.3 0.5 6049 + 6068 2 -154.75 -194.1 -74.3 0.5 6067 + 6069 2 -130.45 -185.3 -68.4 1 5986 + 6070 2 -131.95 -183.2 -68 1 6069 + 6071 2 -135.75 -183.2 -68.6 1.25 6070 + 6072 2 -139.55 -180.8 -69.1 1.25 6071 + 6073 2 -143.55 -181.4 -65.5 1.5 6072 + 6074 2 -146.65 -177.6 -67.3 1.5 6073 + 6075 2 -151.05 -178.4 -68.6 0.5 6074 + 6076 2 -156.65 -175.2 -66.1 0.5 6075 + 6077 2 -163.55 -174 -64.6 0.5 6076 + 6078 2 -166.55 -177.3 -66.9 0.5 6077 + 6079 2 -171.55 -178.9 -66.9 0.5 6078 + 6080 2 -176.85 -178.8 -61.6 0.25 6079 + 6081 2 -180.75 -175.6 -61.6 0.25 6080 + 6082 2 -181.95 -173.5 -61.6 0.25 6081 + 6083 2 -184.65 -170.8 -61.6 0.25 6082 + 6084 2 -182.65 -168.7 -61.6 0.25 6083 + 6085 2 -180.65 -179.7 -64.6 0.25 6080 + 6086 2 -183.55 -179.7 -64.6 0.25 6085 + 6087 2 -174.25 -181.7 -67.7 0.25 6079 + 6088 2 -176.85 -183.6 -63.7 0.25 6087 + 6089 2 -178.65 -185.8 -63.7 0.25 6088 + 6090 2 -164.75 -170.4 -63.9 0.25 6077 + 6091 2 -169.15 -168.1 -67.4 0.25 6090 + 6092 2 -173.55 -166.3 -67.4 0.25 6091 + 6093 2 -150.35 -174.2 -64.6 0.5 6074 + 6094 2 -155.05 -170.1 -67.1 0.5 6093 + 6095 2 -158.15 -166.6 -64.2 0.5 6094 + 6096 2 -163.85 -162.9 -62.7 0.5 6095 + 6097 2 -170.25 -159.9 -65.8 0.5 6096 + 6098 2 -171.75 -158.5 -62.2 0.5 6097 + 6099 2 -176.35 -158.2 -63.8 0.5 6098 + 6100 2 -179.85 -156.2 -66.4 0.5 6099 + 6101 2 -185.25 -155 -66.4 0.25 6100 + 6102 2 -187.75 -157.6 -66.4 0.25 6101 + 6103 2 -184.45 -159.4 -66.4 0.25 6100 + 6104 2 -181.75 -158.2 -63.4 0.25 6099 + 6105 2 -185.65 -161 -63.4 0.25 6104 + 6106 2 -172.45 -165.1 -65.8 0.25 6097 + 6107 2 -139.35 -185.1 -63.7 0.25 6072 + 6108 2 -143.75 -185.1 -63.7 0.25 6107 + 6109 2 -140.25 -185.1 -63.8 0.25 6071 + 6110 2 -134.15 -181.3 -72 0.5 6070 + 6111 2 -134.15 -179.5 -74 0.5 6110 + 6112 2 -137.55 -178 -71.3 0.25 6111 + 6113 2 -137.55 -176.3 -71.3 0.25 6112 + 6114 2 -130.85 -179.5 -71 0.5 6111 + 6115 2 -75.15 -182.6 -57.3 2 5975 + 6116 2 -81.25 -180.7 -57.9 2 6115 + 6117 2 -84.65 -179.5 -62.1 2 6116 + 6118 2 -88.75 -178.3 -60.1 1.75 6117 + 6119 2 -88.75 -178.3 -60.2 2 6118 + 6120 2 -90.45 -176.7 -59.4 1.75 6119 + 6121 2 -92.95 -175.2 -57.7 1.25 6120 + 6122 2 -96.45 -174 -60.9 1.25 6121 + 6123 2 -98.45 -173.4 -63.3 1.75 6122 + 6124 2 -102.65 -171.4 -67.6 2.5 6123 + 6125 2 -107.85 -169.1 -65.9 2.5 6124 + 6126 2 -112.95 -170.5 -70.2 2 6125 + 6127 2 -116.05 -169.7 -73.8 2 6126 + 6128 2 -118.95 -166.6 -75.5 2.25 6127 + 6129 2 -118.65 -167.6 -77 2 6128 + 6130 2 -122.75 -163.3 -81.2 1.25 6129 + 6131 2 -127.25 -160.9 -79.5 1.25 6130 + 6132 2 -133.25 -158.7 -84.8 1.25 6131 + 6133 2 -137.05 -157.5 -85.7 1.25 6132 + 6134 2 -137.85 -158.6 -86.2 1.25 6133 + 6135 2 -141.65 -156.4 -85.9 1.25 6134 + 6136 2 -146.15 -151.7 -80.6 1.25 6135 + 6137 2 -146.15 -148.2 -79.4 1.25 6136 + 6138 2 -152.15 -143.7 -81.4 1.25 6137 + 6139 2 -157.65 -140.1 -83.2 1 6138 + 6140 2 -164.85 -138.6 -83 1 6139 + 6141 2 -167.95 -141.4 -79.6 0.75 6140 + 6142 2 -173.45 -139.6 -83 0.75 6141 + 6143 2 -176.85 -141 -82.7 0.75 6142 + 6144 2 -180.85 -140.3 -79.2 0.5 6143 + 6145 2 -183.45 -139.4 -79.2 0.5 6144 + 6146 2 -186.95 -144.1 -79.2 0.5 6145 + 6147 2 -178.35 -146.6 -81.2 0.5 6143 + 6148 2 -181.25 -149.6 -81.2 0.5 6147 + 6149 2 -169.45 -135.4 -81 0.5 6140 + 6150 2 -177.95 -133.4 -83.8 0.5 6149 + 6151 2 -146.05 -155.3 -86.6 0.5 6135 + 6152 2 -147.55 -154.4 -85.5 0.5 6151 + 6153 2 -150.55 -153.2 -88.4 0.5 6152 + 6154 2 -152.85 -150.3 -88.4 0.5 6153 + 6155 2 -154.85 -147 -88 0.5 6154 + 6156 2 -154.75 -143.8 -91.2 0.5 6155 + 6157 2 -160.15 -140.6 -93.1 0.5 6156 + 6158 2 -158.25 -145.7 -90.8 0.25 6155 + 6159 2 -161.85 -149.3 -91.3 0.25 6158 + 6160 2 -144.75 -158.6 -85.4 0.5 6134 + 6161 2 -146.55 -160 -88.7 0.5 6160 + 6162 2 -150.55 -158.8 -88 0.5 6161 + 6163 2 -152.75 -161.2 -90.4 0.5 6162 + 6164 2 -147.55 -161.5 -88.7 0.25 6161 + 6165 2 -121.65 -168.1 -76.6 1 6129 + 6166 2 -125.25 -165.2 -77.8 0.75 6165 + 6167 2 -127.85 -163.8 -75.4 0.75 6166 + 6168 2 -128.85 -160.6 -74.6 0.75 6167 + 6169 2 -126.05 -159.5 -78.6 0.75 6168 + 6170 2 -130.55 -157.3 -73.3 0.5 6169 + 6171 2 -126.65 -155.1 -72.3 0.5 6170 + 6172 2 -129.95 -151.6 -72.4 0.5 6171 + 6173 2 -133.05 -149.2 -68.6 0.5 6172 + 6174 2 -135.45 -148.8 -68.6 0.5 6173 + 6175 2 -137.25 -147.9 -69.2 0.5 6174 + 6176 2 -143.35 -147.1 -71.4 0.5 6175 + 6177 2 -148.25 -149.4 -70.2 0.5 6176 + 6178 2 -154.15 -149.4 -72.4 0.5 6177 + 6179 2 -139.65 -152.1 -69.2 0.25 6175 + 6180 2 -134.35 -152.8 -68.6 0.25 6174 + 6181 2 -124.05 -169.1 -73.5 1 6128 + 6182 2 -127.25 -166.9 -76.2 1.25 6181 + 6183 2 -129.45 -168.6 -74.2 2 6182 + 6184 2 -135.25 -168.8 -74.2 1.25 6183 + 6185 2 -139.15 -166.2 -78 1.25 6184 + 6186 2 -140.75 -164.9 -77.1 1 6185 + 6187 2 -146.35 -163.4 -75.9 1.25 6186 + 6188 2 -150.65 -163.4 -70.2 1.25 6187 + 6189 2 -148.65 -167.3 -67.2 1.25 6188 + 6190 2 -155.65 -163.2 -65.6 0.5 6189 + 6191 2 -159.55 -162.2 -64.7 0.5 6190 + 6192 2 -162.05 -161.3 -64.8 0.25 6191 + 6193 2 -160.65 -164.4 -64.7 0.25 6191 + 6194 2 -154.15 -170.7 -67.2 0.5 6189 + 6195 2 -135.25 -171.3 -75.1 1 6183 + 6196 2 -136.65 -172.8 -74.1 0.75 6195 + 6197 2 -138.35 -173.5 -74.5 0.75 6196 + 6198 2 -141.35 -172.6 -78.5 0.75 6197 + 6199 2 -142.35 -175.1 -77.1 1 6198 + 6200 2 -147.55 -172 -80.8 0.75 6199 + 6201 2 -150.15 -172 -81 0.75 6200 + 6202 2 -154.25 -173.7 -81 0.75 6201 + 6203 2 -156.45 -178 -78.2 0.75 6202 + 6204 2 -156.45 -180.4 -82.5 0.75 6203 + 6205 2 -160.45 -180.4 -82.5 0.5 6204 + 6206 2 -147.15 -178 -80.2 0.75 6199 + 6207 2 -149.65 -182.3 -76.2 0.75 6206 + 6208 2 -93.65 -181.1 -66.6 0.5 6118 + 6209 2 -97.35 -181.1 -66.9 0.5 6208 + 6210 2 -101.05 -181.1 -69.5 0.75 6209 + 6211 2 -106.45 -178.2 -70.1 0.75 6210 + 6212 2 -112.15 -177.2 -70 0.75 6211 + 6213 2 -118.55 -179 -68.2 0.75 6212 + 6214 2 -123.65 -175.3 -67.7 0.75 6213 + 6215 2 -125.65 -177.1 -67.7 0.75 6214 + 6216 2 -129.85 -174.1 -69.4 0.75 6215 + 6217 2 -129.85 -174.1 -71.3 0.75 6216 + 6218 2 -134.85 -169.9 -67.8 0.5 6217 + 6219 2 -135.85 -166.8 -67.7 0.5 6218 + 6220 2 -137.05 -164.6 -67 0.5 6219 + 6221 2 -139.15 -160.9 -64.1 0.5 6220 + 6222 2 -137.65 -172.3 -67.7 0.5 6219 + 6223 2 -126.05 -179.2 -67.2 0.5 6215 + 6224 2 -124.25 -179.8 -68.2 0.5 6213 + 6225 2 -89.75 -184.5 -67.4 0.5 6117 + 6226 2 -95.45 -184.5 -69.6 0.5 6225 + 6227 2 -102.65 -184.5 -70.2 0.75 6226 + 6228 2 -107.45 -183 -73.6 0.75 6227 + 6229 2 -112.25 -186.2 -71.4 0.75 6228 + 6230 2 -117.55 -188.1 -70.2 0.75 6229 + 6231 2 -121.55 -190.3 -70.9 0.75 6230 + 6232 2 -69.55 -193.5 -44.8 0.5 5971 + 6233 2 -75.75 -192.6 -44.9 0.25 6232 + 6234 2 -79.45 -192.6 -48.1 0.25 6233 + 6235 2 -85.15 -193.3 -46.1 0.25 6234 + 6236 2 -93.15 -191.4 -47.2 0.25 6235 + 6237 2 -97.85 -191.9 -46 0.25 6236 + 6238 1 -419.15 -21 96.2 7.25 1 + 6239 1 -420.35 -19 100.6 7 6238 + 6240 1 -422.25 -17 107.4 7 6239 + 6241 1 -424.05 -15.1 106.2 7.25 6240 + 6242 1 -423.55 -13.9 105.7 7 6241 + 6243 1 -425.45 -12 110.2 6.75 6242 + 6244 1 -426.85 -10.2 109.6 6.25 6243 + 6245 1 -428.85 -8.5 110.5 5.75 6244 + 6246 1 -428.75 -8.6 111 4.5 6245 + 6247 1 -430.85 -4.6 110.7 4 6246 + 6248 1 -430.85 -3.3 114.3 2.5 6247 diff --git a/tests/swc/dCH-cobalt.CNG_cvapp.morph.nml b/tests/swc/dCH-cobalt.CNG_cvapp.morph.nml new file mode 100644 index 00000000..ba7292b7 --- /dev/null +++ b/tests/swc/dCH-cobalt.CNG_cvapp.morph.nml @@ -0,0 +1,75597 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: dCH-cobalt.CNG.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/dCH-cobalt.CNG_small.swc b/tests/swc/dCH-cobalt.CNG_small.swc new file mode 100644 index 00000000..6d96c36c --- /dev/null +++ b/tests/swc/dCH-cobalt.CNG_small.swc @@ -0,0 +1,185 @@ +# Original file dCH-cobalt.swc edited by Duncan Donohue using StdSwc version 1.31 on 10/1/10. +# Irregularities and fixes documented in dCH-cobalt.swc.std. See StdSwc1.31.doc for more information. +# +# dCH neuron (lobula place tangential cells, LPTC) from Calliphora vicina +# identification by response properties, cobalt fills, light microscopy, 40x objective +# processed with the TREES toolbox http://www.treestoolbox.org +# scaling 1:1:1 um +# Max Planck Institute of Neurobiology, Martinsried, Germany +# Systems and Computational Neuroscience, Alexander Borst +# published in "The intrinsic electrophysiological characteristics of fly lobula plate tangential cells: I. Passive membrane properties" Haag J, Borst A. PMID 9001975 +# ORIGINAL_SOURCE +# CREATURE +# REGION +# FIELD/LAYER +# TYPE +# CONTRIBUTOR +# REFERENCE +# RAW +# EXTRAS +# SOMA_AREA +# SHRINKAGE_CORRECTION +# VERSION_NUMBER +# VERSION_DATE +# ********************************************* +# SCALE 1.0 1.0 1.0 + 1 1 -419.15 -22.7 95.4 8 -1 + 2 1 -417.75 -24.9 94.7 8 1 + 3 1 -415.65 -25.4 89.2 6.75 2 + 4 1 -418.25 -27.6 86.8 6 3 + 5 1 -419.85 -29 86.3 5.75 4 + 6 1 -419.65 -30.8 85.5 6 5 + 7 1 -422.45 -32.1 82.4 6 6 + 8 1 -423.45 -33.3 82.4 6 7 + 9 1 -425.85 -35.6 80.1 6.25 8 + 10 1 -430.45 -40.2 65 2 9 + 11 1 -434.45 -39.5 63.9 1.25 10 + 12 1 -426.75 -39.5 65 3.25 9 + 13 1 -428.15 -43.9 58.6 3.25 12 + 14 1 -422.65 -47.3 58.6 2.5 13 + 15 1 -415.85 -43.9 58.4 2.25 14 + 16 1 -410.05 -48.2 53.8 2.5 15 + 17 1 -402.55 -51.2 50.5 2.5 16 + 18 1 -393.75 -56.9 46.6 1.75 17 + 19 1 -390.05 -56.7 44.5 1.5 18 + 20 1 -387.05 -62.3 45.6 1.75 19 + 21 1 -381.15 -61 39.8 1.75 20 + 22 1 -376.25 -64.5 41.3 1.75 21 + 23 1 -369.55 -63.6 40.6 1.5 22 + 24 1 -365.35 -68.1 35.7 1.5 23 + 25 1 -354.15 -64.8 33 1.75 24 + 26 1 -353.85 -67 33 1.75 25 + 27 1 -348.85 -70.4 32 2 26 + 28 1 -343.35 -71.4 30.1 1.75 27 + 29 1 -335.75 -76.9 29.2 1.75 28 + 30 1 -322.85 -78.5 26 2.5 29 + 31 1 -319.25 -80.9 25.5 2.5 30 + 32 1 -314.45 -84 24.1 1.75 31 + 33 1 -306.05 -86.3 24.9 1.75 32 + 34 1 -294.95 -90.3 16.3 1.25 33 + 35 1 -292.95 -93.5 16.1 1.25 34 + 36 1 -287.35 -94.6 15 1.75 35 + 37 1 -276.05 -98.5 11 1.75 36 + 38 1 -268.15 -103.5 6 1.25 37 + 39 1 -264.65 -103.2 7.3 1.25 38 + 40 1 -261.15 -105.7 3.7 1.25 39 + 41 1 -257.85 -107.8 3.6 1.25 40 + 42 1 -249.55 -110.5 0.2 1.25 41 + 43 1 -241.65 -113.7 -4.5 1.5 42 + 44 1 -235.95 -119.3 -6.4 2 43 + 45 1 -229.45 -121.4 -11.3 1.5 44 + 46 1 -221.85 -124.8 -16.1 1.25 45 + 47 1 -217.95 -128.6 -16 1.25 46 + 48 1 -210.05 -134.2 -21.9 1.25 47 + 49 1 -203.95 -140.2 -28.2 1.25 48 + 50 1 -198.55 -142.5 -28 1.25 49 + 51 1 -188.45 -145.9 -32.9 1.25 50 + 52 1 -183.25 -149.1 -35.7 1.25 51 + 53 1 -173.45 -153.6 -38.8 1.25 52 + 54 1 -164.35 -158.7 -40.6 1 53 + 55 1 -151.15 -166.8 -44.4 1.25 54 + 56 1 -142.45 -173.1 -47 1.25 55 + 57 1 -131.65 -181.3 -46.8 1.25 56 + 58 1 -121.55 -186.6 -46.8 1.25 57 + 59 1 -113.65 -189.3 -45.9 1.25 58 + 60 1 -104.85 -191.3 -43.1 1.75 59 + 61 1 -99.35 -193 -42.4 2 60 + 62 1 -91.05 -193 -40.3 1.75 61 + 63 1 -86.15 -191.4 -39.5 1.5 62 + 64 1 -81.65 -192.5 -39.3 1.5 63 + 65 1 -74.75 -193.5 -40.1 1.25 64 + 66 1 -67.05 -195.7 -41.3 1.5 65 + 67 1 -62.45 -195.7 -41.9 1 66 + 68 1 -59.15 -195.2 -42.1 1.25 67 + 69 1 -54.35 -193.8 -43.2 1.75 68 + 70 1 -51.85 -194.35 -42.8 1.25 69 + 71 1 -49.35 -194.9 -42.4 1.25 70 + 72 2 -47.35 -190.4 -52.9 2.75 70 + 73 2 -45.05 -190.2 -52.9 2.5 72 + 74 2 -35.75 -191.8 -53.4 3.25 73 + 75 2 -24.95 -193 -51.6 3.75 74 + 76 2 -20.25 -193 -53.3 3.75 75 + 77 2 -11.25 -189.2 -53.8 3.75 76 + 78 2 -4.45 -187.4 -56.1 4.25 77 + 79 2 5.55 -187.4 -58.5 3.75 78 + 80 2 9.95 -187.4 -56.8 3.5 79 + 81 2 15.55 -185.7 -58.1 3.75 80 + 82 2 23.55 -185.7 -60 5 81 + 83 2 29.95 -184 -61.5 5.25 82 + 84 2 38.15 -183.8 -63.6 6.25 83 + 85 2 45.95 -181.5 -62.9 6.5 84 + 86 2 52.45 -178.9 -65.3 5.75 85 + 87 2 59.75 -178.3 -65.3 5.25 86 + 88 2 65.75 -176.1 -65.5 4.25 87 + 89 2 72.65 -171.7 -65.8 4.25 88 + 90 2 79.45 -167.5 -64.7 5.25 89 + 91 2 87.05 -164.9 -64.8 4.75 90 + 92 2 93.15 -163.3 -63.5 3 91 + 93 2 97.45 -160.3 -63.7 4 92 + 94 2 98.05 -156.9 -61.9 4.5 93 + 95 2 104.05 -151.7 -62.7 4.5 94 + 96 2 107.85 -147 -62.9 5 95 + 97 2 112.75 -141.7 -67 4.75 96 + 98 2 117.55 -137.2 -69.6 5 97 + 99 2 121.95 -134.2 -73.8 5.25 98 + 100 2 125.45 -131.2 -73.8 5.25 99 + 101 2 128.25 -127.9 -78.1 5 100 + 102 2 131.45 -124.3 -78 4.75 101 + 103 2 134.65 -120.1 -82.6 5.25 102 + 104 2 139.45 -115.3 -87.8 4 103 + 105 2 143.35 -111.5 -90.8 3.75 104 + 106 2 147.45 -104.4 -97.5 4 105 + 107 2 151.85 -99.6 -98.6 4.5 106 + 108 2 157.05 -97.3 -103.8 4.25 107 + 109 2 162.15 -92 -103.8 5 108 + 110 2 166.85 -88.2 -104.1 5.25 109 + 111 2 171.65 -81.6 -103.7 4.25 110 + 112 2 175.15 -77.7 -105.1 4.25 111 + 113 2 180.15 -73.1 -103.3 3.75 112 + 114 2 183.95 -67.9 -104.1 4.5 113 + 115 3 185.25 -68.1 -102.5 3.25 114 + 116 3 189.05 -67.6 -104.2 3.75 115 + 117 3 192.05 -64.3 -98.9 3.5 116 + 118 3 195.85 -63.2 -95.9 3.5 117 + 119 3 199.75 -60.3 -97.3 3.5 118 + 120 3 203.55 -60.5 -95.1 3 119 + 121 3 206.75 -57.9 -93.8 3.25 120 + 122 3 209.65 -54.9 -92.7 3.25 121 + 123 3 211.95 -53 -89.3 3.25 122 + 124 3 213.85 -51.5 -88.7 3 123 + 125 3 213.85 -50.4 -89.2 3.25 124 + 126 3 219.35 -47.7 -86.7 3 125 + 127 3 219.65 -45.5 -84.7 3 126 + 128 3 226.35 -43.2 -85.5 3.25 127 + 129 3 227.55 -43 -90.9 1.5 128 + 130 3 230.65 -42.1 -90.9 3.25 129 + 131 3 231.15 -41.5 -86.6 3.25 130 + 132 3 231.15 -41.5 -86.7 1.75 131 + 133 3 233.45 -42.1 -86.6 1.75 132 + 134 3 236.55 -42.1 -87.4 1.5 133 + 135 3 238.65 -40.2 -89.4 1.75 134 + 136 3 240.95 -39 -88.1 1.75 135 + 137 3 242.05 -36.9 -87.4 2 136 + 138 3 245.35 -33.4 -81.4 2.25 137 + 139 3 248.95 -32.4 -80.6 2.25 138 + 140 3 252.15 -30.5 -77.8 2.5 139 + 141 3 254.35 -29.9 -74.9 2.5 140 + 142 3 255.95 -27.3 -76.2 2 141 + 143 3 260.05 -24.4 -73.7 2.5 142 + 144 3 263.15 -21.8 -71 2.25 143 + 145 3 263.75 -20.2 -66.7 2 144 + 146 3 269.75 -17.7 -62.1 2.5 145 + 147 3 271.95 -18.5 -61.7 2.5 146 + 148 3 273.85 -17.4 -60.9 2.5 147 + 149 3 273.05 -18 -56.9 2.75 148 + 150 3 273.05 -18 -56.8 2 149 + 151 3 274.35 -16.3 -52.9 2 150 + 152 3 275.95 -16.1 -53.6 2 151 + 153 3 278.55 -12.7 -48.9 2.25 152 + 154 3 279.95 -10.8 -47.6 2.5 153 + 155 3 279.35 -12.5 -44.7 2.25 154 + 156 3 283.75 -9.5 -47.2 2.25 155 + 157 3 285.35 -9.5 -47.1 2.25 156 + 158 3 289.15 -11 -43 3 157 + 159 3 290.65 -8.3 -41.7 3 158 + 160 3 292.55 -7.3 -36.9 3.25 159 diff --git a/tests/swc/dCH-cobalt.CNG_small_cvapp.morph.nml b/tests/swc/dCH-cobalt.CNG_small_cvapp.morph.nml new file mode 100644 index 00000000..ec5dfcdf --- /dev/null +++ b/tests/swc/dCH-cobalt.CNG_small_cvapp.morph.nml @@ -0,0 +1,1013 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: dCH-cobalt.CNG_small.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/l22.swc b/tests/swc/l22.swc new file mode 100644 index 00000000..2d04ae8d --- /dev/null +++ b/tests/swc/l22.swc @@ -0,0 +1,1621 @@ +# Original file l22.swc edited by Duncan Donohue using StdSwc version 1.21 on 7/25/05. +# Irregularities and fixes documented in l22.swc.std. See StdSwc1.21.doc for more information. +# +# ORIGINAL_SOURCE Neurolucida +# CREATURE rat F344 +# REGION Hippocampus +# FIELD/LAYER CA3 +# TYPE CA3c Pyramidal Cell in vivo young +# CONTRIBUTOR Buzsaki_G & Turner_DA +# REFERENCE J. Comp. Neurol. 356: 580-594, 1995 +# RAW l22.asc +# EXTRAS Turner_P.CA3 +# SOMA_AREA 0.98E3 +# SHRINKAGE_CORRECTION 1.33 1.33 2.5 +# VERSION_NUMBER 2.0 +# VERSION_DATE 1998-03-27 +# ********************************************* +# SCALE 1.33 1.33 2.5 +# + 1 1 0 -5.114 4.688 7.843 -1 + 2 1 -0.313 -0.323 4.906 7.645 1 + 3 1 -0.625 4.469 5.125 5.932 2 + 4 1 -0.938 9.26 5.344 4.287 3 + 5 1 -1.25 14.051 5.562 3.303 4 + 6 1 -1.563 18.843 5.781 2.833 5 + 7 1 -1.875 23.634 6 2.73 6 + 8 1 -2.913 28.103 10.7 2.42 7 + 9 4 -3.112 30.457 13.2 2.42 8 + 10 4 -3.325 30.457 13.2 2.42 9 + 11 4 0.825 34.287 14.2 1.33 10 + 12 4 1.663 39.607 13.95 1.33 11 + 13 4 2.487 44.076 10.95 1.02 12 + 14 4 4.575 50.686 9.7 1.02 13 + 15 4 5.812 52.814 9.95 1.02 14 + 16 4 3.538 57.922 14.45 0.55 15 + 17 4 0.213 66.008 14.45 0.55 16 + 18 4 0 66.008 14.45 0.55 17 + 19 4 -3.95 74.32 14.45 0.55 18 + 20 4 -3.95 74.533 14.45 0.55 19 + 21 4 -4.15 80.917 12.7 0.55 20 + 22 4 1.955 88.219 10.25 0.24 21 + 23 4 3.405 92.262 10.25 0.24 22 + 24 4 4.03 93.113 10.25 0.24 23 + 25 4 5.48 107.384 9.75 0.24 24 + 26 4 5.48 108.023 9.75 0.24 25 + 27 4 12.13 117.173 9.75 0.24 26 + 28 4 12.342 117.811 9.75 0.24 27 + 29 4 16.492 126.55 9.75 0.24 28 + 30 4 16.918 127.401 9.75 0.24 29 + 31 4 19.817 131.87 9.75 0.24 30 + 32 4 22.317 136.551 21.75 0.24 31 + 33 4 22.517 136.764 21.75 0.24 32 + 34 4 22.73 136.977 21.75 0.24 33 + 35 4 27.504 147.417 21.75 0.24 34 + 36 4 27.93 147.843 21.75 0.24 35 + 37 4 29.593 154.014 21.75 0.24 36 + 38 4 29.792 154.865 21.75 0.24 37 + 39 4 30.005 161.036 21.5 0.24 38 + 40 4 30.005 161.888 21.5 0.24 39 + 41 4 30.829 166.157 21.5 0.24 40 + 42 4 38.942 179.776 21.2 0.24 41 + 43 4 38.942 179.989 21.2 0.24 42 + 44 4 39.355 186.173 21.2 0.24 43 + 45 4 39.568 186.599 21.2 0.24 44 + 46 4 43.717 194.047 21.2 0.24 45 + 47 4 43.93 194.473 21.2 0.24 46 + 48 4 47.255 204.488 20.45 0.24 47 + 49 4 51.405 209.169 21.65 0.24 48 + 50 4 55.355 210.659 11.65 0.24 49 + 51 4 55.767 211.084 11.9 0.24 50 + 52 4 60.342 221.724 11.9 0.24 51 + 53 4 60.754 222.576 11.9 0.24 52 + 54 4 64.292 235.357 22.4 0.24 53 + 55 4 68.03 244.308 26.65 0.24 54 + 56 4 68.03 244.521 25.65 0.24 55 + 57 4 71.567 249.202 18.65 0.24 56 + 58 4 71.567 249.628 18.65 0.24 57 + 59 4 72.804 258.353 11.9 0.24 58 + 60 4 72.804 258.778 11.9 0.24 59 + 61 4 75.305 262.821 26.4 0.24 60 + 62 4 75.93 263.247 -0.6 0.24 61 + 63 4 -4.15 81.343 12.7 0.55 21 + 64 4 -7.9 85.599 11.45 0.55 63 + 65 4 -12.462 93.273 21.7 0.39 64 + 66 4 -13.087 96.891 21.7 0.39 65 + 67 4 -12.888 97.103 21.7 0.39 66 + 68 4 -16.412 103.913 17.7 0.39 67 + 69 4 -16.412 104.339 17.2 0.39 68 + 70 4 -18.5 110.097 11.95 0.39 69 + 71 4 -18.7 110.523 11.95 0.39 70 + 72 4 -19.112 113.502 25.95 0.39 71 + 73 4 -19.112 114.141 25.95 0.39 72 + 74 4 -20.575 118.822 25.95 0.39 73 + 75 4 -23.687 132.455 24.7 0.39 74 + 76 4 -23.275 133.093 24.7 0.39 75 + 77 4 -22.65 144.584 24.2 0.39 76 + 78 4 -22.65 145.648 24.2 0.39 77 + 79 4 -24.938 151.62 18.7 0.39 78 + 80 4 -30.337 160.77 19.2 0.39 79 + 81 4 -30.55 160.77 19.2 0.39 80 + 82 4 -33.45 167.58 31.7 0.39 81 + 83 4 -33.662 167.58 31.7 0.39 82 + 84 4 -33.037 168.644 30.7 0.39 83 + 85 4 -33.037 168.644 30.45 0.39 84 + 86 4 -34.075 175.68 33.7 0.39 85 + 87 4 -34.287 175.68 33.7 0.39 86 + 88 4 -34.913 182.277 36.2 0.39 87 + 89 4 -34.913 182.489 36.2 0.39 88 + 90 4 -36.575 192.93 34.7 0.24 89 + 91 4 -36.575 193.143 34.45 0.24 90 + 92 4 -34.7 200.165 34.2 0.24 91 + 93 4 -34.913 200.803 34.2 0.24 92 + 94 4 -37.825 208.903 34.2 0.24 93 + 95 4 -37.825 209.116 34.2 0.24 94 + 96 4 -42.387 219.118 30.2 0.24 95 + 97 4 -44.475 225.076 41.7 0.24 96 + 98 4 -44.675 225.502 41.7 0.24 97 + 99 4 -44.888 232.324 44.2 0.24 98 + 100 4 -44.888 232.537 43.45 0.24 99 + 101 4 -48.213 239.985 42.95 0.24 100 + 102 4 -48.625 240.411 42.95 0.24 101 + 103 4 -48.838 240.411 21.95 0.24 102 + 104 4 -38.863 178.021 29.7 0.24 84 + 105 4 -41.563 183.553 29.7 0.24 104 + 106 4 -44.05 184.83 29.7 0.24 105 + 107 4 -44.262 185.256 29.7 0.24 106 + 108 4 -50.7 201.229 36.45 0.24 107 + 109 4 -50.912 201.229 36.2 0.24 108 + 110 4 -56.312 208.903 29.2 0.24 109 + 111 4 -60.887 212.308 29.2 0.24 110 + 112 4 -67.737 216.99 29.2 0.24 111 + 113 4 -67.95 217.415 29.2 0.24 112 + 114 4 -73.762 222.097 29.2 0.24 113 + 115 4 -73.975 222.522 29.2 0.24 114 + 116 4 -77.087 229.558 29.2 0.24 115 + 117 4 -77.087 229.771 29.2 0.24 116 + 118 4 -81.463 234.452 23.95 0.24 117 + 119 4 -81.662 234.665 24.95 0.24 118 + 120 4 -83.95 238.921 40.95 0.24 119 + 121 4 -84.362 239.56 40.95 0.24 120 + 122 4 -89.562 247.22 40.95 0.24 121 + 123 4 -93.087 253.192 38.7 0.24 122 + 124 4 -95.374 255.533 45.2 0.24 123 + 125 4 -95.374 255.959 45.2 0.24 124 + 126 4 -97.662 261.066 49.7 0.24 125 + 127 4 -97.875 261.279 47.45 0.24 126 + 128 4 -103.487 265.322 44.7 0.24 127 + 129 4 -103.687 265.535 43.2 0.24 128 + 130 4 -103.9 266.173 30.2 0.24 129 + 131 4 -104.112 266.173 30.45 0.24 130 + 132 4 -104.312 265.96 30.7 0.24 131 + 133 4 9.563 56.006 9.95 0.86 15 + 134 4 14.55 61.752 16.45 0.86 133 + 135 4 17.25 66.221 16.45 0.86 134 + 136 4 17.25 66.434 16.45 0.86 135 + 137 4 23.062 72.405 16.45 0.7 136 + 138 4 23.062 72.618 16.45 0.7 137 + 139 4 28.888 79.64 16.45 0.7 138 + 140 4 28.888 79.853 16.45 0.7 139 + 141 4 32.838 83.045 16.45 0.7 140 + 142 4 33.037 83.471 16.45 0.7 141 + 143 4 36.575 89.443 19.7 0.7 142 + 144 4 42.188 96.678 21.45 0.55 143 + 145 4 42.813 97.955 21.45 0.55 144 + 146 4 42.6 97.955 21.45 0.55 145 + 147 4 47.587 100.934 21.45 0.39 146 + 148 4 47.787 100.934 21.45 0.39 147 + 149 4 51.95 105.19 21.95 0.39 148 + 150 4 52.987 105.615 23.95 0.39 149 + 151 4 51.95 108.169 20.7 0.39 150 + 152 4 51.737 108.169 20.7 0.39 151 + 153 4 54.65 116.907 25.95 0.39 152 + 154 4 54.65 117.12 25.7 0.39 153 + 155 4 57.15 121.801 21.95 0.24 154 + 156 4 57.15 122.014 21.95 0.24 155 + 157 4 59.225 126.27 21.2 0.24 156 + 158 4 59.225 126.483 21.2 0.24 157 + 159 4 63.375 130.965 20.95 0.24 158 + 160 4 63.587 131.604 20.95 0.24 159 + 161 4 65.449 137.562 15.95 0.24 160 + 162 4 71.9 148.628 31.45 0.24 161 + 163 4 71.9 148.84 31.45 0.24 162 + 164 4 74.813 153.748 30.7 0.24 163 + 165 4 75.225 154.386 30.7 0.24 164 + 166 4 77.712 162.898 23.7 0.24 165 + 167 4 77.712 163.324 23.7 0.24 166 + 168 4 81.662 168.87 36.45 0.24 167 + 169 4 82.912 177.595 36.7 0.24 168 + 170 4 83.125 177.595 36.7 0.24 169 + 171 4 84.788 183.341 36.7 0.24 170 + 172 4 84.788 183.553 36.7 0.24 171 + 173 4 84.575 183.553 36.7 0.24 172 + 174 4 85.2 183.766 40.7 0.24 173 + 175 4 89.429 191.706 40.65 0.24 174 + 176 4 89.429 191.919 40.65 0.24 175 + 177 4 90.041 195.749 40.65 0.24 176 + 178 4 90.254 195.962 40.65 0.24 177 + 179 4 90.467 196.388 40.65 0.24 178 + 180 4 95.654 202.772 40.65 0.24 179 + 181 4 100.229 214.276 31.4 0.24 180 + 182 4 101.891 219.809 31.4 0.24 181 + 183 4 102.104 220.022 30.9 0.24 182 + 184 4 102.716 224.704 44.15 0.24 183 + 185 4 102.929 224.916 44.15 0.24 184 + 186 4 104.591 233.229 44.15 0.24 185 + 187 4 105.004 234.08 44.15 0.24 186 + 188 4 108.329 239.187 44.65 0.24 187 + 189 4 108.129 239.187 45.15 0.24 188 + 190 4 107.703 244.507 47.9 0.24 189 + 191 4 107.916 245.146 47.9 0.24 190 + 192 4 106.666 248.989 41.65 0.24 191 + 193 4 106.879 249.628 41.65 0.24 192 + 194 4 109.366 256.437 41.4 0.24 193 + 195 4 109.366 256.65 41.4 0.24 194 + 196 4 109.579 260.693 52.9 0.24 195 + 197 4 109.579 260.906 52.9 0.24 196 + 198 4 109.366 261.332 43.9 0.24 197 + 199 4 59.85 109.459 23.95 0.39 150 + 200 4 60.05 109.672 23.95 0.39 199 + 201 4 60.887 110.097 23.95 0.39 200 + 202 4 61.925 107.956 23.95 0.39 201 + 203 4 66.5 111.161 26.2 0.39 202 + 204 4 71.687 115.843 26.2 0.39 203 + 205 4 71.9 116.269 26.2 0.39 204 + 206 4 75.012 119.886 26.2 0.39 205 + 207 4 75.012 120.099 26.2 0.39 206 + 208 4 75.637 122.653 26.2 0.39 207 + 209 4 80 124.993 24.7 0.24 208 + 210 4 80.212 125.206 24.7 0.24 209 + 211 4 85.612 132.88 21.2 0.24 210 + 212 4 85.825 133.093 21.2 0.24 211 + 213 4 86.862 134.157 21.2 0.24 212 + 214 4 91.225 142.669 20.7 0.24 213 + 215 4 91.424 142.882 20.7 0.24 214 + 216 4 96.837 146.287 29.95 0.24 215 + 217 4 96.837 146.5 30.2 0.24 216 + 218 4 104.312 151.407 32.7 0.24 217 + 219 4 104.525 151.62 32.7 0.24 218 + 220 4 104.724 152.046 32.95 0.24 219 + 221 4 104.724 152.258 36.95 0.24 220 + 222 4 113.462 160.132 36.2 0.24 221 + 223 4 117.825 164.388 43.95 0.24 222 + 224 4 117.825 164.601 43.95 0.24 223 + 225 4 118.649 169.083 42.7 0.24 224 + 226 4 118.649 169.296 42.2 0.24 225 + 227 4 129.249 181.638 42.45 0.24 226 + 228 4 129.249 181.851 42.45 0.24 227 + 229 4 131.737 185.043 47.45 0.24 228 + 230 4 131.949 185.043 46.45 0.24 229 + 231 4 139.224 188.674 42.7 0.24 230 + 232 4 147.537 200.165 54.45 0.24 231 + 233 4 147.537 200.378 54.45 0.24 232 + 234 4 148.787 200.165 49.7 0.24 233 + 235 4 153.349 199.952 49.45 0.24 234 + 236 4 153.562 199.952 49.45 0.24 235 + 237 4 161.036 200.165 42.95 0.24 236 + 238 4 163.324 199.101 60.2 0.24 237 + 239 4 163.537 199.527 60.2 0.24 238 + 240 4 173.299 201.016 48.95 0.24 239 + 241 4 176.425 200.165 41.45 0.24 240 + 242 4 178.912 200.803 59.2 0.24 241 + 243 4 178.699 200.803 59.95 0.24 242 + 244 4 182.649 197.824 64.2 0.24 243 + 245 4 182.649 198.037 64.2 0.24 244 + 246 4 182.649 197.399 65.45 0.24 245 + 247 4 153.775 204.847 55.45 0.24 234 + 248 4 153.775 205.059 55.7 0.24 247 + 249 4 156.262 207.826 58.95 0.24 248 + 250 4 156.262 208.039 58.95 0.24 249 + 251 4 156.674 208.69 58.45 0.24 250 + 252 4 158.962 214.223 51.45 0.24 251 + 253 4 158.962 214.649 51.45 0.24 252 + 254 4 159.174 215.287 52.2 0.24 253 + 255 4 162.699 220.82 58.7 0.24 254 + 256 4 171.849 223.374 63.45 0.24 255 + 257 4 174.336 233.601 67.2 0.24 256 + 258 4 174.336 233.814 66.2 0.24 257 + 259 4 174.762 234.665 69.95 0.24 258 + 260 4 63.175 116.269 20.7 0.24 201 + 261 4 65.037 127.334 20.2 0.24 260 + 262 4 64.838 127.334 20.2 0.24 261 + 263 4 67.537 130.327 20.2 0.24 262 + 264 4 67.737 130.965 20.2 0.24 263 + 265 4 73.975 147.564 20.2 0.24 264 + 266 4 74.187 147.989 20.2 0.24 265 + 267 4 80.212 156.302 20.2 0.24 266 + 268 4 85.2 164.814 20.2 0.24 267 + 269 4 85.2 165.239 20.2 0.24 268 + 270 4 85.612 166.09 20.2 0.24 269 + 271 4 90.812 178.446 20.2 0.24 270 + 272 4 90.812 178.659 20.2 0.24 271 + 273 4 96.837 181.851 20.2 0.24 272 + 274 4 97.25 182.489 20.2 0.24 273 + 275 4 105.15 191.227 20.2 0.24 274 + 276 4 116.162 207.613 9.2 0.24 275 + 277 4 116.162 207.826 9.2 0.24 276 + 278 4 119.274 211.457 9.2 0.24 277 + 279 4 119.487 211.67 9.2 0.24 278 + 280 4 122.599 215.074 9.2 0.24 279 + 281 4 122.812 215.287 9.2 0.24 280 + 282 4 127.175 224.863 9.2 0.24 281 + 283 4 133.2 238.283 9.2 0.24 282 + 284 4 133.2 238.07 9.2 0.24 283 + 285 4 136.525 240.836 6.7 0.24 284 + 286 4 136.937 241.262 6.7 0.24 285 + 287 4 141.512 247.22 18.95 0.24 286 + 288 4 141.512 247.433 0.95 0.24 287 + 289 4 44.262 100.721 11.2 0.39 145 + 290 4 44.262 100.934 11.2 0.39 289 + 291 4 46.337 105.615 11.2 0.39 290 + 292 4 46.337 105.828 11.2 0.39 291 + 293 4 47.587 110.31 9.7 0.39 292 + 294 4 47.787 110.949 9.7 0.39 293 + 295 4 48.625 120.95 7.95 0.39 294 + 296 4 48.625 121.163 7.95 0.39 295 + 297 4 51.95 130.327 7.7 0.39 296 + 298 4 56.312 134.157 9.2 0.39 297 + 299 4 56.525 134.157 9.2 0.39 298 + 300 4 63.175 137.988 9.2 0.39 299 + 301 4 63.587 138.413 9.2 0.39 300 + 302 4 74.813 144.372 9.2 0.39 301 + 303 4 81.875 147.138 9.2 0.39 302 + 304 4 82.287 147.138 9.2 0.39 303 + 305 4 89.562 148.84 9.2 0.39 304 + 306 4 89.762 148.84 9.2 0.39 305 + 307 4 97.037 150.343 1.45 0.39 306 + 308 4 102.024 152.471 1.45 0.39 307 + 309 4 102.237 152.684 1.45 0.39 308 + 310 4 106.812 155.45 1.45 0.24 309 + 311 4 115.949 164.601 1.45 0.24 310 + 312 4 115.949 164.814 1.45 0.24 311 + 313 4 120.937 167.58 1.45 0.24 312 + 314 4 121.349 168.006 1.45 0.24 313 + 315 4 128.837 176.957 1.45 0.24 314 + 316 4 129.037 177.382 1.45 0.24 315 + 317 4 135.487 185.469 1.45 0.24 316 + 318 4 135.487 185.681 1.45 0.24 317 + 319 4 140.475 191.015 -2.55 0.24 318 + 320 4 151.487 201.442 -2.55 0.24 319 + 321 4 151.687 201.655 -2.55 0.24 320 + 322 4 153.775 201.867 -6.55 0.24 321 + 323 4 153.974 202.08 -6.55 0.24 322 + 324 4 156.887 208.903 -1.05 0.24 323 + 325 4 164.162 212.946 0.7 0.24 324 + 326 4 164.162 213.159 0.7 0.24 325 + 327 4 171.437 216.99 -4.55 0.24 326 + 328 4 171.437 217.202 -4.55 0.24 327 + 329 4 174.762 218.266 0.45 0.24 328 + 330 4 174.962 218.266 0.45 0.24 329 + 331 4 175.174 218.266 -14.3 0.24 330 + 332 4 -6.025 36.841 8.45 1.02 9 + 333 4 -6.025 37.054 7.95 1.02 332 + 334 4 -6.863 40.033 6.95 1.17 333 + 335 4 -6.863 41.31 11.2 1.17 334 + 336 4 -6.863 41.097 11.2 1.17 335 + 337 4 -2.913 43.863 5.2 0.86 336 + 338 4 -2.7 46.204 5.2 0.86 337 + 339 4 -6.863 47.907 5.2 0.86 338 + 340 4 -7.062 47.907 5.2 0.86 339 + 341 4 -11.012 48.545 5.2 0.86 340 + 342 4 -11.225 48.545 5.2 0.86 341 + 343 4 -16.625 48.971 5.2 0.86 342 + 344 4 -19.112 48.758 5.2 0.86 343 + 345 4 -19.325 48.758 5.2 0.86 344 + 346 4 -22.437 51.963 5.2 0.86 345 + 347 4 -22.65 52.602 5.2 0.86 346 + 348 4 -25.762 52.602 5.2 0.86 347 + 349 4 -29.087 55.368 5.2 0.7 348 + 350 4 -33.45 55.581 5.2 0.7 349 + 351 4 -33.45 56.006 5.2 0.7 350 + 352 4 -35.325 58.56 1.2 0.7 351 + 353 4 -37.825 63.242 -4.8 0.7 352 + 354 4 -42.6 68.774 -4.8 0.7 353 + 355 4 -42.6 68.987 -4.8 0.7 354 + 356 4 -43.012 69.2 -5.3 0.7 355 + 357 4 -43.225 69.2 -5.3 0.7 356 + 358 4 -43.425 73.469 -8.55 0.55 357 + 359 4 -43.637 73.682 -8.55 0.55 358 + 360 4 -45.087 79.002 -8.55 0.39 359 + 361 4 -47.587 81.768 -8.55 0.39 360 + 362 4 -47.587 81.981 -8.55 0.39 361 + 363 4 -51.112 87.94 -8.55 0.39 362 + 364 4 -51.112 88.365 -8.55 0.39 363 + 365 4 -51.737 93.06 -10.3 0.39 364 + 366 4 -51.737 93.486 -10.3 0.39 365 + 367 4 -52.987 95.614 -10.3 0.39 366 + 368 4 -57.975 98.806 -10.3 0.39 367 + 369 4 -57.975 99.019 -10.55 0.39 368 + 370 4 -59.637 107.318 -0.8 0.39 369 + 371 4 -59.637 107.743 -0.3 0.39 370 + 372 4 -61.3 114.779 1.95 0.39 371 + 373 4 -61.513 115.417 2.7 0.39 372 + 374 4 -64.412 123.078 -13.55 0.39 373 + 375 4 -64.625 123.078 -13.55 0.39 374 + 376 4 -64.838 124.142 -1.8 0.39 375 + 377 4 -72.392 132.747 -1.8 0.39 376 + 378 4 -75.092 133.811 -1.8 0.39 377 + 379 4 -75.092 134.237 -1.8 0.39 378 + 380 4 -78.842 141.259 -8.55 0.39 379 + 381 4 -82.58 154.041 -14.55 0.39 380 + 382 4 -83.404 155.105 -8.3 0.39 381 + 383 4 -88.605 162.14 -12.3 0.24 382 + 384 4 -88.817 162.353 -12.3 0.24 383 + 385 4 -93.18 168.524 -12.3 0.24 384 + 386 4 -93.18 168.95 -12.3 0.24 385 + 387 4 -93.379 176.398 -13.3 0.24 386 + 388 4 -93.379 177.036 -13.55 0.24 387 + 389 4 -96.917 187.051 -16.8 0.24 388 + 390 4 -100.242 194.286 -22.8 0.24 389 + 391 4 -100.242 194.499 -25.3 0.24 390 + 392 4 -100.654 202.386 -28.55 0.24 391 + 393 4 -100.867 203.025 -28.55 0.24 392 + 394 4 -107.717 214.941 -28.8 0.24 393 + 395 4 -107.717 215.154 -28.55 0.24 394 + 396 4 -107.517 215.367 -5.55 0.24 395 + 397 4 -87.78 158.297 -10.05 0.39 382 + 398 4 -87.98 158.509 -10.55 0.39 397 + 399 4 -97.329 164.907 -15.55 0.39 398 + 400 4 -97.329 165.332 -15.55 0.39 399 + 401 4 -106.892 174.057 -7.55 0.39 400 + 402 4 -116.029 181.931 -8.3 0.39 401 + 403 4 -123.105 188.966 -9.05 0.39 402 + 404 4 -127.254 194.074 -2.55 0.24 403 + 405 4 -127.467 194.074 -3.05 0.24 404 + 406 4 -137.229 198.968 6.2 0.24 405 + 407 4 -145.542 204.088 -9.05 0.24 406 + 408 4 -145.755 204.088 -8.55 0.24 407 + 409 4 -155.105 210.047 7.2 0.24 408 + 410 4 -155.105 210.26 6.95 0.24 409 + 411 4 -163.204 214.09 -5.3 0.24 410 + 412 4 -166.742 216.005 -0.8 0.24 411 + 413 4 -167.354 216.218 -1.3 0.24 412 + 414 4 -46.75 69.639 -14.05 0.39 356 + 415 4 -50.5 72.618 -9.55 0.39 414 + 416 4 -50.7 72.618 -9.8 0.39 415 + 417 4 -59.637 72.618 -11.3 0.39 416 + 418 4 -59.85 72.618 -11.55 0.39 417 + 419 4 -63.175 78.576 -14.55 0.39 418 + 420 4 -63.175 78.789 -14.55 0.39 419 + 421 4 -67.537 82.407 -16.05 0.24 420 + 422 4 -70.237 86.024 -3.55 0.24 421 + 423 4 -72.937 88.791 -0.55 0.39 422 + 424 4 -72.937 89.004 -0.55 0.39 423 + 425 4 -78.749 88.152 -0.55 0.39 424 + 426 4 -78.749 88.365 -0.55 0.39 425 + 427 4 -91.012 95.827 -12.55 0.39 426 + 428 4 -91.85 95.827 -12.55 0.39 427 + 429 4 -93.925 98.593 -19.55 0.39 428 + 430 4 -94.137 98.593 -19.55 0.39 429 + 431 4 -98.287 98.806 -19.55 0.39 430 + 432 4 -98.287 99.019 -19.55 0.39 431 + 433 4 -111.999 107.531 -23.05 0.39 432 + 434 4 -111.999 107.743 -23.05 0.39 433 + 435 4 -114.912 108.807 -23.05 0.39 434 + 436 4 -115.125 109.02 -23.05 0.39 435 + 437 4 -117.399 115.417 -25.8 0.39 436 + 438 4 -117.825 115.63 -25.8 0.39 437 + 439 4 -118.024 116.269 -13.3 0.39 438 + 440 4 -121.349 123.078 -15.3 0.39 439 + 441 4 -121.562 123.078 -20.8 0.39 440 + 442 4 -126.962 128.185 -33.55 0.39 441 + 443 4 -127.175 128.398 -35.05 0.39 442 + 444 4 -128.624 136.498 -21.8 0.39 443 + 445 4 -128.624 136.711 -21.05 0.39 444 + 446 4 -135.899 145.648 -30.3 0.39 445 + 447 4 -136.112 146.074 -30.3 0.39 446 + 448 4 -137.775 151.62 -33.55 0.39 447 + 449 4 -138.599 156.302 -41.05 0.39 448 + 450 4 -138.812 156.302 -41.55 0.39 449 + 451 4 -146.087 165.878 -29.8 0.24 450 + 452 4 -146.087 166.09 -30.3 0.24 451 + 453 4 -150.237 174.403 -32.3 0.24 452 + 454 4 -150.45 174.829 -32.3 0.24 453 + 455 4 -150.45 182.064 -30.8 0.24 454 + 456 4 -151.687 184.405 -44.55 0.24 455 + 457 4 -153.15 193.143 -28.8 0.24 456 + 458 4 -153.15 193.355 -28.55 0.24 457 + 459 4 -152.937 193.781 -32.05 0.24 458 + 460 4 -113.25 120.737 -21.3 0.24 439 + 461 4 -110.762 125.845 -38.05 0.24 460 + 462 4 -110.962 125.845 -38.05 0.24 461 + 463 4 -110.762 126.27 -38.05 0.24 462 + 464 4 -97.462 95.401 -19.3 0.24 428 + 465 4 -110.137 97.316 -4.3 0.24 464 + 466 4 -110.137 97.529 -4.55 0.24 465 + 467 4 -120.525 99.231 -13.05 0.24 466 + 468 4 -122.812 99.87 -3.05 0.24 467 + 469 4 -135.899 107.105 0.2 0.24 468 + 470 4 -136.525 107.318 0.2 0.24 469 + 471 4 -150.237 114.353 -0.55 0.24 470 + 472 4 -150.45 114.566 -0.55 0.24 471 + 473 4 -164.162 122.014 -8.55 0.24 472 + 474 4 -164.361 122.014 -8.3 0.24 473 + 475 4 -171.437 124.781 -9.05 0.24 474 + 476 4 -177.874 130.54 -7.8 0.24 475 + 477 4 -177.874 130.752 -7.8 0.24 476 + 478 4 -183.487 138.626 -2.05 0.24 477 + 479 4 -183.686 138.839 -2.05 0.24 478 + 480 4 -189.924 149.918 -7.8 0.24 479 + 481 4 -189.924 150.13 -7.8 0.24 480 + 482 4 -196.574 157.578 -18.55 0.24 481 + 483 4 -197.611 157.791 -16.3 0.24 482 + 484 4 -70.437 86.024 -3.55 0.24 422 + 485 4 -67.112 89.868 -3.55 0.24 484 + 486 4 -66.7 90.294 -3.55 0.24 485 + 487 4 -65.037 90.719 -14.55 0.24 486 + 488 4 -65.25 90.932 -14.55 0.24 487 + 489 4 -64.625 94.337 -2.05 0.24 488 + 490 4 -64.838 94.337 -2.05 0.24 489 + 491 4 -61.513 96.039 -2.05 0.24 490 + 492 4 -61.3 96.252 -2.05 0.24 491 + 493 4 -57.35 98.38 -4.3 0.24 492 + 494 4 -57.35 98.593 -4.3 0.24 493 + 495 4 -51.737 98.806 -7.3 0.24 494 + 496 4 -51.538 98.806 -7.3 0.24 495 + 497 4 -47.175 99.87 -7.3 0.24 496 + 498 4 -46.962 99.87 -7.3 0.24 497 + 499 4 -45.513 99.019 -7.55 0.24 498 + 500 4 -45.3 99.231 -13.05 0.24 499 + 501 4 -59.637 89.216 -4.05 0.24 487 + 502 4 -54.863 89.216 -4.05 0.24 501 + 503 4 -54.65 89.443 -4.05 0.24 502 + 504 4 -46.75 89.868 -0.55 0.24 503 + 505 4 -46.55 89.868 -0.55 0.24 504 + 506 4 -43.425 88.152 -0.55 0.24 505 + 507 4 -41.975 87.727 -8.05 0.24 506 + 508 4 -8.1 44.076 -0.05 1.49 335 + 509 4 -7.687 45.991 -0.05 1.49 508 + 510 4 -7.687 46.204 -0.05 1.49 509 + 511 4 -8.313 48.758 -0.05 1.49 510 + 512 4 -8.313 48.545 -0.05 1.49 511 + 513 4 -11.425 51.538 -0.05 1.02 512 + 514 4 -11.85 54.517 -0.05 0.7 513 + 515 4 -13.712 57.07 -4.3 0.55 514 + 516 4 -13.087 63.029 -9.3 0.55 515 + 517 4 -13.087 63.242 -9.3 0.55 516 + 518 4 -13.3 68.562 -4.05 0.55 517 + 519 4 -13.513 68.774 -4.05 0.55 518 + 520 4 -14.55 74.108 -7.55 0.55 519 + 521 4 -12.888 77.087 15.95 0.55 520 + 522 4 -10.188 82.407 15.95 0.55 521 + 523 4 -10.188 83.045 15.95 0.55 522 + 524 4 -8.525 88.152 15.95 0.55 523 + 525 4 -8.313 88.791 15.95 0.55 524 + 526 4 -6.863 94.124 15.95 0.55 525 + 527 4 -6.65 94.763 15.95 0.55 526 + 528 4 -6.437 99.019 15.95 0.39 527 + 529 4 -6.437 99.231 15.95 0.39 528 + 530 4 -4.988 103.275 15.95 0.39 529 + 531 4 -5.4 104.977 15.95 0.39 530 + 532 4 -7.275 106.892 15.95 0.24 531 + 533 4 -7.275 107.105 15.95 0.24 532 + 534 4 -7.275 115.205 19.95 0.24 533 + 535 4 -7.275 115.63 19.95 0.24 534 + 536 4 -6.238 117.333 19.95 0.24 535 + 537 4 -6.238 117.545 19.95 0.24 536 + 538 4 -8.725 119.886 22.45 0.24 537 + 539 4 -8.938 120.312 22.45 0.24 538 + 540 4 -10.188 133.519 27.2 0.24 539 + 541 4 -10.188 133.732 27.2 0.24 540 + 542 4 -10.387 134.37 27.2 0.24 541 + 543 4 -12.675 136.072 27.2 0.24 542 + 544 4 -16.213 142.244 27.7 0.24 543 + 545 4 -17.662 142.882 27.7 0.24 544 + 546 4 -17.662 143.095 27.7 0.24 545 + 547 4 -17.25 145.648 31.2 0.24 546 + 548 4 -19.538 147.138 29.2 0.24 547 + 549 4 -19.737 147.351 29.2 0.24 548 + 550 4 -19.95 153.11 27.45 0.24 549 + 551 4 -20.163 153.322 27.45 0.24 550 + 552 4 -22.65 159.494 25.7 0.24 551 + 553 4 -22.863 159.706 25.7 0.24 552 + 554 4 -26.6 166.942 24.2 0.24 553 + 555 4 -30.337 172.275 37.15 0.24 554 + 556 4 -31.375 175.893 38.9 0.24 555 + 557 4 -31.375 176.105 38.9 0.24 556 + 558 4 -34.5 183.766 29.15 0.24 557 + 559 4 -34.5 183.979 30.65 0.24 558 + 560 4 -37.2 188.887 40.9 0.24 559 + 561 4 -37.4 189.099 40.9 0.24 560 + 562 4 -37.612 189.525 40.9 0.24 561 + 563 4 -38.65 190.802 43.9 0.24 562 + 564 4 -38.863 190.802 43.9 0.24 563 + 565 4 -38.437 200.378 29.15 0.24 564 + 566 4 -40.1 201.655 43.4 0.24 565 + 567 4 -40.1 201.867 43.4 0.24 566 + 568 4 -39.9 202.293 43.4 0.24 567 + 569 4 -41.563 204.847 43.4 0.24 568 + 570 4 -41.563 205.272 43.4 0.24 569 + 571 4 -43.012 209.967 43.65 0.24 570 + 572 4 -43.012 210.393 43.9 0.24 571 + 573 4 -44.675 213.798 45.4 0.24 572 + 574 4 -44.675 214.01 45.65 0.24 573 + 575 4 -46.75 214.649 46.15 0.24 574 + 576 4 -46.962 214.649 46.15 0.24 575 + 577 4 -47.175 214.436 46.15 0.24 576 + 578 4 -6.238 141.605 18.7 0.39 542 + 579 4 -4.988 146.5 29.2 0.39 578 + 580 4 -1.663 162.047 22.2 0.39 579 + 581 4 -1.663 162.26 22.2 0.39 580 + 582 4 -1.875 162.898 22.45 0.39 581 + 583 4 -3.325 165.239 19.7 0.24 582 + 584 4 -3.325 165.452 19.7 0.24 583 + 585 4 -1.663 172.488 19.2 0.24 584 + 586 4 -1.663 172.701 19.95 0.24 585 + 587 4 -1.45 173.126 20.95 0.24 586 + 588 4 0 182.915 30.7 0.24 587 + 589 4 0 183.128 30.95 0.24 588 + 590 4 0.625 188.448 31.7 0.24 589 + 591 4 0.825 189.525 31.95 0.24 590 + 592 4 1.25 194.845 31.95 0.24 591 + 593 4 1.875 199.952 32.45 0.24 592 + 594 4 1.875 200.165 32.45 0.24 593 + 595 4 2.7 202.08 32.45 0.24 594 + 596 4 2.7 202.506 32.45 0.24 595 + 597 4 0 211.67 32.95 0.24 596 + 598 4 -0.213 212.308 32.95 0.24 597 + 599 4 0.625 218.692 36.2 0.24 598 + 600 4 0.825 219.118 36.2 0.24 599 + 601 4 1.037 230.196 37.45 0.24 600 + 602 4 -3.95 239.56 28.95 0.24 601 + 603 4 -3.95 239.772 30.7 0.24 602 + 604 4 -4.575 244.667 39.7 0.24 603 + 605 4 -4.362 245.305 39.7 0.24 604 + 606 4 -6.025 249.575 39.45 0.24 605 + 607 4 -6.025 250 37.95 0.24 606 + 608 4 -7.9 258.299 34.7 0.24 607 + 609 4 -7.9 258.512 34.7 0.24 608 + 610 4 -8.725 261.704 25.7 0.24 609 + 611 4 -8.938 261.917 37.2 0.24 610 + 612 4 -0.838 165.878 22.45 0.24 582 + 613 4 1.663 175.68 22.45 0.24 612 + 614 4 1.663 175.893 22.45 0.24 613 + 615 4 4.775 180.148 22.2 0.24 614 + 616 4 4.988 181 22.2 0.24 615 + 617 4 5.613 187.597 30.45 0.24 616 + 618 4 6.025 191.653 30.45 0.24 617 + 619 4 6.025 192.291 30.45 0.24 618 + 620 4 9.137 196.76 30.45 0.24 619 + 621 4 10.387 203.783 33.2 0.24 620 + 622 4 10.188 203.995 33.45 0.24 621 + 623 4 13.3 208.903 36.95 0.24 622 + 624 4 13.087 209.542 37.2 0.24 623 + 625 4 14.75 213.585 39.2 0.24 624 + 626 4 14.75 214.223 39.2 0.24 625 + 627 4 15.375 219.543 39.95 0.24 626 + 628 4 15.375 219.969 40.45 0.24 627 + 629 4 17.875 224.438 40.95 0.24 628 + 630 4 18.075 224.863 41.2 0.24 629 + 631 4 18.288 226.566 41.7 0.24 630 + 632 4 18.288 226.991 41.7 0.24 631 + 633 4 17.662 232.112 41.95 0.24 632 + 634 4 18.075 233.814 33.9 0.24 633 + 635 4 19.538 237.644 36.9 0.24 634 + 636 4 19.325 237.857 36.4 0.24 635 + 637 4 19.737 238.283 34.9 0.24 636 + 638 4 -5.812 51.325 6.7 1.02 511 + 639 4 -5.613 51.325 6.7 1.02 638 + 640 4 -5.812 58.347 6.7 1.02 639 + 641 4 -5.812 58.56 6.7 1.02 640 + 642 4 -5.812 63.454 6.7 1.02 641 + 643 4 -6.65 66.221 6.45 1.02 642 + 644 4 -8.938 71.98 3.7 0.55 643 + 645 4 -10.8 76.448 8.45 0.55 644 + 646 4 -11.225 76.874 8.45 0.55 645 + 647 4 -16.213 76.661 12.2 0.55 646 + 648 4 -16.412 76.661 12.7 0.55 647 + 649 4 -17.875 77.725 16.45 0.55 648 + 650 4 -18.5 78.151 16.7 0.55 649 + 651 4 -19.737 83.045 -6.05 0.55 650 + 652 4 -19.737 83.258 -6.05 0.55 651 + 653 4 -19.112 84.96 -9.55 0.55 652 + 654 4 -19.112 85.173 -9.55 0.55 653 + 655 4 -18.7 85.173 3.2 0.55 654 + 656 4 -3.458 94.124 3.2 0.39 655 + 657 4 0.904 97.955 9.45 0.39 656 + 658 4 1.117 98.167 8.7 0.39 657 + 659 4 5.267 100.295 8.2 0.39 658 + 660 4 5.067 100.295 7.7 0.39 659 + 661 4 16.904 107.318 3.7 0.39 660 + 662 4 17.742 107.318 3.7 0.39 661 + 663 4 21.892 113.289 7.7 0.24 662 + 664 4 22.105 113.502 7.7 0.24 663 + 665 4 27.092 120.737 6.7 0.24 664 + 666 4 27.092 120.95 6.45 0.24 665 + 667 4 35.817 128.185 7.95 0.24 666 + 668 4 36.442 128.611 7.95 0.24 667 + 669 4 44.755 133.306 6.7 0.24 668 + 670 4 49.742 139.903 -0.8 0.24 669 + 671 4 49.955 139.903 -0.8 0.24 670 + 672 4 56.179 147.989 -3.55 0.24 671 + 673 4 63.667 156.089 -6.55 0.24 672 + 674 4 63.454 156.089 -6.55 0.24 673 + 675 4 66.154 162.898 -10.55 0.24 674 + 676 4 66.367 163.111 -10.55 0.24 675 + 677 4 70.317 165.878 -10.8 0.24 676 + 678 4 70.517 166.09 -10.8 0.24 677 + 679 4 71.554 175.254 -12.3 0.24 678 + 680 4 71.355 175.68 -12.3 0.24 679 + 681 4 75.504 186.745 -12.55 0.24 680 + 682 4 77.379 193.143 0.7 0.24 681 + 683 4 77.379 193.355 0.7 0.24 682 + 684 4 85.28 198.463 0.45 0.24 683 + 685 4 85.891 199.101 0.45 0.24 684 + 686 4 88.605 201.655 -7.05 0.24 685 + 687 4 88.392 201.655 -7.05 0.24 686 + 688 4 91.092 204.634 -7.8 0.24 687 + 689 4 90.879 204.634 -7.8 0.24 688 + 690 4 91.717 205.698 -8.05 0.24 689 + 691 4 19.192 105.615 1.2 0.24 662 + 692 4 19.405 105.828 1.2 0.24 691 + 693 4 28.13 106.892 -6.05 0.24 692 + 694 4 30.63 110.31 -7.55 0.24 693 + 695 4 30.829 110.523 -7.55 0.24 694 + 696 4 31.042 110.736 -7.55 0.24 695 + 697 4 34.567 110.736 -8.05 0.24 696 + 698 4 34.78 110.949 -8.3 0.24 697 + 699 4 41.842 119.673 -10.3 0.24 698 + 700 4 41.842 119.886 -10.3 0.24 699 + 701 4 50.567 123.717 -13.05 0.24 700 + 702 4 50.367 123.717 -13.05 0.24 701 + 703 4 55.554 128.611 -14.55 0.24 702 + 704 4 55.767 128.611 -14.55 0.24 703 + 705 4 63.042 131.391 -15.3 0.24 704 + 706 4 63.242 131.391 -15.3 0.24 705 + 707 4 68.655 134.583 -21.8 0.24 706 + 708 4 74.267 135.434 -21.8 0.24 707 + 709 4 76.967 132.242 -22.05 0.24 708 + 710 4 79.867 128.824 -27.8 0.24 709 + 711 4 83.404 126.696 -32.3 0.24 710 + 712 4 85.479 126.483 -40.05 0.24 711 + 713 4 85.692 126.696 -15.05 0.24 712 + 714 4 -6.437 69.2 5.95 0.7 643 + 715 4 -6.863 71.767 5.95 0.55 714 + 716 4 -7.062 73.895 7.95 0.55 715 + 717 4 -7.062 74.108 7.95 0.55 716 + 718 4 -7.275 74.32 7.95 0.55 717 + 719 4 -7.062 76.023 7.95 0.55 718 + 720 4 -6.863 76.023 7.95 0.55 719 + 721 4 -7.475 79.215 7.45 0.55 720 + 722 4 -7.687 79.428 7.45 0.55 721 + 723 4 -9.762 83.258 4.7 0.55 722 + 724 4 -12.675 88.152 15.2 0.39 723 + 725 4 -14.963 90.932 15.2 0.39 724 + 726 4 -14.963 91.145 15.2 0.39 725 + 727 4 -15.787 96.252 15.2 0.24 726 + 728 4 -15.787 96.465 14.95 0.24 727 + 729 4 -15.375 99.019 14.95 0.24 728 + 730 4 -15.588 99.019 14.95 0.24 729 + 731 4 -17.662 101.147 16.45 0.24 730 + 732 4 -17.662 101.359 16.45 0.24 731 + 733 4 -17.662 104.551 6.95 0.24 732 + 734 4 -17.662 104.764 7.45 0.24 733 + 735 4 -23.475 111.161 13.95 0.24 734 + 736 4 -23.9 111.587 13.95 0.24 735 + 737 4 -25.975 116.694 14.45 0.24 736 + 738 4 -31.175 120.95 2.95 0.24 737 + 739 4 -31.175 121.376 2.95 0.24 738 + 740 4 -31.787 124.142 3.45 0.24 739 + 741 4 -31.787 124.568 3.45 0.24 740 + 742 4 -34.913 126.27 3.95 0.24 741 + 743 4 -34.913 126.909 4.2 0.24 742 + 744 4 -36.362 131.816 4.2 0.24 743 + 745 4 -36.575 132.242 4.2 0.24 744 + 746 4 -36.775 132.242 4.7 0.24 745 + 747 4 -42.387 132.88 11.7 0.24 746 + 748 4 -42.387 133.093 11.7 0.24 747 + 749 4 -47.787 135.434 11.7 0.24 748 + 750 4 -48 135.647 11.7 0.24 749 + 751 4 -52.575 140.328 11.7 0.24 750 + 752 4 -52.575 140.541 11.7 0.24 751 + 753 4 -60.887 143.52 11.7 0.24 752 + 754 4 -61.087 143.733 11.7 0.24 753 + 755 4 -67.325 147.776 11.7 0.24 754 + 756 4 -70.025 152.684 11.7 0.24 755 + 757 4 -70.237 153.11 11.7 0.24 756 + 758 4 -78.962 160.558 8.7 0.24 757 + 759 4 -79.374 160.77 8.7 0.24 758 + 760 4 -79.8 161.196 8.7 0.24 759 + 761 4 -89.349 165.665 8.2 0.24 760 + 762 4 -96.212 165.878 4.45 0.24 761 + 763 4 -99.737 164.388 15.45 0.24 762 + 764 4 -99.95 164.388 14.7 0.24 763 + 765 4 -105.15 165.239 13.95 0.24 764 + 766 4 -109.925 163.537 4.95 0.24 765 + 767 4 -110.137 163.537 2.95 0.24 766 + 768 4 -114.074 162.26 -3.3 0.24 767 + 769 4 -114.074 162.047 -2.3 0.24 768 + 770 4 -119.062 162.047 15.45 0.24 769 + 771 4 -122.599 160.983 23.2 0.24 770 + 772 4 -122.599 161.196 23.2 0.24 771 + 773 4 -123.637 161.409 22.95 0.24 772 + 774 4 -39.687 139.69 4.45 0.24 746 + 775 4 -39.687 139.903 4.45 0.24 774 + 776 4 -41.975 146.925 4.45 0.24 775 + 777 4 -41.975 147.138 4.45 0.24 776 + 778 4 -44.05 156.514 4.45 0.24 777 + 779 4 -48.412 171.849 8.2 0.24 778 + 780 4 -48.838 178.446 12.7 0.24 779 + 781 4 -49.037 178.872 11.45 0.24 780 + 782 4 -51.112 183.979 -2.3 0.24 781 + 783 4 -50.912 184.192 -2.3 0.24 782 + 784 4 -50.7 189.951 -2.3 0.24 783 + 785 4 -49.875 193.143 1.7 0.24 784 + 786 4 -49.795 197.997 1.2 0.24 785 + 787 4 -50.208 203.104 -3.3 0.24 786 + 788 4 -51.245 208.85 -15.3 0.24 787 + 789 4 -51.245 209.063 -15.3 0.24 788 + 790 4 -50.62 215.673 -15.3 0.24 789 + 791 4 -50.42 217.801 -8.8 0.24 790 + 792 4 -50.62 218.014 -8.8 0.24 791 + 793 4 -53.745 224.61 -8.3 0.24 792 + 794 4 -53.945 224.61 -9.8 0.24 793 + 795 4 -54.57 230.157 -17.55 0.24 794 + 796 4 -54.783 230.795 -17.8 0.24 795 + 797 4 -55.607 235.902 -22.55 0.24 796 + 798 4 -55.82 236.328 -23.05 0.24 797 + 799 4 -52.083 244.84 -11.8 0.24 798 + 800 4 -52.282 244.84 -11.8 0.24 799 + 801 4 -51.458 245.053 -23.8 0.24 800 + 802 3 -0.449 3.141 9.914 1.02 3 + 803 3 1.4 0.281 10.313 1.02 802 + 804 3 4.457 -2.212 10.746 1.02 803 + 805 3 8.313 -4.043 11.5 1.02 804 + 806 3 12.675 -4.043 11.5 1.02 805 + 807 3 12.888 -4.043 11.5 1.02 806 + 808 3 17.037 -1.915 11.5 1.02 807 + 809 3 21.4 -1.277 11.5 1.02 808 + 810 3 21.613 -1.064 11.5 1.02 809 + 811 3 25.975 -4.894 11.5 1.02 810 + 812 3 29.712 -8.725 14.75 1.02 811 + 813 3 30.125 -14.697 16.5 1.02 812 + 814 3 32.412 -21.932 20.25 1.02 813 + 815 3 35.737 -25.975 24.75 1.02 814 + 816 3 35.737 -26.188 25 1.02 815 + 817 3 39.275 -27.039 21.25 1.02 816 + 818 3 39.275 -26.826 21.25 1.02 817 + 819 3 39.9 -26.613 19.5 1.02 818 + 820 3 44.262 -26.826 15.5 0.55 819 + 821 3 44.462 -26.826 15.5 0.55 820 + 822 3 45.087 -26.826 15.5 0.55 821 + 823 3 51.737 -29.819 15.5 0.39 822 + 824 3 53.2 -29.38 15.5 0.39 823 + 825 3 53.4 -29.38 15.5 0.39 824 + 826 3 53.825 -27.89 6.25 0.39 825 + 827 3 55.9 -28.954 6.25 0.39 826 + 828 3 55.687 -28.741 6.25 0.39 827 + 829 3 55.275 -24.485 6.25 0.39 828 + 830 3 55.488 -24.273 6.25 0.39 829 + 831 3 58.188 -22.145 19.75 0.39 830 + 832 3 61.513 -25.762 26.75 0.39 831 + 833 3 61.513 -25.975 27.25 0.39 832 + 834 3 66.912 -24.698 33.75 0.39 833 + 835 3 67.112 -24.698 34 0.39 834 + 836 3 66.287 -23.634 34.75 0.39 835 + 837 3 68.987 -24.485 36.25 0.39 836 + 838 3 69.2 -24.485 36.25 0.39 837 + 839 3 70.237 -23.421 36.25 0.39 838 + 840 3 70.437 -22.996 36.25 0.39 839 + 841 3 72.312 -22.357 39.75 0.39 840 + 842 3 71.488 -19.591 42.25 0.39 841 + 843 3 71.488 -19.378 42.5 0.39 842 + 844 3 71.275 -19.378 43 0.39 843 + 845 3 78.138 -17.676 33.5 0.24 844 + 846 3 83.125 -17.25 47.25 0.24 845 + 847 3 84.362 -18.953 46.25 0.24 846 + 848 3 84.575 -18.953 44 0.24 847 + 849 3 86.65 -15.761 29 0.24 848 + 850 3 86.65 -15.548 29 0.24 849 + 851 3 93.925 -19.378 38.5 0.24 850 + 852 3 93.925 -19.165 40 0.24 851 + 853 3 94.337 -19.165 32.25 0.24 852 + 854 3 41.15 -30.67 19.5 1.02 819 + 855 3 41.15 -30.883 19.5 1.02 854 + 856 3 45.925 -32.372 19.5 1.02 855 + 857 3 46.124 -32.372 19.5 1.02 856 + 858 3 53.4 -32.798 19.5 1.02 857 + 859 3 55.488 -36.841 20 1.02 858 + 860 3 58.387 -39.182 20 1.02 859 + 861 3 58.387 -38.969 20 1.02 860 + 862 3 61.925 -38.969 20 0.7 861 + 863 3 62.337 -38.969 20 0.7 862 + 864 3 69.612 -41.097 16 0.55 863 + 865 3 70.862 -42.587 16 0.55 864 + 866 3 69.825 -45.991 16 0.55 865 + 867 3 69.825 -48.545 16 0.55 866 + 868 3 70.025 -48.545 16 0.55 867 + 869 3 69.825 -48.971 16 0.55 868 + 870 3 64.718 -58.56 16 0.39 869 + 871 3 66.38 -62.178 16.5 0.39 870 + 872 3 68.242 -66.008 13.25 0.39 871 + 873 3 68.043 -71.98 18.25 0.39 872 + 874 3 68.655 -74.32 18 0.39 873 + 875 3 71.155 -73.682 14 0.39 874 + 876 3 73.03 -80.066 18.5 0.39 875 + 877 3 75.305 -82.62 23.5 0.39 876 + 878 3 77.805 -82.832 19.25 0.39 877 + 879 3 78.018 -82.832 19.25 0.39 878 + 880 3 83.205 -85.599 25 0.39 879 + 881 3 88.605 -87.301 29.25 0.39 880 + 882 3 91.517 -88.578 35.75 0.39 881 + 883 3 94.217 -89.868 38.25 0.39 882 + 884 3 97.955 -94.55 39.5 0.39 883 + 885 3 105.855 -99.657 39.75 0.39 884 + 886 3 105.855 -99.87 39.75 0.39 885 + 887 3 109.393 -103.487 40 0.39 886 + 888 3 109.805 -108.382 34 0.39 887 + 889 3 114.167 -111.374 36.5 0.39 888 + 890 3 112.292 -115.63 43.5 0.39 889 + 891 3 115.617 -116.694 34.5 0.39 890 + 892 3 115.83 -116.694 34.5 0.39 891 + 893 3 119.155 -121.801 31.25 0.39 892 + 894 3 118.942 -121.801 30.75 0.39 893 + 895 3 120.604 -126.057 47.75 0.39 894 + 896 3 120.604 -126.27 48 0.39 895 + 897 3 124.142 -127.547 48 0.24 896 + 898 3 123.929 -127.547 48 0.24 897 + 899 3 124.98 -126.483 53 0.24 898 + 900 3 125.18 -126.27 53 0.24 899 + 901 3 130.167 -132.242 43.75 0.24 900 + 902 3 130.167 -132.029 43.5 0.24 901 + 903 3 130.792 -135.434 38 0.24 902 + 904 3 137.03 -136.285 48.25 0.24 903 + 905 3 137.229 -136.285 48.25 0.24 904 + 906 3 137.855 -136.711 35.75 0.24 905 + 907 3 73.762 -44.502 18.25 0.55 865 + 908 3 75.225 -47.481 13.25 0.55 907 + 909 3 77.512 -48.971 13 0.39 908 + 910 3 81.875 -51.325 18.5 0.39 909 + 911 3 84.362 -53.453 14.75 0.39 910 + 912 3 92.262 -57.922 14.75 0.39 911 + 913 3 92.262 -57.709 14.75 0.39 912 + 914 3 97.662 -59.837 14 0.39 913 + 915 3 97.875 -59.837 14 0.39 914 + 916 3 99.737 -64.944 14 0.39 915 + 917 3 99.95 -64.944 14 0.39 916 + 918 3 108.887 -67.923 13.5 0.39 917 + 919 3 112.624 -68.562 12.75 0.39 918 + 920 3 112.624 -68.349 11.75 0.39 919 + 921 3 119.062 -62.39 8.25 0.39 920 + 922 3 119.062 -62.178 5 0.39 921 + 923 3 120.112 -60.05 21.25 0.39 922 + 924 3 120.525 -59.198 23 0.39 923 + 925 3 116.162 -71.98 18.75 0.39 919 + 926 3 127.374 -76.874 18.75 0.39 925 + 927 3 133.399 -78.789 21.5 0.39 926 + 928 3 138.387 -94.124 9.25 0.39 927 + 929 3 138.387 -93.911 9.25 0.39 928 + 930 3 141.299 -98.593 9.75 0.39 929 + 931 3 141.299 -98.806 9.75 0.39 930 + 932 3 146.287 -103.275 19.5 0.39 931 + 933 3 152.112 -105.615 15 0.39 932 + 934 3 151.899 -105.615 15 0.39 933 + 935 3 164.361 -112.651 15 0.39 934 + 936 3 164.987 -115.417 15 0.39 935 + 937 3 165.412 -119.886 8.25 0.24 936 + 938 3 165.412 -120.099 8.25 0.24 937 + 939 3 170.599 -127.76 8.25 0.24 938 + 940 3 170.812 -127.76 8.25 0.24 939 + 941 3 175.999 -130.54 8.25 0.24 940 + 942 3 176.425 -133.944 8.25 0.24 941 + 943 3 176.425 -133.732 8.25 0.24 942 + 944 3 178.912 -135.008 -1.5 0.24 943 + 945 3 181.199 -140.116 -1 0.24 944 + 946 3 181.412 -140.116 -1 0.24 945 + 947 3 183.075 -140.116 -1 0.24 946 + 948 3 183.487 -143.733 -0.75 0.24 947 + 949 3 189.725 -155.45 -3.75 0.24 948 + 950 3 191.799 -158.855 -8.5 0.24 949 + 951 3 191.587 -158.855 -8.5 0.24 950 + 952 3 194.286 -167.154 -6.75 0.24 951 + 953 3 194.286 -167.367 -6.75 0.24 952 + 954 3 200.524 -173.977 -13.25 0.24 953 + 955 3 200.524 -174.19 -13.25 0.24 954 + 956 3 202.187 -180.148 -12.75 0.24 955 + 957 3 202.187 -180.361 -12.75 0.24 956 + 958 3 202.187 -180.361 3.25 0.24 957 + 959 3 172.887 -117.12 12.25 0.24 936 + 960 3 177.874 -123.291 15 0.24 959 + 961 3 183.075 -127.121 15 0.24 960 + 962 3 189.924 -127.76 5.5 0.24 961 + 963 3 190.137 -127.76 5.25 0.24 962 + 964 3 197.824 -127.334 18.25 0.24 963 + 965 3 198.024 -127.334 16.25 0.24 964 + 966 3 201.974 -128.185 10 0.24 965 + 967 3 202.187 -128.185 9.75 0.24 966 + 968 3 204.887 -128.185 6.75 0.24 967 + 969 3 205.099 -127.973 6.75 0.24 968 + 970 3 209.874 -130.54 5.75 0.24 969 + 971 3 210.087 -130.54 6.25 0.24 970 + 972 3 218.599 -130.327 10.75 0.24 971 + 973 3 218.399 -130.327 10.5 0.24 972 + 974 3 226.499 -127.121 6.75 0.24 973 + 975 3 226.911 -127.121 10 0.24 974 + 976 3 83.95 -56.432 14.75 0.39 911 + 977 3 83.537 -57.07 14.75 0.39 976 + 978 3 57.562 -44.502 18.25 0.39 860 + 979 3 57.35 -44.502 18.25 0.39 978 + 980 3 57.975 -48.119 10.75 0.39 979 + 981 3 57.975 -48.332 11 0.39 980 + 982 3 57.35 -51.112 11.5 0.39 981 + 983 3 57.562 -51.538 11.75 0.39 982 + 984 3 57.762 -51.538 11.75 0.39 983 + 985 3 56.525 -59.198 20.75 0.24 984 + 986 3 55.275 -66.646 20.75 0.24 985 + 987 3 55.275 -66.859 20.75 0.24 986 + 988 3 54.237 -70.064 20.5 0.24 987 + 989 3 54.237 -70.277 20.5 0.24 988 + 990 3 55.9 -76.023 20.5 0.24 989 + 991 3 55.9 -76.236 20.5 0.24 990 + 992 3 55.9 -85.599 20.5 0.24 991 + 993 3 50.487 -93.579 6.5 0.24 992 + 994 3 51.311 -101.24 -3.25 0.24 993 + 995 3 51.311 -101.452 -3.5 0.24 994 + 996 3 52.362 -106.786 -7.25 0.24 995 + 997 3 52.149 -106.786 -7.5 0.24 996 + 998 3 50.075 -112.531 -9.5 0.24 997 + 999 3 53.812 -122.333 3 0.24 998 + 1000 3 56.512 -128.717 8.5 0.24 999 + 1001 3 56.512 -129.356 8.5 0.24 1000 + 1002 3 58.174 -131.697 13 0.24 1001 + 1003 3 56.725 -135.74 -3.75 0.24 1002 + 1004 3 56.725 -135.953 -4 0.24 1003 + 1005 3 60.462 -140.847 13.25 0.24 1004 + 1006 3 59.624 -149.372 11 0.24 1005 + 1007 3 58.999 -156.395 18 0.24 1006 + 1008 3 58.799 -156.608 18.25 0.24 1007 + 1009 3 58.799 -164.282 11.5 0.24 1008 + 1010 3 58.999 -164.707 -1.75 0.24 1009 + 1011 3 56.525 -91.783 12.25 0.24 992 + 1012 3 57.35 -97.103 11.25 0.24 1011 + 1013 3 55.687 -104.551 10.25 0.24 1012 + 1014 3 55.687 -104.764 10.25 0.24 1013 + 1015 3 55.062 -113.289 23 0.24 1014 + 1016 3 55.275 -113.289 23 0.24 1015 + 1017 3 54.863 -118.397 26.5 0.24 1016 + 1018 3 52.163 -127.76 14 0.24 1017 + 1019 3 51.112 -131.816 12.25 0.24 1018 + 1020 3 52.774 -141.605 10.5 0.24 1019 + 1021 3 52.774 -141.818 17.25 0.24 1020 + 1022 3 65.25 -63.029 11.5 0.24 983 + 1023 3 65.875 -67.71 17 0.24 1022 + 1024 3 65.875 -67.498 17 0.24 1023 + 1025 3 73.15 -77.3 9.25 0.24 1024 + 1026 3 73.35 -77.3 9.25 0.24 1025 + 1027 3 81.463 -85.386 9.25 0.24 1026 + 1028 3 81.662 -85.386 9.25 0.24 1027 + 1029 3 88.099 -95.188 9.25 0.24 1028 + 1030 3 97.037 -106.467 9 0.24 1029 + 1031 3 97.037 -106.679 9 0.24 1030 + 1032 3 100.162 -112.013 9 0.24 1031 + 1033 3 103.487 -115.417 9.75 0.24 1032 + 1034 3 103.275 -115.417 9.5 0.24 1033 + 1035 3 104.312 -121.801 9.25 0.24 1034 + 1036 3 108.475 -124.993 8.25 0.24 1035 + 1037 3 108.475 -124.781 8 0.24 1036 + 1038 3 111.374 -129.476 6.25 0.24 1037 + 1039 3 111.374 -129.688 6.25 0.24 1038 + 1040 3 119.274 -136.924 6 0.24 1039 + 1041 3 121.974 -143.52 4.95 0.24 1040 + 1042 3 121.775 -143.52 4.95 0.24 1041 + 1043 3 123.85 -146.287 4.95 0.24 1042 + 1044 3 124.049 -146.287 4.95 0.24 1043 + 1045 3 127.175 -153.11 4.95 0.24 1044 + 1046 3 134.237 -154.599 2.7 0.24 1045 + 1047 3 138.187 -162.473 7.2 0.24 1046 + 1048 3 141.924 -168.431 3.2 0.24 1047 + 1049 3 141.924 -168.657 3.2 0.24 1048 + 1050 3 151.075 -172.488 3.2 0.24 1049 + 1051 3 151.274 -172.488 2.95 0.24 1050 + 1052 3 151.075 -172.275 3.7 0.24 1051 + 1053 3 -0.032 -1.083 8.409 0.86 2 + 1054 3 1.424 -3.201 8.558 0.86 1053 + 1055 3 2.966 -5.678 8.701 0.86 1054 + 1056 3 5.4 -8.512 9 0.86 1055 + 1057 3 8.938 -12.569 9 0.86 1056 + 1058 3 11.85 -14.909 8 0.7 1057 + 1059 3 14.125 -17.037 3.75 0.7 1058 + 1060 3 13.712 -24.911 3.75 0.55 1059 + 1061 3 15.375 -27.89 2.25 0.55 1060 + 1062 3 15.588 -27.89 2.25 0.55 1061 + 1063 3 17.25 -31.734 1.5 0.55 1062 + 1064 3 18.7 -34.926 1 0.55 1063 + 1065 3 19.112 -38.331 1 0.39 1064 + 1066 3 20.575 -44.289 0.5 0.39 1065 + 1067 3 19.737 -47.268 0.5 0.39 1066 + 1068 3 20.987 -50.686 7.25 0.39 1067 + 1069 3 21.2 -50.474 7.5 0.39 1068 + 1070 3 18.288 -54.73 6.75 0.39 1069 + 1071 3 20.362 -64.731 8.75 0.39 1070 + 1072 3 23.475 -73.682 8.75 0.39 1071 + 1073 3 22.863 -78.151 7.25 0.39 1072 + 1074 3 22.863 -77.938 7.25 0.39 1073 + 1075 3 21.2 -81.13 5 0.39 1074 + 1076 3 22.025 -90.294 7.25 0.39 1075 + 1077 3 24.1 -92.209 8.75 0.39 1076 + 1078 3 24.1 -91.996 8.75 0.39 1077 + 1079 3 22.65 -94.55 8.75 0.39 1078 + 1080 3 23.275 -105.403 11 0.39 1079 + 1081 3 23.275 -105.615 11 0.39 1080 + 1082 3 24.725 -110.736 13.75 0.39 1081 + 1083 3 23.475 -118.822 13.75 0.24 1082 + 1084 3 23.475 -119.035 13.75 0.24 1083 + 1085 3 21.613 -124.568 13.75 0.24 1084 + 1086 3 21.4 -124.568 13.75 0.24 1085 + 1087 3 18.288 -127.973 18.75 0.24 1086 + 1088 3 14.55 -135.434 18.75 0.24 1087 + 1089 3 10.188 -143.52 18.75 0.24 1088 + 1090 3 10.188 -143.308 18.75 0.24 1089 + 1091 3 4.362 -150.769 19 0.24 1090 + 1092 3 4.362 -150.982 19 0.24 1091 + 1093 3 1.875 -155.238 20.25 0.24 1092 + 1094 3 -2.288 -162.047 11.75 0.24 1093 + 1095 3 -2.487 -162.047 11.25 0.24 1094 + 1096 3 -6.437 -166.942 10.75 0.24 1095 + 1097 3 -13.925 -174.829 7.75 0.24 1096 + 1098 3 -19.95 -181.213 3.5 0.24 1097 + 1099 3 -22.238 -183.766 3 0.24 1098 + 1100 3 -22.238 -183.553 3 0.24 1099 + 1101 3 -22.238 -183.341 3 0.24 1100 + 1102 3 -19.737 -186.958 5 0.24 1101 + 1103 3 -19.538 -186.958 5 0.24 1102 + 1104 3 -20.575 -189.312 4.75 0.24 1103 + 1105 3 -20.362 -193.355 4 0.24 1104 + 1106 3 -20.362 -193.568 4 0.24 1105 + 1107 3 -18.913 -195.696 1.5 0.24 1106 + 1108 3 -19.112 -199.101 -1.25 0.24 1107 + 1109 3 -19.112 -199.314 -1.25 0.24 1108 + 1110 3 -17.875 -202.08 -11 0.24 1109 + 1111 3 -18.075 -201.867 -11 0.24 1110 + 1112 3 -19.538 -203.144 -11.75 0.24 1111 + 1113 3 -19.325 -203.357 -12 0.24 1112 + 1114 3 -16.625 -205.485 -14.25 0.24 1113 + 1115 3 -16.412 -208.69 -14.25 0.24 1114 + 1116 3 -13.087 -212.521 -14.25 0.24 1115 + 1117 3 -13.3 -214.862 -15.75 0.24 1116 + 1118 3 -13.513 -214.862 -16 0.24 1117 + 1119 3 -11.85 -217.202 -17 0.24 1118 + 1120 3 -11.638 -217.202 -17 0.24 1119 + 1121 3 -12.263 -219.969 -18.25 0.24 1120 + 1122 3 -12.263 -220.182 -18.25 0.24 1121 + 1123 3 -12.05 -222.097 -20.25 0.24 1122 + 1124 3 -10.387 -223.374 -21.75 0.24 1123 + 1125 3 -10.387 -222.948 -22 0.24 1124 + 1126 3 -12.05 -224.863 -23 0.24 1125 + 1127 3 -12.05 -226.991 -24.5 0.24 1126 + 1128 3 -12.05 -229.984 -25.25 0.24 1127 + 1129 3 -12.675 -232.963 -25.75 0.24 1128 + 1130 3 -12.888 -232.963 -26 0.24 1129 + 1131 3 -14.55 -236.368 -28.5 0.24 1130 + 1132 3 -14.55 -236.58 -28.75 0.24 1131 + 1133 3 -15.787 -238.283 -31 0.24 1132 + 1134 3 -11.85 -246.582 -32 0.24 1133 + 1135 3 -11.85 -246.795 -32 0.24 1134 + 1136 3 -11.225 -247.433 -31.5 0.24 1135 + 1137 1 0.313 -9.905 4.469 6.961 1 + 1138 1 0.469 -12.301 4.359 4.681 1137 + 1139 3 -0.684 -10.165 7.945 0.86 1137 + 1140 3 -2.913 -11.505 7.5 0.86 1139 + 1141 3 -11.425 -17.25 7.5 0.86 1140 + 1142 3 -11.638 -17.037 7.5 0.86 1141 + 1143 3 -17.45 -22.783 13.25 0.86 1142 + 1144 3 -17.45 -22.996 13.25 0.86 1143 + 1145 3 -19.737 -25.762 6 0.86 1144 + 1146 3 -19.737 -25.549 6.5 0.86 1145 + 1147 3 -19.95 -31.095 6.75 0.86 1146 + 1148 3 -20.987 -32.585 8 0.86 1147 + 1149 3 -23.275 -34.926 11 0.7 1148 + 1150 3 -23.475 -35.139 11 0.7 1149 + 1151 3 -27.637 -40.671 13.75 0.7 1150 + 1152 3 -31.375 -44.289 16.5 0.7 1151 + 1153 3 -35.95 -46.204 16.5 0.55 1152 + 1154 3 -36.987 -48.758 19 0.55 1153 + 1155 3 -43.225 -54.304 19.25 0.39 1154 + 1156 3 -43.225 -54.091 19.25 0.39 1155 + 1157 3 -46.962 -63.029 20.5 0.39 1156 + 1158 3 -46.962 -63.242 20.5 0.39 1157 + 1159 3 -49.662 -68.349 23.5 0.39 1158 + 1160 3 -54.237 -76.236 22 0.39 1159 + 1161 3 -54.025 -76.236 21.75 0.39 1160 + 1162 3 -54.863 -76.874 16.75 0.39 1161 + 1163 3 -54.863 -76.661 16.75 0.39 1162 + 1164 3 -64.412 -82.62 10.25 0.39 1163 + 1165 3 -64.625 -82.62 10.25 0.39 1164 + 1166 3 -72.312 -89.216 10.25 0.39 1165 + 1167 3 -78.962 -95.827 10.25 0.39 1166 + 1168 3 -80.837 -97.529 16.5 0.39 1167 + 1169 3 -81.037 -97.529 16.5 0.39 1168 + 1170 3 -88.724 -104.339 12.25 0.39 1169 + 1171 3 -97.25 -112.225 14.75 0.39 1170 + 1172 3 -105.562 -119.248 4.25 0.39 1171 + 1173 3 -105.562 -119.461 4.25 0.39 1172 + 1174 3 -112.624 -126.909 4.25 0.39 1173 + 1175 3 -120.937 -136.072 4.25 0.39 1174 + 1176 3 -121.15 -136.072 4.25 0.39 1175 + 1177 3 -125.299 -142.031 4.25 0.39 1176 + 1178 3 -136.525 -158.855 4.25 0.39 1177 + 1179 3 -142.137 -164.601 6.75 0.39 1178 + 1180 3 -145.037 -169.509 4.5 0.39 1179 + 1181 3 -145.037 -169.721 4.5 0.39 1180 + 1182 3 -149.612 -179.936 3.5 0.39 1181 + 1183 3 -153.775 -186.32 0.5 0.39 1182 + 1184 3 -158.549 -198.463 0.5 0.24 1183 + 1185 3 -158.762 -198.463 0.5 0.24 1184 + 1186 3 -163.537 -206.336 0.5 0.24 1185 + 1187 3 -171.224 -217.628 0.25 0.24 1186 + 1188 3 -172.887 -220.394 -8.75 0.24 1187 + 1189 3 -172.674 -220.394 -8.75 0.24 1188 + 1190 3 -173.1 -221.458 -8.75 0.24 1189 + 1191 3 -53.612 -84.109 8.5 0.24 1162 + 1192 3 -53.4 -88.791 8.5 0.24 1191 + 1193 3 -53.4 -89.004 8.5 0.24 1192 + 1194 3 -51.737 -98.167 8.5 0.24 1193 + 1195 3 -52.987 -104.764 8.5 0.24 1194 + 1196 3 -52.987 -109.885 4.75 0.24 1195 + 1197 3 -52.987 -109.672 4.75 0.24 1196 + 1198 3 -56.937 -118.184 4 0.24 1197 + 1199 3 -57.762 -124.355 9.25 0.24 1198 + 1200 3 -57.762 -124.568 9.25 0.24 1199 + 1201 3 -59.424 -133.093 9.25 0.24 1200 + 1202 3 -59.424 -133.306 9.25 0.24 1201 + 1203 3 -60.675 -141.818 8.5 0.24 1202 + 1204 3 -61.513 -149.918 5.75 0.24 1203 + 1205 3 -63.175 -157.578 11.75 0.24 1204 + 1206 3 -62.962 -157.366 11.75 0.24 1205 + 1207 3 -62.55 -158.217 8.25 0.24 1206 + 1208 3 -19.325 -37.905 7.5 0.86 1148 + 1209 3 -20.775 -45.353 -0.5 0.7 1208 + 1210 3 -20.775 -45.566 0.5 0.7 1209 + 1211 3 -19.538 -51.112 14.25 0.7 1210 + 1212 3 -18.5 -57.709 18.25 0.7 1211 + 1213 3 -18.288 -61.326 17.75 0.7 1212 + 1214 3 -18.075 -65.157 17.75 0.7 1213 + 1215 3 -17.875 -65.157 17.75 0.7 1214 + 1216 3 -17.037 -70.064 17.75 0.7 1215 + 1217 3 -13.925 -71.98 14.25 0.7 1216 + 1218 3 -9.563 -71.554 22.5 0.7 1217 + 1219 3 -5.4 -68.562 22.5 0.7 1218 + 1220 3 -5.2 -68.349 22.5 0.7 1219 + 1221 3 -5.2 -68.136 22.5 0.7 1220 + 1222 3 -4.775 -68.349 23.25 0.7 1221 + 1223 3 -23.541 -80.385 23.25 0.55 1222 + 1224 3 -23.541 -80.172 23.25 0.55 1223 + 1225 3 -23.953 -82.939 23.25 0.55 1224 + 1226 3 -24.166 -83.364 23.25 0.39 1225 + 1227 3 -22.716 -84.641 23.25 0.39 1226 + 1228 3 -21.253 -88.472 18.5 0.39 1227 + 1229 3 -21.466 -88.472 18.5 0.39 1228 + 1230 3 -15.854 -93.592 18.5 0.39 1229 + 1231 3 -10.241 -101.679 18.5 0.39 1230 + 1232 3 -8.166 -105.509 18.5 0.39 1231 + 1233 3 -4.429 -108.914 18.5 0.24 1232 + 1234 3 -4.216 -108.914 18.5 0.24 1233 + 1235 3 -3.804 -111.693 18.5 0.24 1234 + 1236 3 1.596 -121.482 18.5 0.24 1235 + 1237 3 2.221 -128.079 18.5 0.24 1236 + 1238 3 3.471 -136.392 17.75 0.24 1237 + 1239 3 4.722 -145.968 17.75 0.24 1238 + 1240 3 7.834 -154.067 25.75 0.24 1239 + 1241 3 8.459 -160.664 25.5 0.24 1240 + 1242 3 12.196 -164.494 23 0.24 1241 + 1243 3 13.234 -173.02 22.5 0.24 1242 + 1244 3 13.446 -173.02 22.5 0.24 1243 + 1245 3 16.146 -178.765 20.25 0.24 1244 + 1246 3 21.759 -180.681 18.5 0.24 1245 + 1247 3 21.958 -180.681 19.5 0.24 1246 + 1248 3 27.159 -182.383 30.75 0.24 1247 + 1249 3 26.946 -182.383 30.75 0.24 1248 + 1250 3 27.571 -182.17 23.5 0.24 1249 + 1251 3 -5.666 -115.098 22.25 0.24 1232 + 1252 3 -5.666 -123.61 17 0.24 1251 + 1253 3 -5.666 -123.397 17 0.24 1252 + 1254 3 -6.091 -132.987 15.75 0.24 1253 + 1255 3 -7.328 -144.052 22.75 0.24 1254 + 1256 3 -7.328 -144.265 22.5 0.24 1255 + 1257 3 -7.328 -149.386 19.75 0.24 1256 + 1258 3 -7.541 -149.386 19.5 0.24 1257 + 1259 3 -4.216 -159.813 18 0.24 1258 + 1260 3 -2.966 -168.75 26.25 0.24 1259 + 1261 3 -2.966 -172.807 22.5 0.24 1260 + 1262 3 -2.766 -172.807 23 0.24 1261 + 1263 3 -5.666 -181.745 22 0.24 1262 + 1264 3 -5.879 -181.532 33.5 0.24 1263 + 1265 3 -25.616 -86.769 31 0.39 1226 + 1266 3 -24.578 -88.684 25.5 0.39 1265 + 1267 3 -26.653 -91.89 30.75 0.39 1266 + 1268 3 -27.903 -97.848 31.75 0.39 1267 + 1269 3 -28.116 -97.848 31.75 0.39 1268 + 1270 3 -28.941 -99.976 33.25 0.39 1269 + 1271 3 -27.491 -104.871 35.5 0.39 1270 + 1272 3 -27.278 -104.871 35.5 0.39 1271 + 1273 3 -29.154 -113.396 38.75 0.24 1272 + 1274 3 -30.191 -118.716 42.75 0.24 1273 + 1275 3 -33.104 -125.738 30.25 0.24 1274 + 1276 3 -37.253 -135.966 39.5 0.24 1275 + 1277 3 -39.754 -141.073 35 0.24 1276 + 1278 3 -43.278 -145.968 23.25 0.24 1277 + 1279 3 -45.366 -150.662 33.75 0.24 1278 + 1280 3 -51.591 -157.046 31.25 0.24 1279 + 1281 3 -58.241 -161.941 31.5 0.24 1280 + 1282 3 -58.241 -162.154 31.5 0.24 1281 + 1283 3 -68.216 -168.325 35.5 0.24 1282 + 1284 3 -68.934 -174.922 31.25 0.24 1283 + 1285 3 -69.147 -174.922 31.25 0.24 1284 + 1286 3 -68.934 -178.326 21.25 0.24 1285 + 1287 3 -72.671 -183.434 27.5 0.24 1286 + 1288 3 -80.784 -187.277 27.5 0.24 1287 + 1289 3 -80.984 -187.277 27.5 0.24 1288 + 1290 3 -87.221 -192.81 24.75 0.24 1289 + 1291 3 -88.472 -198.769 26.75 0.24 1290 + 1292 3 -88.671 -198.769 26.5 0.24 1291 + 1293 3 -91.797 -201.322 18 0.24 1292 + 1294 3 -91.584 -201.109 19 0.24 1293 + 1295 3 -91.797 -201.322 31.75 0.24 1294 + 1296 3 -76.941 -173.445 40 0.24 1283 + 1297 3 -84.016 -174.722 42.25 0.24 1296 + 1298 3 -84.216 -174.722 43 0.24 1297 + 1299 3 -90.241 -178.127 45.75 0.24 1298 + 1300 3 -93.153 -180.042 31.5 0.24 1299 + 1301 3 -102.503 -182.383 41.5 0.24 1300 + 1302 3 -107.703 -185.575 35.75 0.24 1301 + 1303 3 -114.553 -187.916 42.5 0.24 1302 + 1304 3 -114.766 -187.916 43.25 0.24 1303 + 1305 3 -19.391 -82.939 33 0.39 1224 + 1306 3 -18.354 -85.705 33 0.39 1305 + 1307 3 -18.141 -85.918 33 0.39 1306 + 1308 3 -18.354 -89.536 33 0.39 1307 + 1309 3 -18.354 -89.762 33 0.39 1308 + 1310 3 -17.729 -94.23 36.5 0.39 1309 + 1311 3 -17.516 -94.23 36.5 0.39 1310 + 1312 3 -18.141 -96.997 39 0.39 1311 + 1313 3 -15.229 -102.53 34.5 0.39 1312 + 1314 3 -15.229 -102.317 34.75 0.39 1313 + 1315 3 -16.479 -104.871 41 0.39 1314 + 1316 3 -15.029 -105.509 47.75 0.39 1315 + 1317 3 -14.603 -109.991 48.25 0.39 1316 + 1318 3 -14.404 -109.991 48.75 0.39 1317 + 1319 3 -13.978 -109.991 56.25 0.39 1318 + 1320 3 -13.566 -115.524 49.25 0.24 1319 + 1321 3 -15.641 -120.844 46.75 0.24 1320 + 1322 3 -17.928 -127.228 45.5 0.24 1321 + 1323 3 -18.141 -127.228 45.5 0.24 1322 + 1324 3 -20.628 -132.348 44 0.24 1323 + 1325 3 -22.916 -136.817 40.75 0.24 1324 + 1326 3 -27.491 -143.414 54.75 0.24 1325 + 1327 3 -29.366 -148.308 54 0.24 1326 + 1328 3 -29.366 -148.521 53.75 0.24 1327 + 1329 3 -35.591 -154.493 49.25 0.24 1328 + 1330 3 -35.591 -154.706 49 0.24 1329 + 1331 3 -41.004 -159.387 46.5 0.24 1330 + 1332 3 -41.004 -159.6 46.25 0.24 1331 + 1333 3 -41.203 -159.6 46.75 0.24 1332 + 1334 3 -54.53 -177.223 46.45 0.24 1333 + 1335 3 -57.03 -182.13 42.2 0.24 1334 + 1336 3 -59.318 -189.365 35.95 0.24 1335 + 1337 3 -59.318 -189.578 35.95 0.24 1336 + 1338 3 -62.231 -198.104 35.7 0.24 1337 + 1339 3 -67.005 -209.169 32.7 0.24 1338 + 1340 3 -70.118 -217.482 27.7 0.24 1339 + 1341 3 -70.33 -217.482 27.2 0.24 1340 + 1342 3 -72.192 -222.376 22.7 0.24 1341 + 1343 3 -77.393 -229.398 22.2 0.24 1342 + 1344 3 -77.606 -229.398 21.45 0.24 1343 + 1345 3 -80.718 -233.016 17.95 0.24 1344 + 1346 3 -82.38 -238.137 11.2 0.24 1345 + 1347 3 -82.593 -238.137 11.95 0.24 1346 + 1348 3 -88.618 -243.457 9.95 0.24 1347 + 1349 3 -93.393 -246.223 11.45 0.24 1348 + 1350 3 -99.005 -247.713 2.95 0.24 1349 + 1351 3 -99.218 -247.713 3.95 0.24 1350 + 1352 3 -100.255 -247.713 8.45 0.24 1351 + 1353 3 -11.278 -107.637 53.75 0.39 1319 + 1354 3 -12.941 -112.119 57.75 0.39 1353 + 1355 3 -11.278 -114.46 58 0.39 1354 + 1356 3 -11.079 -114.46 58 0.39 1355 + 1357 3 -11.491 -116.375 59.25 0.39 1356 + 1358 3 -11.704 -116.375 59.25 0.39 1357 + 1359 3 -10.454 -119.567 60 0.39 1358 + 1360 3 -11.079 -122.121 56.75 0.39 1359 + 1361 3 -11.491 -121.695 45.75 0.24 1360 + 1362 3 -14.75 -62.603 17.75 0.7 1213 + 1363 3 -14.75 -62.39 18 0.7 1362 + 1364 3 -10.188 -60.688 19.25 0.7 1363 + 1365 3 -9.975 -60.475 19.25 0.7 1364 + 1366 3 -5.613 -56.219 20.25 0.7 1365 + 1367 3 -5.613 -55.581 20.75 0.7 1366 + 1368 3 -4.988 -48.545 21.75 0.7 1367 + 1369 3 -4.988 -48.332 21.75 0.7 1368 + 1370 3 -4.775 -48.332 22 0.7 1369 + 1371 3 0.014 -6.367 3.236 0.7 1 + 1372 3 -1.057 -8.03 2.928 0.7 1371 + 1373 3 -4.15 -10.015 2.25 0.7 1372 + 1374 3 -6.025 -14.697 2.25 0.7 1373 + 1375 3 -7.475 -17.463 -1.5 0.7 1374 + 1376 3 -11.012 -23.847 -4.75 0.7 1375 + 1377 3 -10.8 -23.847 -4.75 0.7 1376 + 1378 3 -13.712 -30.883 -7.25 0.7 1377 + 1379 3 -13.513 -30.883 -7.5 0.7 1378 + 1380 3 -16 -35.351 0.5 0.7 1379 + 1381 3 -22.65 -43.012 -4.75 0.7 1380 + 1382 3 -25.35 -45.991 -3 0.7 1381 + 1383 3 -33.45 -56.219 -12 0.55 1382 + 1384 3 -34.075 -58.347 -11 0.55 1383 + 1385 3 -34.075 -58.134 -11 0.55 1384 + 1386 3 -42.188 -63.242 -11.25 0.39 1385 + 1387 3 -46.962 -68.774 -11.5 0.39 1386 + 1388 3 -51.112 -75.81 -11.5 0.39 1387 + 1389 3 -51.325 -75.81 -11.5 0.39 1388 + 1390 3 -56.099 -79.64 -11.5 0.39 1389 + 1391 3 -61.925 -84.748 -11 0.39 1390 + 1392 3 -66.5 -90.932 -11 0.39 1391 + 1393 3 -73.562 -99.657 -13.5 0.39 1392 + 1394 3 -73.762 -99.87 -13.5 0.39 1393 + 1395 3 -74.813 -100.934 -15.25 0.39 1394 + 1396 3 -81.662 -102.423 -10.75 0.39 1395 + 1397 3 -87.062 -105.615 -9.75 0.39 1396 + 1398 3 -88.432 -111.388 20.75 0.39 1397 + 1399 3 -88.432 -111.175 20.75 0.39 1398 + 1400 3 -86.769 -115.644 30 0.39 1399 + 1401 3 -86.982 -115.644 30 0.39 1400 + 1402 3 -86.57 -122.24 34.5 0.24 1401 + 1403 3 -86.57 -130.553 25.5 0.24 1402 + 1404 3 -86.57 -130.34 25.75 0.24 1403 + 1405 3 -88.645 -138.001 26.5 0.24 1404 + 1406 3 -90.719 -146.526 24 0.24 1405 + 1407 3 -92.382 -153.761 34.5 0.24 1406 + 1408 3 -93.22 -158.869 31.75 0.24 1407 + 1409 3 -96.744 -165.904 29 0.24 1408 + 1410 3 -98.819 -170.799 22.75 0.24 1409 + 1411 3 -99.032 -170.799 23 0.24 1410 + 1412 3 -101.732 -176.97 32.5 0.24 1411 + 1413 3 -103.195 -180.587 33.25 0.24 1412 + 1414 3 -103.195 -180.375 33.5 0.24 1413 + 1415 3 -108.595 -185.282 34.75 0.24 1414 + 1416 3 -108.794 -185.495 34.75 0.24 1415 + 1417 3 -113.582 -190.602 37.75 0.24 1416 + 1418 3 -113.156 -191.028 33 0.24 1417 + 1419 3 -87.275 -105.615 -9.75 0.39 1397 + 1420 3 -92.887 -108.169 -2 0.39 1419 + 1421 3 -97.037 -114.141 -2 0.39 1420 + 1422 3 -105.15 -122.227 -5 0.39 1421 + 1423 3 -111.175 -131.391 -6 0.39 1422 + 1424 3 -111.175 -131.604 -6 0.39 1423 + 1425 3 -116.162 -139.052 -6.25 0.39 1424 + 1426 3 -119.687 -146.074 -6.25 0.39 1425 + 1427 3 -125.299 -155.025 -15 0.24 1426 + 1428 3 -128.425 -162.473 -13.75 0.24 1427 + 1429 3 -130.912 -169.083 -18.25 0.24 1428 + 1430 3 -131.125 -169.296 -18.25 0.24 1429 + 1431 3 -134.649 -175.68 -12 0.24 1430 + 1432 3 -141.1 -183.979 -13.75 0.24 1431 + 1433 3 -141.1 -184.192 -13.75 0.24 1432 + 1434 3 -141.512 -184.617 -6.25 0.24 1433 + 1435 3 -77.925 -106.679 -13.75 0.39 1395 + 1436 3 -77.925 -106.467 -13.75 0.39 1435 + 1437 3 -78.962 -107.105 -13.25 0.39 1436 + 1438 3 -78.962 -106.892 -13.25 0.39 1437 + 1439 3 -80.625 -111.161 -13.25 0.39 1438 + 1440 3 -84.575 -116.269 -16.5 0.24 1439 + 1441 3 -89.762 -121.589 -16.5 0.24 1440 + 1442 3 -89.975 -121.589 -16.5 0.24 1441 + 1443 3 -96.625 -124.993 -16.5 0.24 1442 + 1444 3 -99.537 -129.476 -19.75 0.24 1443 + 1445 3 -99.537 -129.688 -19.75 0.24 1444 + 1446 3 -103.9 -135.221 -19.75 0.24 1445 + 1447 3 -110.55 -140.541 -15.25 0.24 1446 + 1448 3 -116.987 -141.18 -15 0.24 1447 + 1449 3 -119.687 -144.159 -18.5 0.24 1448 + 1450 3 -122.187 -146.712 -13.25 0.24 1449 + 1451 3 -125.924 -149.279 -22.25 0.24 1450 + 1452 3 -134.237 -156.089 -16.75 0.24 1451 + 1453 3 -134.45 -156.089 -16.75 0.24 1452 + 1454 3 -142.549 -162.686 -17 0.24 1453 + 1455 3 -142.549 -162.898 -17 0.24 1454 + 1456 3 -149.199 -171.211 -17.25 0.24 1455 + 1457 3 -149.412 -171.424 -17.25 0.24 1456 + 1458 3 -154.812 -176.957 -20 0.24 1457 + 1459 3 -161.036 -184.83 -25 0.24 1458 + 1460 3 -164.787 -190.802 -28.75 0.24 1459 + 1461 3 -164.787 -191.015 -28.75 0.24 1460 + 1462 3 -171.637 -200.803 -32.25 0.24 1461 + 1463 3 -174.962 -205.485 -33.75 0.24 1462 + 1464 3 -183.686 -212.521 -33.75 0.24 1463 + 1465 3 -183.899 -212.521 -33.75 0.24 1464 + 1466 3 -190.137 -220.394 -36.75 0.24 1465 + 1467 3 -197.412 -226.353 -38.25 0.24 1466 + 1468 3 -197.412 -226.14 -38.25 0.24 1467 + 1469 3 -197.199 -226.353 -7 0.24 1468 + 1470 3 -84.788 -118.822 -10.25 0.24 1437 + 1471 3 -87.062 -126.696 -12 0.24 1470 + 1472 3 -91.424 -135.434 -3.5 0.24 1471 + 1473 3 -91.637 -135.434 -3.5 0.24 1472 + 1474 3 -95.175 -146.925 -3.25 0.24 1473 + 1475 3 -98.5 -154.599 -3.25 0.24 1474 + 1476 3 -105.15 -164.814 -11.25 0.24 1475 + 1477 3 -107.225 -169.083 -4.5 0.24 1476 + 1478 3 -107.225 -169.296 -4.5 0.24 1477 + 1479 3 -110.337 -182.064 -3 0.24 1478 + 1480 3 -110.337 -182.277 -2.75 0.24 1479 + 1481 3 -112.624 -186.958 -1.75 0.24 1480 + 1482 3 -117.612 -193.568 -3.25 0.24 1481 + 1483 3 -121.15 -200.378 -2.75 0.24 1482 + 1484 3 -125.512 -205.485 -2.5 0.24 1483 + 1485 3 -125.512 -205.272 -2.25 0.24 1484 + 1486 3 -127.374 -211.882 -9.5 0.24 1485 + 1487 3 -131.949 -221.458 -4.25 0.24 1486 + 1488 3 -131.949 -221.246 -4.25 0.24 1487 + 1489 3 -132.162 -221.671 -1 0.24 1488 + 1490 3 -131.949 -221.458 -0.75 0.24 1489 + 1491 3 -134.237 -226.778 -10.25 0.24 1490 + 1492 3 -139.437 -235.516 -15.5 0.24 1491 + 1493 3 -139.437 -235.729 -15.5 0.24 1492 + 1494 3 -139.637 -236.58 -15.25 0.24 1493 + 1495 3 -133.2 -222.735 11.5 0.24 1489 + 1496 3 -133.2 -222.522 9.5 0.24 1495 + 1497 3 -140.475 -228.068 -3.5 0.24 1496 + 1498 3 -140.674 -228.068 -3.5 0.24 1497 + 1499 3 -146.287 -235.304 -10.25 0.24 1498 + 1500 3 -146.087 -235.304 -10.25 0.24 1499 + 1501 3 -146.087 -235.729 -9 0.24 1500 + 1502 3 -35.325 -67.072 -12.5 0.39 1384 + 1503 3 -35.325 -67.285 -12.75 0.39 1502 + 1504 3 -35.112 -74.746 -11 0.39 1503 + 1505 3 -36.163 -82.62 -15.25 0.24 1504 + 1506 3 -36.163 -82.832 -15.25 0.24 1505 + 1507 3 -40.725 -93.06 -16.75 0.24 1506 + 1508 3 -45.087 -102.849 -16 0.24 1507 + 1509 3 -45.3 -107.743 -21.75 0.24 1508 + 1510 3 -45.3 -107.531 -22 0.24 1509 + 1511 3 -46.962 -115.205 -24.25 0.24 1510 + 1512 3 -49.037 -123.929 -26.5 0.24 1511 + 1513 3 -49.037 -124.142 -26.5 0.24 1512 + 1514 3 -51.95 -129.901 -31 0.24 1513 + 1515 3 -52.163 -129.901 -31 0.24 1514 + 1516 3 -55.488 -135.647 -34.75 0.24 1515 + 1517 3 -55.687 -135.647 -34.75 0.24 1516 + 1518 3 -55.9 -136.072 -11 0.24 1517 + 1519 3 -68.841 -137.668 -11.25 0.24 1518 + 1520 3 -77.566 -136.817 -4.75 0.24 1519 + 1521 3 -77.778 -136.817 -6 0.24 1520 + 1522 3 -83.391 -137.03 -6.75 0.24 1521 + 1523 3 -86.503 -140.86 -1.75 0.24 1522 + 1524 3 -86.716 -140.86 -1.75 0.24 1523 + 1525 3 -89.416 -145.542 -19.25 0.24 1524 + 1526 3 -89.615 -145.542 -19.25 0.24 1525 + 1527 3 -93.153 -150.024 -18.75 0.24 1526 + 1528 3 -93.366 -150.024 -18.75 0.24 1527 + 1529 3 -96.265 -152.152 -18.75 0.24 1528 + 1530 3 -98.553 -153.003 -24.25 0.24 1529 + 1531 3 -98.354 -153.216 -24.5 0.24 1530 + 1532 3 -99.178 -158.536 -19.75 0.24 1531 + 1533 3 -101.053 -160.877 -16.5 0.24 1532 + 1534 3 -101.053 -161.09 -18.25 0.24 1533 + 1535 3 -104.791 -162.792 -28.5 0.24 1534 + 1536 3 -105.004 -162.792 -28.5 0.24 1535 + 1537 3 -108.954 -169.615 -32.75 0.24 1536 + 1538 3 -110.403 -172.807 -29.75 0.24 1537 + 1539 3 -110.616 -173.02 -29.75 0.24 1538 + 1540 3 -114.979 -176.212 -32.75 0.24 1539 + 1541 3 -114.979 -176.425 -32.75 0.24 1540 + 1542 3 -117.678 -179.191 -37 0.24 1541 + 1543 3 -119.966 -183.66 -40 0.24 1542 + 1544 3 -124.741 -189.419 -27.75 0.24 1543 + 1545 3 -127.653 -192.398 -30 0.24 1544 + 1546 3 -130.353 -196.654 -29.25 0.24 1545 + 1547 3 -132.016 -198.782 -47.25 0.24 1546 + 1548 3 -132.016 -199.207 -31 0.24 1547 + 1549 3 -24.938 -50.261 -6.75 0.55 1382 + 1550 3 -25.762 -53.878 -13.25 0.39 1549 + 1551 3 -25.137 -61.965 -15 0.39 1550 + 1552 3 -27.012 -70.49 -15 0.39 1551 + 1553 3 -29.925 -79.215 -15.75 0.39 1552 + 1554 3 -30.337 -83.684 -12 0.39 1553 + 1555 3 -27.637 -88.791 -14.75 0.39 1554 + 1556 3 -25.563 -88.152 -17.75 0.39 1555 + 1557 3 -25.762 -88.152 -17.75 0.39 1556 + 1558 3 -29.3 -91.571 -22.25 0.39 1557 + 1559 3 -27.225 -99.87 -24.25 0.39 1558 + 1560 3 -25.563 -104.339 -26.25 0.39 1559 + 1561 3 -25.762 -104.339 -26.25 0.39 1560 + 1562 3 -27.637 -111.161 -25.25 0.24 1561 + 1563 3 -27.637 -111.374 -25.25 0.24 1562 + 1564 3 -24.525 -119.673 -25.75 0.24 1563 + 1565 3 -24.525 -119.886 -25.75 0.24 1564 + 1566 3 -21.825 -128.398 -25 0.24 1565 + 1567 3 -18.5 -137.136 -26.75 0.39 1566 + 1568 3 -18.288 -137.988 -26.25 0.39 1567 + 1569 3 -18.288 -137.988 -26.5 0.39 1568 + 1570 3 -17.25 -143.52 -25.5 0.39 1569 + 1571 3 -16.838 -156.94 -29 0.39 1570 + 1572 3 -16.412 -160.558 -36 0.39 1571 + 1573 3 -13.087 -174.403 -36 0.39 1572 + 1574 3 -12.888 -191.227 -31.75 0.39 1573 + 1575 3 -13.087 -191.866 -32 0.39 1574 + 1576 3 -13.087 -191.653 -32 0.39 1575 + 1577 3 -12.263 -196.335 -34.5 0.24 1576 + 1578 3 -11.012 -209.116 -36 0.24 1577 + 1579 3 -7.475 -218.479 -32.75 0.24 1578 + 1580 3 -8.1 -224.65 -28 0.24 1579 + 1581 3 -5.4 -228.92 -29.75 0.24 1580 + 1582 3 -5.613 -228.494 -29.75 0.24 1581 + 1583 3 -5.812 -228.281 -29.75 0.24 1582 + 1584 3 -5.4 -228.92 -31.75 0.24 1583 + 1585 3 -14.337 -196.76 -32.25 0.24 1575 + 1586 3 -15.375 -201.655 -34.5 0.24 1585 + 1587 3 -15.787 -208.265 -37 0.24 1586 + 1588 3 -16 -208.265 -37 0.24 1587 + 1589 3 -16.625 -217.841 -31.5 0.24 1588 + 1590 3 -18.075 -226.566 -36.25 0.24 1589 + 1591 3 -17.875 -226.778 -36.25 0.24 1590 + 1592 3 -18.5 -237.857 -37.25 0.24 1591 + 1593 3 -14.963 -246.156 -38 0.24 1592 + 1594 3 -14.963 -245.944 -38 0.24 1593 + 1595 3 -14.75 -245.944 -36.75 0.24 1594 + 1596 3 -19.538 -144.372 -28.25 0.24 1568 + 1597 3 -19.737 -144.372 -28.25 0.24 1596 + 1598 3 -20.163 -152.471 -28.75 0.24 1597 + 1599 3 -19.112 -156.727 -31.5 0.24 1598 + 1600 3 -18.075 -161.196 -33 0.24 1599 + 1601 3 -18.913 -167.793 -32.5 0.24 1600 + 1602 3 -18.913 -168.218 -22.25 0.24 1601 diff --git a/tests/swc/l22_cvapp.morph.nml b/tests/swc/l22_cvapp.morph.nml new file mode 100644 index 00000000..a0fce9a8 --- /dev/null +++ b/tests/swc/l22_cvapp.morph.nml @@ -0,0 +1,10390 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: l22.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/l22_cylsoma.swc b/tests/swc/l22_cylsoma.swc new file mode 100644 index 00000000..6108e670 --- /dev/null +++ b/tests/swc/l22_cylsoma.swc @@ -0,0 +1,26 @@ +# Original file l22.swc edited by Duncan Donohue using StdSwc version 1.21 on 7/25/05. +# Irregularities and fixes documented in l22.swc.std. See StdSwc1.21.doc for more information. +# +# ORIGINAL_SOURCE Neurolucida +# CREATURE rat F344 +# REGION Hippocampus +# FIELD/LAYER CA3 +# TYPE CA3c Pyramidal Cell in vivo young +# CONTRIBUTOR Buzsaki_G & Turner_DA +# REFERENCE J. Comp. Neurol. 356: 580-594, 1995 +# RAW l22.asc +# EXTRAS Turner_P.CA3 +# SOMA_AREA 0.98E3 +# SHRINKAGE_CORRECTION 1.33 1.33 2.5 +# VERSION_NUMBER 2.0 +# VERSION_DATE 1998-03-27 +# ********************************************* +# SCALE 1.33 1.33 2.5 +# + + 1 1 -2.913 28.103 10.7 3.42 -1 + 2 1 -13.112 30.457 13.2 1 1 + 3 3 -3.112 40.457 13.2 1 2 + 4 3 -3.112 50.457 13.2 1 3 + 5 3 -13.112 60.457 13.2 0.3 4 + 6 3 3.112 60.457 13.2 0.3 4 diff --git a/tests/swc/l22_cylsoma_cvapp.morph.nml b/tests/swc/l22_cylsoma_cvapp.morph.nml new file mode 100644 index 00000000..8a0079db --- /dev/null +++ b/tests/swc/l22_cylsoma_cvapp.morph.nml @@ -0,0 +1,92 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: l22_cylsoma.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/l22_small.swc b/tests/swc/l22_small.swc new file mode 100644 index 00000000..0fef8409 --- /dev/null +++ b/tests/swc/l22_small.swc @@ -0,0 +1,52 @@ +# Original file l22.swc edited by Duncan Donohue using StdSwc version 1.21 on 7/25/05. +# Irregularities and fixes documented in l22.swc.std. See StdSwc1.21.doc for more information. +# +# ORIGINAL_SOURCE Neurolucida +# CREATURE rat F344 +# REGION Hippocampus +# FIELD/LAYER CA3 +# TYPE CA3c Pyramidal Cell in vivo young +# CONTRIBUTOR Buzsaki_G & Turner_DA +# REFERENCE J. Comp. Neurol. 356: 580-594, 1995 +# RAW l22.asc +# EXTRAS Turner_P.CA3 +# SOMA_AREA 0.98E3 +# SHRINKAGE_CORRECTION 1.33 1.33 2.5 +# VERSION_NUMBER 2.0 +# VERSION_DATE 1998-03-27 +# ********************************************* +# SCALE 1.33 1.33 2.5 +# + 1 1 0 -5.114 4.688 7.843 -1 + 2 1 -0.313 -0.323 4.906 7.645 1 + 3 1 -0.625 4.469 5.125 5.932 2 + 4 1 -0.938 9.26 5.344 4.287 3 + 5 1 -1.25 14.051 5.562 3.303 4 + 6 1 -1.563 18.843 5.781 2.833 5 + 7 1 -1.875 23.634 6 2.73 6 + 8 1 -2.913 28.103 10.7 2.42 7 + 9 4 -3.112 30.457 13.2 2.42 8 + 10 4 -3.325 30.457 13.2 2.42 9 + 11 4 0.825 34.287 14.2 1.33 10 + 12 4 1.663 39.607 13.95 1.33 11 + 13 4 2.487 44.076 10.95 1.02 12 + 14 4 4.575 50.686 9.7 1.02 13 + 15 4 5.812 52.814 9.95 1.02 14 + 16 4 3.538 57.922 14.45 0.55 15 + 17 4 0.213 66.008 14.45 0.55 16 + 18 4 0 66.008 14.45 0.55 17 + 19 4 -3.95 74.32 14.45 0.55 18 + 20 4 -3.95 74.533 14.45 0.55 19 + 21 4 -4.15 80.917 12.7 0.55 20 + 22 4 1.955 88.219 10.25 0.24 21 + 23 4 3.405 92.262 10.25 0.24 22 + 24 4 4.03 93.113 10.25 0.24 23 + 25 4 5.48 107.384 9.75 0.24 24 + 26 4 5.48 108.023 9.75 0.24 25 + 27 4 12.13 117.173 9.75 0.24 26 + 28 4 12.342 117.811 9.75 0.24 27 + 29 4 16.492 126.55 9.75 0.24 28 + 30 4 16.918 127.401 9.75 0.24 29 + 31 4 19.817 131.87 9.75 0.24 30 + 32 4 22.317 136.551 21.75 0.24 31 + 33 4 22.517 136.764 21.75 0.24 32 diff --git a/tests/swc/l22_small_cvapp.morph.nml b/tests/swc/l22_small_cvapp.morph.nml new file mode 100644 index 00000000..1c7a3f89 --- /dev/null +++ b/tests/swc/l22_small_cvapp.morph.nml @@ -0,0 +1,238 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: l22_small.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/l22_sphersoma.swc b/tests/swc/l22_sphersoma.swc new file mode 100644 index 00000000..bb9b7e6d --- /dev/null +++ b/tests/swc/l22_sphersoma.swc @@ -0,0 +1,26 @@ +# Original file l22.swc edited by Duncan Donohue using StdSwc version 1.21 on 7/25/05. +# Irregularities and fixes documented in l22.swc.std. See StdSwc1.21.doc for more information. +# +# ORIGINAL_SOURCE Neurolucida +# CREATURE rat F344 +# REGION Hippocampus +# FIELD/LAYER CA3 +# TYPE CA3c Pyramidal Cell in vivo young +# CONTRIBUTOR Buzsaki_G & Turner_DA +# REFERENCE J. Comp. Neurol. 356: 580-594, 1995 +# RAW l22.asc +# EXTRAS Turner_P.CA3 +# SOMA_AREA 0.98E3 +# SHRINKAGE_CORRECTION 1.33 1.33 2.5 +# VERSION_NUMBER 2.0 +# VERSION_DATE 1998-03-27 +# ********************************************* +# SCALE 1.33 1.33 2.5 +# + + 1 1 -2.913 28.103 10.7 3.42 -1 + 2 3 -13.112 30.457 13.2 1 1 + 3 3 -3.112 40.457 13.2 1 2 + 4 3 -3.112 50.457 13.2 1 3 + 5 3 -13.112 60.457 13.2 0.3 4 + 6 3 3.112 60.457 13.2 0.3 4 diff --git a/tests/swc/l22_sphersoma_cvapp.morph.nml b/tests/swc/l22_sphersoma_cvapp.morph.nml new file mode 100644 index 00000000..4c63492b --- /dev/null +++ b/tests/swc/l22_sphersoma_cvapp.morph.nml @@ -0,0 +1,95 @@ + + + + Neuronal morphology exported in NeuroML v2.3.1 from CVapp (NeuroMorpho.org version) + Original file: l22_sphersoma.swc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/swc/test_ExportNML.py b/tests/swc/test_ExportNML.py new file mode 100644 index 00000000..af0dea5a --- /dev/null +++ b/tests/swc/test_ExportNML.py @@ -0,0 +1,183 @@ +import logging +import os +import unittest +from functools import lru_cache + +import pytest +from neuroml import Cell +from parameterized import parameterized + +from pyneuroml.io import read_neuroml2_file +from pyneuroml.swc.ExportNML import convert_swc_to_neuroml + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + + +# Define a test class for NeuroMLWriter +class TestNeuroMLWriter(unittest.TestCase): + @pytest.fixture(autouse=True) + def this_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + + @lru_cache(maxsize=10000) + def compare_segment_points(self, cell1, cell2, seg1, seg2): + """Compare two segments""" + distal_match = ( + (float(seg1.distal.x) == float(seg2.distal.x)) + and (float(seg1.distal.y) == float(seg2.distal.y)) + and (float(seg1.distal.z) == float(seg2.distal.z)) + and (float(seg1.distal.diameter) == float(seg2.distal.diameter)) + ) + + prox1 = cell1.get_actual_proximal(seg1.id) + prox2 = cell2.get_actual_proximal(seg2.id) + + proximal_match = ( + (float(prox1.x) == float(prox2.x)) + and (float(prox1.y) == float(prox2.y)) + and (float(prox1.z) == float(prox2.z)) + and (float(prox1.diameter) == float(prox2.diameter)) + ) + + return distal_match and proximal_match + + def compare_to_cvapp_output( + self, cvapp_output_file, exported_nml_doc, test_segments + ): + """Compare our export to the CVApp output. + + Ideally, we need to match pretty much exactly---apart from the strings + that are used in IDs and so on. + + Things we check: + + - same number of segments + - proximals and distals of segments + + Things we do not check + + - same number of segment groups and their composition because there are + different ways of creating "unbranched segment groups". The way we do + it in PyNeuroML is to create a new one from each branching point, but + CVApp treats the soma as a special case. From a modelling + perspective, both are correct because a simulator will be able to + create sections (in NEURON) for example that result in the same + biophysics. + + :param cvapp_output_file: name of CVApp conversion file + :type cvapp_output_file: str + :param exported_nml_doc: our NeuroML export + :type exported_nml_doc: NeuroMLDocument + :param test_segments: toggle whether individual segments should also be + compared. For larger models, this can take a long time, so we turn + this off for them + :type test_segments: bool + + """ + cvapp_doc = read_neuroml2_file(cvapp_output_file) + + num_segments_cvapp = len(cvapp_doc.morphology[0].segments) + num_segments_nml = len(exported_nml_doc.morphology[0].segments) + + if test_segments: + # create cells to be able to use cell functions like get_segment + cell_cvapp = Cell(id="cell_cvapp", morphology=cvapp_doc.morphology[0]) + cell_nml = Cell(id="cell_nml", morphology=exported_nml_doc.morphology[0]) + + # Match parents and distal points + # Do not match proximal points because our exporter does unbranched + # segment groups differently from CVapp, and adds proximal points to + # the root segments of all unbranched segment groups. + matched = [] + for seg_cvapp in cvapp_doc.morphology[0].segments: + for seg_nml in exported_nml_doc.morphology[0].segments: + # already matched, don't bother matching again + if seg_nml in matched: + continue + + logger.debug(f"Comparing {seg_cvapp} - {seg_nml}") + + # compare the distals of the segments + if self.compare_segment_points( + cell_cvapp, cell_nml, seg_cvapp, seg_nml + ): + # Parents: we can't just compare the parent segment IDs + # because there is no guarantee that the order of the + # segments, and thus the segment ids, are the same. So, we + # also go and match the distals of the parents + + # we do not mark parents as matched because we're not + # testing their parents too, we'll do that again when we + # match the parents explicitly + + # both none: fine + if seg_cvapp.parent is None and seg_nml.parent is None: + matched.append(seg_nml) + logger.debug("Matched") + break + + # both not None + elif seg_cvapp.parent and seg_nml.parent: + parent_cvapp = cell_cvapp.get_segment( + seg_cvapp.parent.segments + ) + parent_nml = cell_nml.get_segment(seg_nml.parent.segments) + + if self.compare_segment_points( + cell_cvapp, cell_nml, parent_cvapp, parent_nml + ): + matched.append(seg_nml) + logger.debug("Matched") + break + + # one is none, one isn't, no match + else: + pass + + len_matched = len(list(set(matched))) + + # list of ones that didn't match + unmatched = set(matched) ^ set(exported_nml_doc.morphology[0].segments) + + self.assertEqual( + len_matched, + num_segments_nml, + f"Number of segments does not match: (cvapp: {num_segments_cvapp} vs nml: {num_segments_nml}): {unmatched}", + ) + else: + self.assertEqual( + num_segments_cvapp, + num_segments_nml, + f"Number of segments does not match: (cvapp: {num_segments_cvapp} vs nml: {num_segments_nml})", + ) + + # https://pypi.org/project/parameterized/#description + @parameterized.expand( + [ + ("Case1_new.swc", True), + ("Case2_new.swc", True), + ("Case3_new.swc", True), + ("Case4_new.swc", True), + ("Case5_new.swc", True), + ("dCH-cobalt.CNG_small.swc", True), + ("l22_cylsoma.swc", True), + ("l22_small.swc", True), + ("l22_sphersoma.swc", True), + # ("dCH-cobalt.CNG.swc", False), # takes too long to test + # "l22.swc", # UNKNOWN_PARENT: skip for time being + ] + ) + def test_swc_conversions(self, swc_file, test_segments): + "Test SWC conversions" + swc_nml_file = swc_file.replace(".swc", "_cvapp.morph.nml") + nml_file = swc_file.replace(".swc", "_pynml.morph.nml") + nml_output = convert_swc_to_neuroml(swc_file, nml_file, True) + + self.compare_to_cvapp_output(swc_nml_file, nml_output, test_segments) + os.unlink(nml_file) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/tellurium/do_test_tellurium.py b/tests/tellurium/do_test_tellurium.py index 2cc020b6..da129ff6 100644 --- a/tests/tellurium/do_test_tellurium.py +++ b/tests/tellurium/do_test_tellurium.py @@ -8,11 +8,10 @@ as pytest is segfaulting """ +import os from pyneuroml import tellurium -import os - def test_run_tellurium_on_valid_file(): "ensure it runs a basic sedml file without error" diff --git a/tests/test_biosimulations.py b/tests/test_biosimulations.py index 978104c6..3e91b1fa 100644 --- a/tests/test_biosimulations.py +++ b/tests/test_biosimulations.py @@ -8,13 +8,13 @@ """ import logging -import os import pathlib from pyneuroml.biosimulations import ( get_simulator_versions, submit_simulation, ) +from pyneuroml.utils.misc import chdir from . import BaseTestCase @@ -53,20 +53,18 @@ def test_submit_simulation(self): dry_run = True thispath = pathlib.Path(__file__) dirname = str(thispath.parent.parent) - cwd = os.getcwd() - os.chdir(dirname + "/examples") - sim_dict = { - "name": "PyNeuroML test simulation", - "simulator": "neuron", - "simulatorVersion": "latest", - "maxTime": "20", - } + with chdir(dirname + "/examples"): + sim_dict = { + "name": "PyNeuroML test simulation", + "simulator": "neuron", + "simulatorVersion": "latest", + "maxTime": "20", + } - resdict = submit_simulation( - "LEMS_NML2_Ex5_DetCell.xml", sim_dict=sim_dict, dry_run=dry_run - ) - response = resdict["response"] - os.chdir(cwd) + resdict = submit_simulation( + "LEMS_NML2_Ex5_DetCell.xml", sim_dict=sim_dict, dry_run=dry_run + ) + response = resdict["response"] if dry_run: pass diff --git a/tests/test_io.py b/tests/test_io.py new file mode 100644 index 00000000..3167eb8b --- /dev/null +++ b/tests/test_io.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +""" +Tests for io methods + +File: tests/test_io.py + +Copyright 2024 NeuroML contributors +""" + +import logging +import os + +from pyneuroml.errors import NMLFileTypeError +from pyneuroml.io import confirm_file_type + +from . import BaseTestCase + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + + +class TestIo(BaseTestCase): + """Test io module""" + + def test_confirm_file_type(self): + """Test confirm_file_type method.""" + + # LEMS file with xml extension + test_lems_file = "a_test_lems_file.xml" + with open(test_lems_file, "w") as f: + print(" ", file=f) + confirm_file_type(test_lems_file, ["xml"]) + + # lems file with non xml extension but provided tag + test_lems_file2 = "a_test_lems_file.lems" + with open(test_lems_file2, "w") as f: + print(" ", file=f) + + confirm_file_type(test_lems_file2, ["xml"], "lems") + + # lems file with non xml and bad tag: should fail + with self.assertRaises(NMLFileTypeError): + test_lems_file3 = "a_bad_test_lems_file.lems" + with open(test_lems_file3, "w") as f: + print(" ", file=f) + + confirm_file_type(test_lems_file3, ["xml"], "lems") + + os.unlink(test_lems_file) + os.unlink(test_lems_file2) + os.unlink(test_lems_file3) diff --git a/tests/test_nsgr.py b/tests/test_nsgr.py index 22cdec81..0437be8b 100644 --- a/tests/test_nsgr.py +++ b/tests/test_nsgr.py @@ -7,7 +7,6 @@ Copyright 2024 NeuroML contributors """ - import logging import pathlib as pl diff --git a/tests/test_pynml.py b/tests/test_pynml.py index 72b32008..21fff8c8 100644 --- a/tests/test_pynml.py +++ b/tests/test_pynml.py @@ -13,24 +13,22 @@ import shutil import unittest -from pyneuroml.pynml import ( - execute_command_in_dir, - execute_command_in_dir_with_realtime_output, - extract_lems_definition_files, - list_exposures, - list_recording_paths_for_exposures, - run_jneuroml, - validate_neuroml2, -) +import pytest + +import pyneuroml.pynml as pynmlpynml logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) class TestJarUtils(unittest.TestCase): - """Test jNeuroML jar related functions""" + @pytest.fixture(autouse=True) + def this_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + def test_lems_def_files_extraction(self): """Test extraction of NeuroML2 LEMS files from jar.""" filelist = [ @@ -46,19 +44,23 @@ def test_lems_def_files_extraction(self): "Synapses.xml", ] - extraction_dir = extract_lems_definition_files() + extraction_dir = pynmlpynml.extract_lems_definition_files() newfilelist = os.listdir(extraction_dir) shutil.rmtree(extraction_dir[: -1 * len("NeuroML2CoreTypes/")]) assert sorted(filelist) == sorted(newfilelist) class TestHelperUtils(unittest.TestCase): - """Test helper utilities.""" + @pytest.fixture(autouse=True) + def this_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + def test_exposure_listing(self): """Test listing of exposures in NeuroML documents.""" - exps = list_exposures("tests/izhikevich_test_file.nml", "iz") + exps = pynmlpynml.list_exposures("izhikevich_test_file.nml", "iz") ctypes = {} for key, val in exps.items(): ctypes[key.type] = val @@ -75,15 +77,13 @@ def test_exposure_listing(self): def test_exposure_listing_2(self): """Test listing of exposures in NeuroML documents.""" - os.chdir("tests/") - exps = list_exposures("HH_example_net.nml") + exps = pynmlpynml.list_exposures("HH_example_net.nml") print(exps) - os.chdir("../") def test_recording_path_listing(self): """Test listing of recording paths in NeuroML documents.""" - paths = list_recording_paths_for_exposures( - "tests/izhikevich_test_file.nml", "", "IzhNet" + paths = pynmlpynml.list_recording_paths_for_exposures( + "izhikevich_test_file.nml", "", "IzhNet" ) print("\n".join(paths)) # self.assertTrue("izh2007RS0/u" in paths) @@ -91,12 +91,10 @@ def test_recording_path_listing(self): def test_recording_path_listing_2(self): """Test listing of recording paths in NeuroML documents.""" - os.chdir("tests/") - paths = list_recording_paths_for_exposures( + paths = pynmlpynml.list_recording_paths_for_exposures( "HH_example_net.nml", "hh_cell", "single_hh_cell_network" ) print("\n".join(paths)) - os.chdir("../") def test_execute_command_in_dir(self): """Test execute_command_in_dir function.""" @@ -106,7 +104,7 @@ def test_execute_command_in_dir(self): output = None retcode = None - retcode, output = execute_command_in_dir( + retcode, output = pynmlpynml.execute_command_in_dir( command, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) @@ -116,7 +114,7 @@ def test_execute_command_in_dir(self): command_bad = "ls non_existent_file" output = None retcode = None - retcode, output = execute_command_in_dir( + retcode, output = pynmlpynml.execute_command_in_dir( command_bad, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) self.assertNotEqual(retcode, 0) @@ -129,7 +127,7 @@ def test_execute_command_in_dir_with_realtime_output(self): verbose = True success = False - success = execute_command_in_dir_with_realtime_output( + success = pynmlpynml.execute_command_in_dir_with_realtime_output( command, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) self.assertTrue(success) @@ -137,7 +135,7 @@ def test_execute_command_in_dir_with_realtime_output(self): command_bad = "ls non_existent_file" success = True - success = execute_command_in_dir_with_realtime_output( + success = pynmlpynml.execute_command_in_dir_with_realtime_output( command_bad, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) self.assertFalse(success) @@ -145,32 +143,32 @@ def test_execute_command_in_dir_with_realtime_output(self): def test_run_jneuroml(self): """Test run_jneuroml""" retstat = None - retstat = run_jneuroml("-v", None, None) + retstat = pynmlpynml.run_jneuroml("-v", None, None) self.assertTrue(retstat) retstat = None - retstat = run_jneuroml("-randomflag", "", "") + retstat = pynmlpynml.run_jneuroml("-randomflag", "", "") self.assertFalse(retstat) def test_validate_neuroml2(self): """Test validate_neuroml2""" - os.chdir("tests/") retval = None - retval = validate_neuroml2("HH_example_k_channel.nml") + retval = pynmlpynml.validate_neuroml2("HH_example_k_channel.nml") self.assertTrue(retval) retval = None retstring = None - retval, retstring = validate_neuroml2( + retval, retstring = pynmlpynml.validate_neuroml2( "HH_example_k_channel.nml", return_string=True ) self.assertTrue(retval) self.assertIn("Valid against schema and all tests", retstring) - os.chdir("../") retval = None retstring = None - retval, retstring = validate_neuroml2("setup.cfg", return_string=True) + retval, retstring = pynmlpynml.validate_neuroml2( + "../setup.cfg", return_string=True + ) self.assertFalse(retval) self.assertIn("1 failed", retstring) diff --git a/tests/test_runners.py b/tests/test_runners.py index 7009003f..a5bdc75a 100644 --- a/tests/test_runners.py +++ b/tests/test_runners.py @@ -10,6 +10,8 @@ import logging import pathlib as pl +import pytest + from pyneuroml.runners import ( execute_command_in_dir, execute_multiple_in_dir, @@ -26,14 +28,20 @@ class TestRunners(BaseTestCase): """Test runners module""" + # Run in top repo dir + @pytest.fixture(autouse=True) + def top_dir(self, monkeypatch, request): + target_dir = request.path.parent.parent + monkeypatch.chdir(target_dir) + def test_generate_sim_scripts_in_folder(self): """test generate_sim_scripts_in_folder method""" thispath = pl.Path(__file__) - dirname = str(thispath.parent.parent) + topdirname = str(thispath.parent.parent) dirname = generate_sim_scripts_in_folder( engine="jneuroml_neuron", lems_file_name="LEMS_NML2_Ex5_DetCell.xml", - root_dir=dirname + "/examples/", + root_dir=topdirname + "/examples/", run_dir=str(thispath.parent), ) self.assertTrue(pl.Path(dirname).exists()) diff --git a/tests/utils/test_nml2py.py b/tests/utils/test_nml2py.py new file mode 100644 index 00000000..5f1f44eb --- /dev/null +++ b/tests/utils/test_nml2py.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +""" +Test nml2py.py + +File: tests/utils/test_nml2py.py + +Copyright 2026 Ankur Sinha +Author: Ankur Sinha +""" + +import logging +import tempfile +from pathlib import Path + +import pytest +from neuroml.utils import component_factory + +from pyneuroml.io import read_neuroml2_file, write_neuroml2_file +from pyneuroml.utils.nml2py import NmlPythonizer, _sanitize_var_name + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# NOTE: when using xdist, one cannot print to stdout. -s won't work. +# So, use logging, which works with xdist. + + +@pytest.fixture(autouse=True) +def to_test_dir(monkeypatch, request): + target_dir = request.path.parent.parent + monkeypatch.chdir(target_dir) + + +def test_nml2py(): + converter = NmlPythonizer("HH_example_net.nml", "temp_nml2py_1") + files = converter.write() + script = files[-1] + + assert Path(script).exists() + + +def test_collect_one(): + """Test _collect_one""" + nml_doc = component_factory("NeuroMLDocument", id="nml_doc") + net = nml_doc.add("Network", id="nml_net", validate=False) + inc = nml_doc.add("IncludeType", href="test.nml") + + # set up mock file + converter = NmlPythonizer("somefile.nml", "temp_nml2py_1") + net_var = converter._collect_one(net, "nml_doc") + + assert id(net) in converter._obj_to_var + assert converter._obj_to_var.get(id(net)) == net_var + + # skip include type, handled separately + assert converter._collect_one(inc, "nml_doc") is None + + +def test_make_var_name(): + """Test _make_var_name""" + nml_doc = component_factory("NeuroMLDocument", id="nml_doc") + + # set up mock file + converter = NmlPythonizer("somefile.nml", "temp_nml2py_1") + net_var = converter._make_var_name(nml_doc, "NeuroMLDocument") + assert net_var == "nml_doc" + assert converter._var_counters["nml_doc"] == 0 + + +def test_sanitize_var_name_int(): + """Test _sanitize_var_name""" + vname = _sanitize_var_name(15) + assert vname == "_15" + + +def test_sanitize_var_name_str(): + """Test _sanitize_var_name""" + vname = _sanitize_var_name("lol$name") + assert vname == "lol_name" + + +def test_walk_children(): + """Test _walk_children""" + converter = NmlPythonizer("HH_example_net.nml", "temp_nml2py_1") + raw_doc = read_neuroml2_file("HH_example_net.nml", include_includes=False) + converter._walk_children(raw_doc, "nml_doc") + + logger.debug(f"{converter._obj_to_var = }") + logger.debug(f"{converter._components = }") + logger.debug(f"{raw_doc.networks[0].info(True) = }") + + assert converter._obj_to_var[id(raw_doc.networks[0])] == raw_doc.networks[0].id + assert ( + converter._obj_to_var[id(raw_doc.networks[0].populations[0])] + == raw_doc.networks[0].populations[0].id + ) + + +def test_generated_code_structure(): + """Test generated code contains expected variable names, parameters, and structure.""" + converter = NmlPythonizer("HH_example_net.nml", "temp_nml2py_1") + converter.raw_doc = read_neuroml2_file("HH_example_net.nml", include_includes=False) + converter._collect_components() + code = converter.generate() + + assert "nml_doc.add(\"IncludeType\", href='HH_example_cell.nml')" in code + assert "single_hh_cell_network = nml_doc.add(" in code + assert "pop0 = single_hh_cell_network.add(" in code + assert "pg = nml_doc.add(" in code + assert "amplitude='0.08nA'" in code + assert "delay='100ms'" in code + assert "size=2" in code + assert "component='hh_cell'" in code + assert "target='pop0[0]'" in code + assert "# --- Networks ---" in code + assert "# --- Populations ---" in code + assert "# --- Inputs ---" in code + assert "# --- Other ---" in code + + +def test_generated_code_structure_1(): + """Test generated code contains expected variable names, parameters, and structure. + + This creates a temporary file with the cell included to test extraction. + """ + model = read_neuroml2_file("HH_example_net.nml", include_includes=True) + cell_file_name = f"{model.cells[0].id}.cell.nml" + + with tempfile.NamedTemporaryFile("w", dir=".") as f: + write_neuroml2_file(model, f.name) + + converter = NmlPythonizer(f.name, "temp_nml2py_1") + written = converter.write() + + for af in written: + assert Path(af).exists() is True + + with open(written[-1], "r") as sf: + code = sf.read() + logger.debug(f"{code = }") + + assert f'nml_doc.add("IncludeType", href={cell_file_name!r})' in code + assert "single_hh_cell_network = nml_doc.add(" in code + assert "pop0 = single_hh_cell_network.add(" in code + assert "pg = nml_doc.add(" in code + assert "amplitude='0.08nA'" in code + assert "delay='100ms'" in code + assert "size=2" in code + assert "component='hh_cell'" in code + assert "target='pop0[0]'" in code + assert "# --- Includes ---" in code + assert "# --- Networks ---" in code + assert "# --- Populations ---" in code + assert "# --- Inputs ---" in code + assert "# --- Other ---" in code + + +def test_generated_code_exec(): + """Test that generated code executes and creates the correct model structure.""" + converter = NmlPythonizer("HH_example_net.nml", "temp_nml2py_1") + converter.raw_doc = read_neuroml2_file("HH_example_net.nml", include_includes=False) + converter._collect_components() + code = converter.generate() + + ns = {} + exec(code, ns) + + nml_doc = ns["nml_doc"] + assert nml_doc.id == "network" + + net = ns["single_hh_cell_network"] + assert net.id == "single_hh_cell_network" + + pop = ns["pop0"] + assert pop.id == "pop0" + assert pop.size == 2 + assert pop.component == "hh_cell" + + pg = ns["pg"] + assert pg.id == "pg" + assert pg.amplitude == "0.08nA" + assert pg.delay == "100ms" + + assert len(nml_doc.includes) == 1 + assert nml_doc.includes[0].href == "HH_example_cell.nml" diff --git a/tests/lems/test_lems.py b/tests/utils/test_simdata.py similarity index 87% rename from tests/lems/test_lems.py rename to tests/utils/test_simdata.py index 8606ab51..27d27d0c 100644 --- a/tests/lems/test_lems.py +++ b/tests/utils/test_simdata.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 """ -Tests related to pyneuroml.lems module +Tests related to pyneuroml.utils.simdata module -File: tests/lems/tests_lems.py +File: tests/utils/test_simdata.py Copyright 2024 NeuroML contributors """ @@ -12,14 +12,14 @@ import tempfile import unittest -import pyneuroml.lems as pyl +import pyneuroml.utils.simdata as pyl logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) -class TestLEMSModule(unittest.TestCase): - """Test the LEMS module""" +class TestSimdataModule(unittest.TestCase): + """Test the simdata module""" def test_load_sim_data_from_lems_file(self): """Test the load_sim_data_from_lems_file function""" @@ -113,19 +113,23 @@ def test_load_sim_data_from_lems_file(self): f.flush() f.close() - events = pyl.load_sim_data_from_lems_file( + all_events = pyl.load_sim_data_from_lems_file( f.name, base_dir=".", get_events=True, get_traces=False ) - traces = pyl.load_sim_data_from_lems_file( + all_traces = pyl.load_sim_data_from_lems_file( f.name, base_dir=".", get_events=False, get_traces=True ) + self.assertIsNotNone(all_events) + events = all_events[event_data_file.name] self.assertIsNotNone(events) self.assertEqual(events["IzPop0[0]"][0], 0.04350000000009967) self.assertEqual(events["IzPop0[0]"][-1], 0.9433999999997897) print(events) + self.assertIsNotNone(all_traces) + traces = all_traces[trace_file.name] self.assertIsNotNone(traces) self.assertEqual(traces["t"][0], 0.0) self.assertEqual(traces["t"][-1], 0.0019) diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index a53e6476..2b18e1be 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -9,9 +9,11 @@ import logging import math +import os import pathlib as pl import neuroml +import pytest from pyneuroml.pynml import read_neuroml2_file, write_neuroml2_file from pyneuroml.utils import ( @@ -20,6 +22,7 @@ rotate_cell, translate_cell_to_coords, ) +from pyneuroml.utils.components import add_new_component from .. import BaseTestCase @@ -30,9 +33,14 @@ class TestUtils(BaseTestCase): """Test utils module""" + @pytest.fixture(autouse=True) + def to_test_dir(self, monkeypatch, request): + target_dir = request.path.parent.parent + monkeypatch.chdir(target_dir) + def test_extract_position_info(self): """Test extract_position_info""" - nml_files = ["tests/plot/L23-example/TestNetwork.net.nml"] + nml_files = ["plot/L23-example/TestNetwork.net.nml"] for nml_file in nml_files: nml_model = read_neuroml2_file( nml_file, @@ -156,7 +164,7 @@ def test_rotate_cell(self): ) newdoc.validate(recursive=True) - write_neuroml2_file(newdoc, "tests/utils/test_rotation.net.nml", validate=True) + write_neuroml2_file(newdoc, "utils/test_rotation.net.nml", validate=True) def test_translate_cell_to_coords(self): """Test translate_cell_to_coords""" @@ -279,6 +287,13 @@ def test_translate_cell_to_coords(self): ) newdoc.validate(recursive=True) - write_neuroml2_file( - newdoc, "tests/utils/test_translation.net.nml", validate=True + write_neuroml2_file(newdoc, "utils/test_translation.net.nml", validate=True) + + def test_adding_new_components(self): + """Test add_new_component method.""" + new_comp, new_comp_file = add_new_component( + "newcomp", "sometype", param1="5v", param2="something" ) + self.assertIsNotNone(new_comp) + self.assertIsFile(new_comp_file) + os.unlink(new_comp_file)