diff --git a/notebooks/pointing_accuracy_vs_spatial_resolution_tradebook.ipynb b/notebooks/pointing_accuracy_vs_spatial_resolution_tradebook.ipynb
new file mode 100644
index 0000000..3770925
--- /dev/null
+++ b/notebooks/pointing_accuracy_vs_spatial_resolution_tradebook.ipynb
@@ -0,0 +1,3158 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Pointing Accuracy Constraint vs Spatial Resolution"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# external\n",
+ "import astropy.units as unit\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import plot\n",
+ "from IPython.display import display\n",
+ "\n",
+ "# project\n",
+ "from payload_designer import components, systems"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Setup\n",
+ "Run this section onwards when a parameter is updated."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# region constants\n",
+ "target_wavelength = 1600 * unit.nm\n",
+ "orbital_altitude = 600 * unit.km\n",
+ "\n",
+ "# endregion\n",
+ "\n",
+ "# region variables\n",
+ "spatial_resolution = np.arange(start=0, stop=100000, step=100) * unit.m\n",
+ "# endregion"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Artifact Instantiation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# region systems\n",
+ "payload = systems.payloads.HyperspectralImager(spatial_resolution=spatial_resolution)\n",
+ "# endregion"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Pipeline\n",
+ "The computational graph"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pointing_constraint = payload.get_pointing_accuracy_constraint(\n",
+ " wavelength=target_wavelength, target_distance=orbital_altitude\n",
+ ").to(unit.degree)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plots"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.plotly.v1+json": {
+ "config": {
+ "plotlyServerURL": "https://plot.ly"
+ },
+ "data": [
+ {
+ "hovertemplate": "Spatial Resolution [m]=%{x}
Pointing Accuracy Constraint [deg]=%{y}",
+ "legendgroup": "",
+ "line": {
+ "color": "#636efa",
+ "dash": "solid"
+ },
+ "marker": {
+ "symbol": "circle"
+ },
+ "mode": "lines",
+ "name": "",
+ "orientation": "v",
+ "showlegend": false,
+ "type": "scatter",
+ "x": [
+ 0,
+ 100,
+ 200,
+ 300,
+ 400,
+ 500,
+ 600,
+ 700,
+ 800,
+ 900,
+ 1000,
+ 1100,
+ 1200,
+ 1300,
+ 1400,
+ 1500,
+ 1600,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2100,
+ 2200,
+ 2300,
+ 2400,
+ 2500,
+ 2600,
+ 2700,
+ 2800,
+ 2900,
+ 3000,
+ 3100,
+ 3200,
+ 3300,
+ 3400,
+ 3500,
+ 3600,
+ 3700,
+ 3800,
+ 3900,
+ 4000,
+ 4100,
+ 4200,
+ 4300,
+ 4400,
+ 4500,
+ 4600,
+ 4700,
+ 4800,
+ 4900,
+ 5000,
+ 5100,
+ 5200,
+ 5300,
+ 5400,
+ 5500,
+ 5600,
+ 5700,
+ 5800,
+ 5900,
+ 6000,
+ 6100,
+ 6200,
+ 6300,
+ 6400,
+ 6500,
+ 6600,
+ 6700,
+ 6800,
+ 6900,
+ 7000,
+ 7100,
+ 7200,
+ 7300,
+ 7400,
+ 7500,
+ 7600,
+ 7700,
+ 7800,
+ 7900,
+ 8000,
+ 8100,
+ 8200,
+ 8300,
+ 8400,
+ 8500,
+ 8600,
+ 8700,
+ 8800,
+ 8900,
+ 9000,
+ 9100,
+ 9200,
+ 9300,
+ 9400,
+ 9500,
+ 9600,
+ 9700,
+ 9800,
+ 9900,
+ 10000,
+ 10100,
+ 10200,
+ 10300,
+ 10400,
+ 10500,
+ 10600,
+ 10700,
+ 10800,
+ 10900,
+ 11000,
+ 11100,
+ 11200,
+ 11300,
+ 11400,
+ 11500,
+ 11600,
+ 11700,
+ 11800,
+ 11900,
+ 12000,
+ 12100,
+ 12200,
+ 12300,
+ 12400,
+ 12500,
+ 12600,
+ 12700,
+ 12800,
+ 12900,
+ 13000,
+ 13100,
+ 13200,
+ 13300,
+ 13400,
+ 13500,
+ 13600,
+ 13700,
+ 13800,
+ 13900,
+ 14000,
+ 14100,
+ 14200,
+ 14300,
+ 14400,
+ 14500,
+ 14600,
+ 14700,
+ 14800,
+ 14900,
+ 15000,
+ 15100,
+ 15200,
+ 15300,
+ 15400,
+ 15500,
+ 15600,
+ 15700,
+ 15800,
+ 15900,
+ 16000,
+ 16100,
+ 16200,
+ 16300,
+ 16400,
+ 16500,
+ 16600,
+ 16700,
+ 16800,
+ 16900,
+ 17000,
+ 17100,
+ 17200,
+ 17300,
+ 17400,
+ 17500,
+ 17600,
+ 17700,
+ 17800,
+ 17900,
+ 18000,
+ 18100,
+ 18200,
+ 18300,
+ 18400,
+ 18500,
+ 18600,
+ 18700,
+ 18800,
+ 18900,
+ 19000,
+ 19100,
+ 19200,
+ 19300,
+ 19400,
+ 19500,
+ 19600,
+ 19700,
+ 19800,
+ 19900,
+ 20000,
+ 20100,
+ 20200,
+ 20300,
+ 20400,
+ 20500,
+ 20600,
+ 20700,
+ 20800,
+ 20900,
+ 21000,
+ 21100,
+ 21200,
+ 21300,
+ 21400,
+ 21500,
+ 21600,
+ 21700,
+ 21800,
+ 21900,
+ 22000,
+ 22100,
+ 22200,
+ 22300,
+ 22400,
+ 22500,
+ 22600,
+ 22700,
+ 22800,
+ 22900,
+ 23000,
+ 23100,
+ 23200,
+ 23300,
+ 23400,
+ 23500,
+ 23600,
+ 23700,
+ 23800,
+ 23900,
+ 24000,
+ 24100,
+ 24200,
+ 24300,
+ 24400,
+ 24500,
+ 24600,
+ 24700,
+ 24800,
+ 24900,
+ 25000,
+ 25100,
+ 25200,
+ 25300,
+ 25400,
+ 25500,
+ 25600,
+ 25700,
+ 25800,
+ 25900,
+ 26000,
+ 26100,
+ 26200,
+ 26300,
+ 26400,
+ 26500,
+ 26600,
+ 26700,
+ 26800,
+ 26900,
+ 27000,
+ 27100,
+ 27200,
+ 27300,
+ 27400,
+ 27500,
+ 27600,
+ 27700,
+ 27800,
+ 27900,
+ 28000,
+ 28100,
+ 28200,
+ 28300,
+ 28400,
+ 28500,
+ 28600,
+ 28700,
+ 28800,
+ 28900,
+ 29000,
+ 29100,
+ 29200,
+ 29300,
+ 29400,
+ 29500,
+ 29600,
+ 29700,
+ 29800,
+ 29900,
+ 30000,
+ 30100,
+ 30200,
+ 30300,
+ 30400,
+ 30500,
+ 30600,
+ 30700,
+ 30800,
+ 30900,
+ 31000,
+ 31100,
+ 31200,
+ 31300,
+ 31400,
+ 31500,
+ 31600,
+ 31700,
+ 31800,
+ 31900,
+ 32000,
+ 32100,
+ 32200,
+ 32300,
+ 32400,
+ 32500,
+ 32600,
+ 32700,
+ 32800,
+ 32900,
+ 33000,
+ 33100,
+ 33200,
+ 33300,
+ 33400,
+ 33500,
+ 33600,
+ 33700,
+ 33800,
+ 33900,
+ 34000,
+ 34100,
+ 34200,
+ 34300,
+ 34400,
+ 34500,
+ 34600,
+ 34700,
+ 34800,
+ 34900,
+ 35000,
+ 35100,
+ 35200,
+ 35300,
+ 35400,
+ 35500,
+ 35600,
+ 35700,
+ 35800,
+ 35900,
+ 36000,
+ 36100,
+ 36200,
+ 36300,
+ 36400,
+ 36500,
+ 36600,
+ 36700,
+ 36800,
+ 36900,
+ 37000,
+ 37100,
+ 37200,
+ 37300,
+ 37400,
+ 37500,
+ 37600,
+ 37700,
+ 37800,
+ 37900,
+ 38000,
+ 38100,
+ 38200,
+ 38300,
+ 38400,
+ 38500,
+ 38600,
+ 38700,
+ 38800,
+ 38900,
+ 39000,
+ 39100,
+ 39200,
+ 39300,
+ 39400,
+ 39500,
+ 39600,
+ 39700,
+ 39800,
+ 39900,
+ 40000,
+ 40100,
+ 40200,
+ 40300,
+ 40400,
+ 40500,
+ 40600,
+ 40700,
+ 40800,
+ 40900,
+ 41000,
+ 41100,
+ 41200,
+ 41300,
+ 41400,
+ 41500,
+ 41600,
+ 41700,
+ 41800,
+ 41900,
+ 42000,
+ 42100,
+ 42200,
+ 42300,
+ 42400,
+ 42500,
+ 42600,
+ 42700,
+ 42800,
+ 42900,
+ 43000,
+ 43100,
+ 43200,
+ 43300,
+ 43400,
+ 43500,
+ 43600,
+ 43700,
+ 43800,
+ 43900,
+ 44000,
+ 44100,
+ 44200,
+ 44300,
+ 44400,
+ 44500,
+ 44600,
+ 44700,
+ 44800,
+ 44900,
+ 45000,
+ 45100,
+ 45200,
+ 45300,
+ 45400,
+ 45500,
+ 45600,
+ 45700,
+ 45800,
+ 45900,
+ 46000,
+ 46100,
+ 46200,
+ 46300,
+ 46400,
+ 46500,
+ 46600,
+ 46700,
+ 46800,
+ 46900,
+ 47000,
+ 47100,
+ 47200,
+ 47300,
+ 47400,
+ 47500,
+ 47600,
+ 47700,
+ 47800,
+ 47900,
+ 48000,
+ 48100,
+ 48200,
+ 48300,
+ 48400,
+ 48500,
+ 48600,
+ 48700,
+ 48800,
+ 48900,
+ 49000,
+ 49100,
+ 49200,
+ 49300,
+ 49400,
+ 49500,
+ 49600,
+ 49700,
+ 49800,
+ 49900,
+ 50000,
+ 50100,
+ 50200,
+ 50300,
+ 50400,
+ 50500,
+ 50600,
+ 50700,
+ 50800,
+ 50900,
+ 51000,
+ 51100,
+ 51200,
+ 51300,
+ 51400,
+ 51500,
+ 51600,
+ 51700,
+ 51800,
+ 51900,
+ 52000,
+ 52100,
+ 52200,
+ 52300,
+ 52400,
+ 52500,
+ 52600,
+ 52700,
+ 52800,
+ 52900,
+ 53000,
+ 53100,
+ 53200,
+ 53300,
+ 53400,
+ 53500,
+ 53600,
+ 53700,
+ 53800,
+ 53900,
+ 54000,
+ 54100,
+ 54200,
+ 54300,
+ 54400,
+ 54500,
+ 54600,
+ 54700,
+ 54800,
+ 54900,
+ 55000,
+ 55100,
+ 55200,
+ 55300,
+ 55400,
+ 55500,
+ 55600,
+ 55700,
+ 55800,
+ 55900,
+ 56000,
+ 56100,
+ 56200,
+ 56300,
+ 56400,
+ 56500,
+ 56600,
+ 56700,
+ 56800,
+ 56900,
+ 57000,
+ 57100,
+ 57200,
+ 57300,
+ 57400,
+ 57500,
+ 57600,
+ 57700,
+ 57800,
+ 57900,
+ 58000,
+ 58100,
+ 58200,
+ 58300,
+ 58400,
+ 58500,
+ 58600,
+ 58700,
+ 58800,
+ 58900,
+ 59000,
+ 59100,
+ 59200,
+ 59300,
+ 59400,
+ 59500,
+ 59600,
+ 59700,
+ 59800,
+ 59900,
+ 60000,
+ 60100,
+ 60200,
+ 60300,
+ 60400,
+ 60500,
+ 60600,
+ 60700,
+ 60800,
+ 60900,
+ 61000,
+ 61100,
+ 61200,
+ 61300,
+ 61400,
+ 61500,
+ 61600,
+ 61700,
+ 61800,
+ 61900,
+ 62000,
+ 62100,
+ 62200,
+ 62300,
+ 62400,
+ 62500,
+ 62600,
+ 62700,
+ 62800,
+ 62900,
+ 63000,
+ 63100,
+ 63200,
+ 63300,
+ 63400,
+ 63500,
+ 63600,
+ 63700,
+ 63800,
+ 63900,
+ 64000,
+ 64100,
+ 64200,
+ 64300,
+ 64400,
+ 64500,
+ 64600,
+ 64700,
+ 64800,
+ 64900,
+ 65000,
+ 65100,
+ 65200,
+ 65300,
+ 65400,
+ 65500,
+ 65600,
+ 65700,
+ 65800,
+ 65900,
+ 66000,
+ 66100,
+ 66200,
+ 66300,
+ 66400,
+ 66500,
+ 66600,
+ 66700,
+ 66800,
+ 66900,
+ 67000,
+ 67100,
+ 67200,
+ 67300,
+ 67400,
+ 67500,
+ 67600,
+ 67700,
+ 67800,
+ 67900,
+ 68000,
+ 68100,
+ 68200,
+ 68300,
+ 68400,
+ 68500,
+ 68600,
+ 68700,
+ 68800,
+ 68900,
+ 69000,
+ 69100,
+ 69200,
+ 69300,
+ 69400,
+ 69500,
+ 69600,
+ 69700,
+ 69800,
+ 69900,
+ 70000,
+ 70100,
+ 70200,
+ 70300,
+ 70400,
+ 70500,
+ 70600,
+ 70700,
+ 70800,
+ 70900,
+ 71000,
+ 71100,
+ 71200,
+ 71300,
+ 71400,
+ 71500,
+ 71600,
+ 71700,
+ 71800,
+ 71900,
+ 72000,
+ 72100,
+ 72200,
+ 72300,
+ 72400,
+ 72500,
+ 72600,
+ 72700,
+ 72800,
+ 72900,
+ 73000,
+ 73100,
+ 73200,
+ 73300,
+ 73400,
+ 73500,
+ 73600,
+ 73700,
+ 73800,
+ 73900,
+ 74000,
+ 74100,
+ 74200,
+ 74300,
+ 74400,
+ 74500,
+ 74600,
+ 74700,
+ 74800,
+ 74900,
+ 75000,
+ 75100,
+ 75200,
+ 75300,
+ 75400,
+ 75500,
+ 75600,
+ 75700,
+ 75800,
+ 75900,
+ 76000,
+ 76100,
+ 76200,
+ 76300,
+ 76400,
+ 76500,
+ 76600,
+ 76700,
+ 76800,
+ 76900,
+ 77000,
+ 77100,
+ 77200,
+ 77300,
+ 77400,
+ 77500,
+ 77600,
+ 77700,
+ 77800,
+ 77900,
+ 78000,
+ 78100,
+ 78200,
+ 78300,
+ 78400,
+ 78500,
+ 78600,
+ 78700,
+ 78800,
+ 78900,
+ 79000,
+ 79100,
+ 79200,
+ 79300,
+ 79400,
+ 79500,
+ 79600,
+ 79700,
+ 79800,
+ 79900,
+ 80000,
+ 80100,
+ 80200,
+ 80300,
+ 80400,
+ 80500,
+ 80600,
+ 80700,
+ 80800,
+ 80900,
+ 81000,
+ 81100,
+ 81200,
+ 81300,
+ 81400,
+ 81500,
+ 81600,
+ 81700,
+ 81800,
+ 81900,
+ 82000,
+ 82100,
+ 82200,
+ 82300,
+ 82400,
+ 82500,
+ 82600,
+ 82700,
+ 82800,
+ 82900,
+ 83000,
+ 83100,
+ 83200,
+ 83300,
+ 83400,
+ 83500,
+ 83600,
+ 83700,
+ 83800,
+ 83900,
+ 84000,
+ 84100,
+ 84200,
+ 84300,
+ 84400,
+ 84500,
+ 84600,
+ 84700,
+ 84800,
+ 84900,
+ 85000,
+ 85100,
+ 85200,
+ 85300,
+ 85400,
+ 85500,
+ 85600,
+ 85700,
+ 85800,
+ 85900,
+ 86000,
+ 86100,
+ 86200,
+ 86300,
+ 86400,
+ 86500,
+ 86600,
+ 86700,
+ 86800,
+ 86900,
+ 87000,
+ 87100,
+ 87200,
+ 87300,
+ 87400,
+ 87500,
+ 87600,
+ 87700,
+ 87800,
+ 87900,
+ 88000,
+ 88100,
+ 88200,
+ 88300,
+ 88400,
+ 88500,
+ 88600,
+ 88700,
+ 88800,
+ 88900,
+ 89000,
+ 89100,
+ 89200,
+ 89300,
+ 89400,
+ 89500,
+ 89600,
+ 89700,
+ 89800,
+ 89900,
+ 90000,
+ 90100,
+ 90200,
+ 90300,
+ 90400,
+ 90500,
+ 90600,
+ 90700,
+ 90800,
+ 90900,
+ 91000,
+ 91100,
+ 91200,
+ 91300,
+ 91400,
+ 91500,
+ 91600,
+ 91700,
+ 91800,
+ 91900,
+ 92000,
+ 92100,
+ 92200,
+ 92300,
+ 92400,
+ 92500,
+ 92600,
+ 92700,
+ 92800,
+ 92900,
+ 93000,
+ 93100,
+ 93200,
+ 93300,
+ 93400,
+ 93500,
+ 93600,
+ 93700,
+ 93800,
+ 93900,
+ 94000,
+ 94100,
+ 94200,
+ 94300,
+ 94400,
+ 94500,
+ 94600,
+ 94700,
+ 94800,
+ 94900,
+ 95000,
+ 95100,
+ 95200,
+ 95300,
+ 95400,
+ 95500,
+ 95600,
+ 95700,
+ 95800,
+ 95900,
+ 96000,
+ 96100,
+ 96200,
+ 96300,
+ 96400,
+ 96500,
+ 96600,
+ 96700,
+ 96800,
+ 96900,
+ 97000,
+ 97100,
+ 97200,
+ 97300,
+ 97400,
+ 97500,
+ 97600,
+ 97700,
+ 97800,
+ 97900,
+ 98000,
+ 98100,
+ 98200,
+ 98300,
+ 98400,
+ 98500,
+ 98600,
+ 98700,
+ 98800,
+ 98900,
+ 99000,
+ 99100,
+ 99200,
+ 99300,
+ 99400,
+ 99500,
+ 99600,
+ 99700,
+ 99800,
+ 99900
+ ],
+ "xaxis": "x",
+ "y": [
+ 0,
+ 0.0047746482817044335,
+ 0.009549296497094309,
+ 0.014323944579855075,
+ 0.019098592463672185,
+ 0.02387324008223112,
+ 0.028647887369217372,
+ 0.033422534258316476,
+ 0.03819718068321397,
+ 0.04297182657759547,
+ 0.04774647187514661,
+ 0.05252111650955307,
+ 0.057295760414500616,
+ 0.06207040352367503,
+ 0.06684504577076222,
+ 0.07161968708944809,
+ 0.07639432741341867,
+ 0.08116896667636012,
+ 0.08594360481195855,
+ 0.0907182417539003,
+ 0.09549287743587175,
+ 0.10026751179155938,
+ 0.10504214475464979,
+ 0.10981677625882971,
+ 0.11459140623778596,
+ 0.11936603462520558,
+ 0.12414066135477553,
+ 0.1289152863601832,
+ 0.13368990957511584,
+ 0.13846453093326105,
+ 0.14323915036830656,
+ 0.14801376781394016,
+ 0.1527883832038498,
+ 0.15756299647172375,
+ 0.1623376075512504,
+ 0.16711221637611817,
+ 0.17188682288001592,
+ 0.1766614269966325,
+ 0.181436028659657,
+ 0.1862106278027788,
+ 0.19098522435968746,
+ 0.19575981826407265,
+ 0.20053440944962445,
+ 0.20530899785003298,
+ 0.21008358339898867,
+ 0.2148581660301822,
+ 0.21963274567730456,
+ 0.2244073222740468,
+ 0.22918189575410042,
+ 0.23395646605115697,
+ 0.2387310330989086,
+ 0.2435055968310473,
+ 0.24828015718126567,
+ 0.2530547140832565,
+ 0.25782926747071283,
+ 0.2626038172773279,
+ 0.26737836343679555,
+ 0.2721529058828096,
+ 0.27692744454906426,
+ 0.28170197936925434,
+ 0.2864765102770745,
+ 0.29125103720622003,
+ 0.29602556009038655,
+ 0.3008000788632698,
+ 0.3055745934585662,
+ 0.31034910380997227,
+ 0.3151236098511848,
+ 0.3198981115159013,
+ 0.3246726087378194,
+ 0.32944710145063694,
+ 0.3342215895880525,
+ 0.33899607308376484,
+ 0.3437705518714731,
+ 0.34854502588487685,
+ 0.3533194950576761,
+ 0.35809395932357113,
+ 0.36286841861626273,
+ 0.3676428728694522,
+ 0.372417322016841,
+ 0.3771917659921313,
+ 0.3819662047290255,
+ 0.38674063816122645,
+ 0.39151506622243754,
+ 0.39628948884636267,
+ 0.4010639059667059,
+ 0.40583831751717203,
+ 0.41061272343146626,
+ 0.41538712364329416,
+ 0.4201615180863619,
+ 0.424935906694376,
+ 0.42971028940104355,
+ 0.4344846661400723,
+ 0.4392590368451701,
+ 0.4440334014500455,
+ 0.44880775988840776,
+ 0.4535821120939664,
+ 0.4583564580004315,
+ 0.46313079754151376,
+ 0.4679051306509241,
+ 0.4726794572623747,
+ 0.47745377730957744,
+ 0.48222809072624506,
+ 0.48700239744609125,
+ 0.49177669740282953,
+ 0.4965509905301746,
+ 0.5013252767618416,
+ 0.5060995560315458,
+ 0.5108738282730035,
+ 0.5156480934199319,
+ 0.5204223514060476,
+ 0.5251966021650691,
+ 0.529970845630715,
+ 0.5347450817367042,
+ 0.5395193104167566,
+ 0.5442935316045925,
+ 0.5490677452339332,
+ 0.5538419512385,
+ 0.5586161495520156,
+ 0.5633903401082025,
+ 0.5681645228407844,
+ 0.5729386976834859,
+ 0.5777128645700316,
+ 0.5824870234341468,
+ 0.5872611742095583,
+ 0.5920353168299926,
+ 0.5968094512291771,
+ 0.6015835773408406,
+ 0.6063576950987116,
+ 0.6111318044365199,
+ 0.6159059052879959,
+ 0.6206799975868706,
+ 0.6254540812668758,
+ 0.6302281562617439,
+ 0.6350022225052082,
+ 0.6397762799310026,
+ 0.6445503284728616,
+ 0.6493243680645211,
+ 0.6540983986397167,
+ 0.6588724201321855,
+ 0.6636464324756655,
+ 0.6684204356038944,
+ 0.6731944294506121,
+ 0.6779684139495583,
+ 0.6827423890344736,
+ 0.6875163546390998,
+ 0.6922903106971791,
+ 0.6970642571424543,
+ 0.7018381939086699,
+ 0.7066121209295704,
+ 0.711386038138901,
+ 0.7161599454704085,
+ 0.7209338428578398,
+ 0.7257077302349431,
+ 0.7304816075354671,
+ 0.7352554746931614,
+ 0.7400293316417766,
+ 0.7448031783150643,
+ 0.7495770146467764,
+ 0.7543508405706661,
+ 0.7591246560204874,
+ 0.7638984609299951,
+ 0.7686722552329448,
+ 0.7734460388630932,
+ 0.7782198117541979,
+ 0.7829935738400169,
+ 0.7877673250543098,
+ 0.7925410653308368,
+ 0.7973147946033585,
+ 0.8020885128056375,
+ 0.8068622198714367,
+ 0.8116359157345193,
+ 0.8164096003286508,
+ 0.8211832735875968,
+ 0.8259569354451235,
+ 0.830730585834999,
+ 0.8355042246909917,
+ 0.8402778519468711,
+ 0.8450514675364078,
+ 0.8498250713933732,
+ 0.8545986634515397,
+ 0.8593722436446808,
+ 0.864145811906571,
+ 0.8689193681709857,
+ 0.8736929123717011,
+ 0.8784664444424949,
+ 0.8832399643171452,
+ 0.8880134719294318,
+ 0.892786967213135,
+ 0.897560450102036,
+ 0.9023339205299178,
+ 0.9071073784305639,
+ 0.9118808237377585,
+ 0.9166542563852877,
+ 0.9214276763069379,
+ 0.9262010834364973,
+ 0.9309744777077542,
+ 0.9357478590544985,
+ 0.9405212274105219,
+ 0.9452945827096156,
+ 0.9500679248855731,
+ 0.9548412538721889,
+ 0.9596145696032577,
+ 0.9643878720125764,
+ 0.9691611610339427,
+ 0.9739344366011552,
+ 0.9787076986480131,
+ 0.983480947108318,
+ 0.9882541819158717,
+ 0.9930274030044769,
+ 0.9978006103079389,
+ 1.0025738037600627,
+ 1.0073469832946544,
+ 1.0121201488455225,
+ 1.0168933003464757,
+ 1.021666437731324,
+ 1.026439560933879,
+ 1.031212669887953,
+ 1.0359857645273594,
+ 1.0407588447859133,
+ 1.0455319105974308,
+ 1.050304961895729,
+ 1.0550779986146266,
+ 1.0598510206879428,
+ 1.0646240280494992,
+ 1.0693970206331174,
+ 1.0741699983726205,
+ 1.0789429612018338,
+ 1.0837159090545827,
+ 1.088488841864694,
+ 1.0932617595659966,
+ 1.09803466209232,
+ 1.1028075493774945,
+ 1.1075804213553526,
+ 1.1123532779597283,
+ 1.1171261191244548,
+ 1.1218989447833692,
+ 1.1266717548703085,
+ 1.131444549319111,
+ 1.1362173280636163,
+ 1.1409900910376667,
+ 1.1457628381751035,
+ 1.1505355694097708,
+ 1.155308284675514,
+ 1.160080983906179,
+ 1.1648536670356138,
+ 1.169626333997668,
+ 1.1743989847261913,
+ 1.1791716191550357,
+ 1.1839442372180549,
+ 1.1887168388491027,
+ 1.193489423982035,
+ 1.1982619925507096,
+ 1.203034544488985,
+ 1.2078070797307208,
+ 1.212579598209779,
+ 1.2173520998600218,
+ 1.222124584615314,
+ 1.2268970524095206,
+ 1.2316695031765093,
+ 1.2364419368501478,
+ 1.2412143533643065,
+ 1.245986752652857,
+ 1.250759134649671,
+ 1.2555314992886235,
+ 1.2603038465035896,
+ 1.2650761762284468,
+ 1.2698484883970735,
+ 1.2746207829433494,
+ 1.2793930598011563,
+ 1.284165318904377,
+ 1.2889375601868953,
+ 1.2937097835825981,
+ 1.2984819890253725,
+ 1.3032541764491066,
+ 1.3080263457876915,
+ 1.3127984969750188,
+ 1.317570629944982,
+ 1.3223427446314757,
+ 1.3271148409683968,
+ 1.3318869188896427,
+ 1.3366589783291132,
+ 1.3414310192207095,
+ 1.3462030414983333,
+ 1.3509750450958895,
+ 1.3557470299472838,
+ 1.3605189959864226,
+ 1.3652909431472153,
+ 1.3700628713635725,
+ 1.3748347805694052,
+ 1.3796066706986276,
+ 1.3843785416851553,
+ 1.3891503934629035,
+ 1.3939222259657913,
+ 1.3986940391277392,
+ 1.4034658328826675,
+ 1.4082376071645,
+ 1.4130093619071615,
+ 1.417781097044578,
+ 1.4225528125106777,
+ 1.42732450823939,
+ 1.4320961841646465,
+ 1.4368678402203796,
+ 1.4416394763405245,
+ 1.4464110924590172,
+ 1.4511826885097951,
+ 1.4559542644267984,
+ 1.4607258201439681,
+ 1.4654973555952469,
+ 1.4702688707145795,
+ 1.4750403654359123,
+ 1.479811839693193,
+ 1.484583293420372,
+ 1.4893547265513998,
+ 1.4941261390202298,
+ 1.498897530760817,
+ 1.5036689017071179,
+ 1.5084402517930908,
+ 1.5132115809526954,
+ 1.5179828891198937,
+ 1.5227541762286492,
+ 1.527525442212927,
+ 1.5322966870066943,
+ 1.5370679105439198,
+ 1.541839112758574,
+ 1.546610293584629,
+ 1.5513814529560592,
+ 1.5561525908068405,
+ 1.5609237070709503,
+ 1.565694801682368,
+ 1.5704658745750752,
+ 1.5752369256830545,
+ 1.5800079549402912,
+ 1.584778962280772,
+ 1.589549947638485,
+ 1.5943209109474206,
+ 1.5990918521415713,
+ 1.603862771154931,
+ 1.6086336679214952,
+ 1.6134045423752623,
+ 1.618175394450231,
+ 1.6229462240804031,
+ 1.6277170311997824,
+ 1.632487815742373,
+ 1.6372585776421829,
+ 1.6420293168332207,
+ 1.6468000332494968,
+ 1.6515707268250241,
+ 1.6563413974938177,
+ 1.6611120451898935,
+ 1.66588266984727,
+ 1.6706532713999678,
+ 1.6754238497820089,
+ 1.6801944049274176,
+ 1.6849649367702197,
+ 1.6897354452444437,
+ 1.6945059302841192,
+ 1.6992763918232783,
+ 1.704046829795955,
+ 1.7088172441361846,
+ 1.7135876347780055,
+ 1.7183580016554572,
+ 1.7231283447025816,
+ 1.7278986638534224,
+ 1.7326689590420248,
+ 1.7374392302024373,
+ 1.7422094772687091,
+ 1.7469797001748921,
+ 1.75174989885504,
+ 1.7565200732432085,
+ 1.761290223273455,
+ 1.7660603488798399,
+ 1.7708304499964247,
+ 1.775600526557273,
+ 1.780370578496451,
+ 1.7851406057480266,
+ 1.7899106082460694,
+ 1.7946805859246517,
+ 1.799450538717848,
+ 1.8042204665597337,
+ 1.8089903693843872,
+ 1.8137602471258893,
+ 1.8185300997183222,
+ 1.8232999270957697,
+ 1.8280697291923194,
+ 1.8328395059420592,
+ 1.8376092572790808,
+ 1.8423789831374753,
+ 1.8471486834513395,
+ 1.8519183581547705,
+ 1.8566880071818657,
+ 1.861457630466729,
+ 1.8662272279434622,
+ 1.870996799546171,
+ 1.8757663452089643,
+ 1.8805358648659518,
+ 1.885305358451244,
+ 1.8900748258989577,
+ 1.8948442671432082,
+ 1.8996136821181133,
+ 1.9043830707577951,
+ 1.9091524329963767,
+ 1.913921768767982,
+ 1.9186910780067397,
+ 1.9234603606467788,
+ 1.9282296166222308,
+ 1.9329988458672311,
+ 1.9377680483159143,
+ 1.94253722390242,
+ 1.947306372560889,
+ 1.952075494225463,
+ 1.9568445888302883,
+ 1.9616136563095126,
+ 1.9663826965972846,
+ 1.9711517096277562,
+ 1.9759206953350827,
+ 1.98068965365342,
+ 1.9854585845169266,
+ 1.9902274878597643,
+ 1.9949963636160954,
+ 1.999765211720086,
+ 2.004534032105904,
+ 2.0093028247077203,
+ 2.0140715894597063,
+ 2.0188403262960377,
+ 2.0236090351508906,
+ 2.0283777159584453,
+ 2.0331463686528837,
+ 2.0379149931683895,
+ 2.0426835894391493,
+ 2.047452157399352,
+ 2.0522206969831887,
+ 2.0569892081248526,
+ 2.0617576907585407,
+ 2.0665261448184498,
+ 2.071294570238781,
+ 2.076062966953738,
+ 2.0808313348975256,
+ 2.0855996740043516,
+ 2.090367984208426,
+ 2.095136265443962,
+ 2.099904517645174,
+ 2.1046727407462793,
+ 2.109440934681498,
+ 2.114209099385052,
+ 2.118977234791166,
+ 2.1237453408340685,
+ 2.1285134174479867,
+ 2.133281464567154,
+ 2.1380494821258043,
+ 2.142817470058174,
+ 2.147585428298503,
+ 2.1523533567810342,
+ 2.1571212554400097,
+ 2.161889124209677,
+ 2.1666569630242867,
+ 2.1714247718180886,
+ 2.1761925505253368,
+ 2.1809602990802897,
+ 2.185728017417205,
+ 2.190495705470345,
+ 2.195263363173974,
+ 2.2000309904623583,
+ 2.2047985872697673,
+ 2.209566153530473,
+ 2.2143336891787486,
+ 2.219101194148873,
+ 2.223868668375124,
+ 2.2286361117917837,
+ 2.233403524333137,
+ 2.238170905933471,
+ 2.2429382565270743,
+ 2.247705576048241,
+ 2.252472864431264,
+ 2.257240121610441,
+ 2.2620073475200733,
+ 2.266774542094462,
+ 2.2715417052679125,
+ 2.2763088369747333,
+ 2.281075937149234,
+ 2.2858430057257273,
+ 2.2906100426385296,
+ 2.2953770478219586,
+ 2.3001440212103352,
+ 2.304910962737983,
+ 2.3096778723392286,
+ 2.3144447499483993,
+ 2.319211595499828,
+ 2.3239784089278483,
+ 2.328745190166796,
+ 2.333511939151012,
+ 2.3382786558148383,
+ 2.3430453400926177,
+ 2.3478119919187,
+ 2.3525786112274347,
+ 2.357345197953174,
+ 2.3621117520302737,
+ 2.366878273393092,
+ 2.3716447619759897,
+ 2.3764112177133314,
+ 2.381177640539483,
+ 2.3859440303888126,
+ 2.3907103871956936,
+ 2.3954767108944997,
+ 2.4002430014196086,
+ 2.4050092587054004,
+ 2.4097754826862574,
+ 2.414541673296566,
+ 2.4193078304707143,
+ 2.424073954143093,
+ 2.4288400442480964,
+ 2.4336061007201217,
+ 2.438372123493567,
+ 2.4431381125028357,
+ 2.447904067682334,
+ 2.4526699889664667,
+ 2.457435876289647,
+ 2.4622017295862877,
+ 2.4669675487908047,
+ 2.471733333837618,
+ 2.476499084661149,
+ 2.481264801195823,
+ 2.4860304833760667,
+ 2.490796131136312,
+ 2.4955617444109905,
+ 2.50032732313454,
+ 2.5050928672413995,
+ 2.50985837666601,
+ 2.5146238513428165,
+ 2.519389291206267,
+ 2.5241546961908132,
+ 2.528920066230907,
+ 2.5336854012610046,
+ 2.5384507012155666,
+ 2.543215966029054,
+ 2.547981195635933,
+ 2.552746389970671,
+ 2.5575115489677387,
+ 2.56227667256161,
+ 2.5670417606867626,
+ 2.571806813277675,
+ 2.5765718302688305,
+ 2.581336811594715,
+ 2.5861017571898164,
+ 2.5908666669886267,
+ 2.5956315409256403,
+ 2.6003963789353546,
+ 2.60516118095227,
+ 2.60992594691089,
+ 2.614690676745721,
+ 2.619455370391272,
+ 2.624220027782057,
+ 2.6289846488525894,
+ 2.6337492335373884,
+ 2.638513781770976,
+ 2.643278293487876,
+ 2.6480427686226156,
+ 2.6528072071097264,
+ 2.65757160888374,
+ 2.662335973879195,
+ 2.6671003020306303,
+ 2.6718645932725877,
+ 2.6766288475396145,
+ 2.681393064766259,
+ 2.6861572448870716,
+ 2.6909213878366094,
+ 2.695685493549429,
+ 2.7004495619600917,
+ 2.705213593003162,
+ 2.709977586613207,
+ 2.7147415427247963,
+ 2.719505461272505,
+ 2.724269342190909,
+ 2.7290331854145866,
+ 2.7337969908781226,
+ 2.738560758516102,
+ 2.743324488263113,
+ 2.74808818005375,
+ 2.752851833822607,
+ 2.7576154495042817,
+ 2.762379027033378,
+ 2.7671425663444986,
+ 2.771906067372252,
+ 2.77666953005125,
+ 2.7814329543161067,
+ 2.7861963401014385,
+ 2.7909596873418674,
+ 2.795722995972017,
+ 2.800486265926513,
+ 2.8052494971399877,
+ 2.8100126895470736,
+ 2.814775843082407,
+ 2.8195389576806282,
+ 2.8243020332763806,
+ 2.8290650698043094,
+ 2.8338280671990654,
+ 2.838591025395301,
+ 2.843353944327672,
+ 2.8481168239308388,
+ 2.852879664139462,
+ 2.8576424648882086,
+ 2.862405226111748,
+ 2.8671679477447514,
+ 2.871930629721895,
+ 2.876693271977858,
+ 2.8814558744473224,
+ 2.886218437064973,
+ 2.8909809597655,
+ 2.895743442483594,
+ 2.900505885153951,
+ 2.90526828771127,
+ 2.9100306500902517,
+ 2.914792972225603,
+ 2.919555254052032,
+ 2.9243174955042504,
+ 2.9290796965169736,
+ 2.9338418570249205,
+ 2.938603976962813,
+ 2.943366056265376,
+ 2.9481280948673394,
+ 2.952890092703434,
+ 2.957652049708396,
+ 2.9624139658169644,
+ 2.9671758409638804,
+ 2.97193767508389,
+ 2.9766994681117436,
+ 2.981461219982192,
+ 2.986222930629991,
+ 2.9909845999899005,
+ 2.995746227996683,
+ 3.0005078145851045,
+ 3.005269359689934,
+ 3.010030863245945,
+ 3.014792325187913,
+ 3.019553745450619,
+ 3.0243151239688455,
+ 3.029076460677379,
+ 3.033837755511009,
+ 3.038599008404531,
+ 3.0433602192927403,
+ 3.048121388110438,
+ 3.0528825147924286,
+ 3.057643599273518,
+ 3.0624046414885187,
+ 3.067165641372245,
+ 3.0719265988595135,
+ 3.076687513885147,
+ 3.0814483863839706,
+ 3.0862092162908112,
+ 3.090970003540502,
+ 3.0957307480678793,
+ 3.10049144980778,
+ 3.1052521086950478,
+ 3.110012724664529,
+ 3.114773297651073,
+ 3.119533827589533,
+ 3.1242943144147666,
+ 3.129054758061632,
+ 3.1338151584649956,
+ 3.138575515559723,
+ 3.1433358292806854,
+ 3.148096099562759,
+ 3.152856326340821,
+ 3.1576165095497517,
+ 3.162376649124439,
+ 3.167136744999771,
+ 3.1718967971106387,
+ 3.176656805391941,
+ 3.181416769778576,
+ 3.1861766902054476,
+ 3.190936566607463,
+ 3.1956963989195333,
+ 3.200456187076571,
+ 3.2052159310134973,
+ 3.2099756306652316,
+ 3.214735285966699,
+ 3.21949489685283,
+ 3.224254463258556,
+ 3.229013985118813,
+ 3.233773462368543,
+ 3.238532894942688,
+ 3.243292282776195,
+ 3.248051625804017,
+ 3.2528109239611074,
+ 3.2575701771824237,
+ 3.2623293854029307,
+ 3.2670885485575925,
+ 3.2718476665813783,
+ 3.276606739409263,
+ 3.2813657669762226,
+ 3.2861247492172367,
+ 3.2908836860672928,
+ 3.2956425774613773,
+ 3.300401423334482,
+ 3.3051602236216038,
+ 3.309918978257741,
+ 3.314677687177898,
+ 3.3194363503170816,
+ 3.324194967610302,
+ 3.3289535389925744,
+ 3.333712064398917,
+ 3.3384705437643523,
+ 3.3432289770239065,
+ 3.3479873641126088,
+ 3.352745704965493,
+ 3.357503999517597,
+ 3.3622622477039616,
+ 3.3670204494596323,
+ 3.371778604719657,
+ 3.37653671341909,
+ 3.3812947754929863,
+ 3.3860527908764073,
+ 3.3908107595044177,
+ 3.3955686813120844,
+ 3.40032655623448,
+ 3.405084384206681,
+ 3.409842165163766,
+ 3.414599899040819,
+ 3.419357585772928,
+ 3.4241152252951843,
+ 3.4288728175426826,
+ 3.433630362450522,
+ 3.4383878599538065,
+ 3.4431453099876426,
+ 3.447902712487141,
+ 3.452660067387417,
+ 3.4574173746235877,
+ 3.462174634130778,
+ 3.466931845844114,
+ 3.4716890096987254,
+ 3.4764461256297468,
+ 3.481203193572317,
+ 3.485960213461579,
+ 3.4907171852326777,
+ 3.495474108820765,
+ 3.5002309841609938,
+ 3.504987811188523,
+ 3.509744589838515,
+ 3.5145013200461355,
+ 3.519258001746555,
+ 3.524014634874949,
+ 3.528771219366493,
+ 3.5335277551563706,
+ 3.5382842421797696,
+ 3.5430406803718775,
+ 3.5477970696678907,
+ 3.5525534100030067,
+ 3.5573097013124277,
+ 3.56206594353136,
+ 3.5668221365950146,
+ 3.5715782804386054,
+ 3.576334374997351,
+ 3.5810904202064746,
+ 3.5858464160012016,
+ 3.590602362316765,
+ 3.595358259088398,
+ 3.6001141062513375,
+ 3.604869903740831,
+ 3.6096256514921223,
+ 3.614381349440463,
+ 3.6191369975211094,
+ 3.6238925956693198,
+ 3.628648143820357,
+ 3.6334036419094917,
+ 3.6381590898719924,
+ 3.642914487643136,
+ 3.647669835158203,
+ 3.652425132352477,
+ 3.657180379161246,
+ 3.661935575519803,
+ 3.666690721363443,
+ 3.671445816627471,
+ 3.676200861247186,
+ 3.680955855157901,
+ 3.685710798294928,
+ 3.690465690593584,
+ 3.695220531989191,
+ 3.699975322417077,
+ 3.7047300618125667,
+ 3.709484750110998,
+ 3.71423938724771,
+ 3.7189939731580433,
+ 3.723748507777344,
+ 3.728502991040966,
+ 3.7332574228842614,
+ 3.7380118032425913,
+ 3.742766132051321,
+ 3.7475204092458156,
+ 3.7522746347614473,
+ 3.757028808533596,
+ 3.7617829304976382,
+ 3.7665370005889605,
+ 3.7712910187429536,
+ 3.7760449848950093,
+ 3.780798898980525,
+ 3.785552760934905,
+ 3.7903065706935526,
+ 3.79506032819188,
+ 3.7998140333653043,
+ 3.8045676861492406,
+ 3.809321286479114,
+ 3.814074834290355,
+ 3.8188283295183916,
+ 3.8235817720986627,
+ 3.8283351619666095,
+ 3.833088499057676,
+ 3.837841783307312,
+ 3.842595014650972,
+ 3.847348193024113,
+ 3.852101318362198,
+ 3.856854390600695,
+ 3.861607409675074,
+ 3.8663603755208107,
+ 3.8711132880733867,
+ 3.8758661472682845,
+ 3.880618953040993,
+ 3.8853717053270063,
+ 3.8901244040618224,
+ 3.8948770491809412,
+ 3.899629640619871,
+ 3.9043821783141235,
+ 3.90913466219921,
+ 3.913887092210654,
+ 3.9186394682839785,
+ 3.9233917903547106,
+ 3.9281440583583853,
+ 3.9328962722305385,
+ 3.9376484319067124,
+ 3.942400537322454,
+ 3.9471525884133127,
+ 3.951904585114845,
+ 3.9566565273626093,
+ 3.961408415092172,
+ 3.966160248239098,
+ 3.9709120267389633,
+ 3.975663750527346,
+ 3.9804154195398254,
+ 3.98516703371199,
+ 3.989918592979431,
+ 3.9946700972777434,
+ 3.999421546542527,
+ 4.004172940709388,
+ 4.008924279713933,
+ 4.013675563491778,
+ 4.01842679197854,
+ 4.023177965109842,
+ 4.027929082821312,
+ 4.03268014504858,
+ 4.037431151727286,
+ 4.042182102793067,
+ 4.04693299818157,
+ 4.051683837828445,
+ 4.056434621669348,
+ 4.0611853496399375,
+ 4.065936021675876,
+ 4.070686637712834,
+ 4.075437197686483,
+ 4.080187701532502,
+ 4.084938149186572,
+ 4.089688540584381,
+ 4.094438875661618,
+ 4.099189154353982,
+ 4.103939376597174,
+ 4.108689542326896,
+ 4.113439651478862,
+ 4.118189703988784,
+ 4.12293969979238,
+ 4.1276896388253785,
+ 4.132439521023504,
+ 4.137189346322492,
+ 4.141939114658079,
+ 4.146688825966009,
+ 4.151438480182029,
+ 4.1561880772418895,
+ 4.160937617081348,
+ 4.165687099636167,
+ 4.170436524842112,
+ 4.175185892634952,
+ 4.179935202950464,
+ 4.184684455724429,
+ 4.189433650892629,
+ 4.194182788390857,
+ 4.198931868154905,
+ 4.203680890120574,
+ 4.208429854223666,
+ 4.21317876039999,
+ 4.217927608585359,
+ 4.222676398715594,
+ 4.227425130726513,
+ 4.2321738045539465,
+ 4.236922420133728,
+ 4.241670977401691,
+ 4.24641947629368,
+ 4.251167916745542,
+ 4.255916298693128,
+ 4.260664622072292,
+ 4.265412886818899,
+ 4.270161092868811,
+ 4.274909240157902,
+ 4.279657328622045,
+ 4.284405358197123,
+ 4.289153328819018,
+ 4.293901240423623,
+ 4.298649092946831,
+ 4.303396886324542,
+ 4.30814462049266,
+ 4.312892295387097,
+ 4.317639910943763,
+ 4.322387467098581,
+ 4.327134963787472,
+ 4.331882400946366,
+ 4.336629778511198,
+ 4.341377096417904,
+ 4.34612435460243,
+ 4.350871553000723,
+ 4.355618691548736,
+ 4.360365770182427,
+ 4.365112788837761,
+ 4.369859747450705,
+ 4.37460664595723,
+ 4.379353484293316,
+ 4.384100262394946,
+ 4.388846980198105,
+ 4.393593637638789,
+ 4.398340234652993,
+ 4.40308677117672,
+ 4.407833247145979,
+ 4.412579662496782,
+ 4.417326017165144,
+ 4.4220723110870885,
+ 4.426818544198645,
+ 4.431564716435844,
+ 4.436310827734722,
+ 4.441056878031323,
+ 4.445802867261693,
+ 4.450548795361884,
+ 4.455294662267956,
+ 4.460040467915967,
+ 4.464786212241987,
+ 4.469531895182088,
+ 4.4742775166723465,
+ 4.479023076648846,
+ 4.483768575047674,
+ 4.488514011804921,
+ 4.4932593868566855,
+ 4.498004700139072,
+ 4.502749951588184,
+ 4.5074951411401365,
+ 4.512240268731049,
+ 4.516985334297041,
+ 4.52173033777424,
+ 4.526475279098784,
+ 4.531220158206804,
+ 4.535964975034448,
+ 4.540709729517864,
+ 4.545454421593201,
+ 4.550199051196622,
+ 4.554943618264289,
+ 4.55968812273237,
+ 4.5644325645370385,
+ 4.569176943614475,
+ 4.573921259900861,
+ 4.578665513332388,
+ 4.58340970384525,
+ 4.588153831375644,
+ 4.5928978958597755,
+ 4.597641897233856,
+ 4.602385835434099,
+ 4.607129710396724,
+ 4.611873522057959,
+ 4.616617270354029,
+ 4.621360955221173,
+ 4.626104576595633,
+ 4.630848134413652,
+ 4.635591628611481,
+ 4.64033505912538,
+ 4.645078425891606,
+ 4.649821728846429,
+ 4.65456496792612,
+ 4.659308143066955,
+ 4.664051254205216,
+ 4.6687943012771935,
+ 4.673537284219177,
+ 4.678280202967467,
+ 4.683023057458366,
+ 4.687765847628181,
+ 4.692508573413228,
+ 4.697251234749826,
+ 4.701993831574297,
+ 4.706736363822971,
+ 4.711478831432188,
+ 4.71622123433828,
+ 4.720963572477598,
+ 4.725705845786492,
+ 4.730448054201316,
+ 4.735190197658433,
+ 4.739932276094209,
+ 4.744674289445015,
+ 4.749416237647231,
+ 4.7541581206372365,
+ 4.758899938351422
+ ],
+ "yaxis": "y"
+ }
+ ],
+ "layout": {
+ "legend": {
+ "tracegroupgap": 0
+ },
+ "template": {
+ "data": {
+ "bar": [
+ {
+ "error_x": {
+ "color": "#f2f5fa"
+ },
+ "error_y": {
+ "color": "#f2f5fa"
+ },
+ "marker": {
+ "line": {
+ "color": "rgb(17,17,17)",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "bar"
+ }
+ ],
+ "barpolar": [
+ {
+ "marker": {
+ "line": {
+ "color": "rgb(17,17,17)",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "barpolar"
+ }
+ ],
+ "carpet": [
+ {
+ "aaxis": {
+ "endlinecolor": "#A2B1C6",
+ "gridcolor": "#506784",
+ "linecolor": "#506784",
+ "minorgridcolor": "#506784",
+ "startlinecolor": "#A2B1C6"
+ },
+ "baxis": {
+ "endlinecolor": "#A2B1C6",
+ "gridcolor": "#506784",
+ "linecolor": "#506784",
+ "minorgridcolor": "#506784",
+ "startlinecolor": "#A2B1C6"
+ },
+ "type": "carpet"
+ }
+ ],
+ "choropleth": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "choropleth"
+ }
+ ],
+ "contour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "contour"
+ }
+ ],
+ "contourcarpet": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "contourcarpet"
+ }
+ ],
+ "heatmap": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "heatmap"
+ }
+ ],
+ "heatmapgl": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "heatmapgl"
+ }
+ ],
+ "histogram": [
+ {
+ "marker": {
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "histogram"
+ }
+ ],
+ "histogram2d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2d"
+ }
+ ],
+ "histogram2dcontour": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "histogram2dcontour"
+ }
+ ],
+ "mesh3d": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "type": "mesh3d"
+ }
+ ],
+ "parcoords": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "parcoords"
+ }
+ ],
+ "pie": [
+ {
+ "automargin": true,
+ "type": "pie"
+ }
+ ],
+ "scatter": [
+ {
+ "marker": {
+ "line": {
+ "color": "#283442"
+ }
+ },
+ "type": "scatter"
+ }
+ ],
+ "scatter3d": [
+ {
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatter3d"
+ }
+ ],
+ "scattercarpet": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattercarpet"
+ }
+ ],
+ "scattergeo": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattergeo"
+ }
+ ],
+ "scattergl": [
+ {
+ "marker": {
+ "line": {
+ "color": "#283442"
+ }
+ },
+ "type": "scattergl"
+ }
+ ],
+ "scattermapbox": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scattermapbox"
+ }
+ ],
+ "scatterpolar": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolar"
+ }
+ ],
+ "scatterpolargl": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterpolargl"
+ }
+ ],
+ "scatterternary": [
+ {
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "type": "scatterternary"
+ }
+ ],
+ "surface": [
+ {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "type": "surface"
+ }
+ ],
+ "table": [
+ {
+ "cells": {
+ "fill": {
+ "color": "#506784"
+ },
+ "line": {
+ "color": "rgb(17,17,17)"
+ }
+ },
+ "header": {
+ "fill": {
+ "color": "#2a3f5f"
+ },
+ "line": {
+ "color": "rgb(17,17,17)"
+ }
+ },
+ "type": "table"
+ }
+ ]
+ },
+ "layout": {
+ "annotationdefaults": {
+ "arrowcolor": "#f2f5fa",
+ "arrowhead": 0,
+ "arrowwidth": 1
+ },
+ "autotypenumbers": "strict",
+ "coloraxis": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "colorscale": {
+ "diverging": [
+ [
+ 0,
+ "#8e0152"
+ ],
+ [
+ 0.1,
+ "#c51b7d"
+ ],
+ [
+ 0.2,
+ "#de77ae"
+ ],
+ [
+ 0.3,
+ "#f1b6da"
+ ],
+ [
+ 0.4,
+ "#fde0ef"
+ ],
+ [
+ 0.5,
+ "#f7f7f7"
+ ],
+ [
+ 0.6,
+ "#e6f5d0"
+ ],
+ [
+ 0.7,
+ "#b8e186"
+ ],
+ [
+ 0.8,
+ "#7fbc41"
+ ],
+ [
+ 0.9,
+ "#4d9221"
+ ],
+ [
+ 1,
+ "#276419"
+ ]
+ ],
+ "sequential": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ],
+ "sequentialminus": [
+ [
+ 0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1,
+ "#f0f921"
+ ]
+ ]
+ },
+ "colorway": [
+ "#636efa",
+ "#EF553B",
+ "#00cc96",
+ "#ab63fa",
+ "#FFA15A",
+ "#19d3f3",
+ "#FF6692",
+ "#B6E880",
+ "#FF97FF",
+ "#FECB52"
+ ],
+ "font": {
+ "color": "#f2f5fa"
+ },
+ "geo": {
+ "bgcolor": "rgb(17,17,17)",
+ "lakecolor": "rgb(17,17,17)",
+ "landcolor": "rgb(17,17,17)",
+ "showlakes": true,
+ "showland": true,
+ "subunitcolor": "#506784"
+ },
+ "hoverlabel": {
+ "align": "left"
+ },
+ "hovermode": "closest",
+ "mapbox": {
+ "style": "dark"
+ },
+ "paper_bgcolor": "rgb(17,17,17)",
+ "plot_bgcolor": "rgb(17,17,17)",
+ "polar": {
+ "angularaxis": {
+ "gridcolor": "#506784",
+ "linecolor": "#506784",
+ "ticks": ""
+ },
+ "bgcolor": "rgb(17,17,17)",
+ "radialaxis": {
+ "gridcolor": "#506784",
+ "linecolor": "#506784",
+ "ticks": ""
+ }
+ },
+ "scene": {
+ "xaxis": {
+ "backgroundcolor": "rgb(17,17,17)",
+ "gridcolor": "#506784",
+ "gridwidth": 2,
+ "linecolor": "#506784",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#C8D4E3"
+ },
+ "yaxis": {
+ "backgroundcolor": "rgb(17,17,17)",
+ "gridcolor": "#506784",
+ "gridwidth": 2,
+ "linecolor": "#506784",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#C8D4E3"
+ },
+ "zaxis": {
+ "backgroundcolor": "rgb(17,17,17)",
+ "gridcolor": "#506784",
+ "gridwidth": 2,
+ "linecolor": "#506784",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "#C8D4E3"
+ }
+ },
+ "shapedefaults": {
+ "line": {
+ "color": "#f2f5fa"
+ }
+ },
+ "sliderdefaults": {
+ "bgcolor": "#C8D4E3",
+ "bordercolor": "rgb(17,17,17)",
+ "borderwidth": 1,
+ "tickwidth": 0
+ },
+ "ternary": {
+ "aaxis": {
+ "gridcolor": "#506784",
+ "linecolor": "#506784",
+ "ticks": ""
+ },
+ "baxis": {
+ "gridcolor": "#506784",
+ "linecolor": "#506784",
+ "ticks": ""
+ },
+ "bgcolor": "rgb(17,17,17)",
+ "caxis": {
+ "gridcolor": "#506784",
+ "linecolor": "#506784",
+ "ticks": ""
+ }
+ },
+ "title": {
+ "x": 0.05
+ },
+ "updatemenudefaults": {
+ "bgcolor": "#506784",
+ "borderwidth": 0
+ },
+ "xaxis": {
+ "automargin": true,
+ "gridcolor": "#283442",
+ "linecolor": "#506784",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#283442",
+ "zerolinewidth": 2
+ },
+ "yaxis": {
+ "automargin": true,
+ "gridcolor": "#283442",
+ "linecolor": "#506784",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "#283442",
+ "zerolinewidth": 2
+ }
+ }
+ },
+ "title": {
+ "text": "FINCH Eye Pointing Accuracy Constraint vs. Spatial Resolution"
+ },
+ "xaxis": {
+ "anchor": "y",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "Spatial Resolution [m]"
+ }
+ },
+ "yaxis": {
+ "anchor": "x",
+ "domain": [
+ 0,
+ 1
+ ],
+ "title": {
+ "text": "Pointing Accuracy Constraint [deg]"
+ }
+ }
+ }
+ }
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Spatial Resolution [m] | \n",
+ " Pointing Accuracy Constraint [deg] | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 0.0 | \n",
+ " 0.000000 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 100.0 | \n",
+ " 0.004775 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 200.0 | \n",
+ " 0.009549 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 300.0 | \n",
+ " 0.014324 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 400.0 | \n",
+ " 0.019099 | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 995 | \n",
+ " 99500.0 | \n",
+ " 4.739932 | \n",
+ "
\n",
+ " \n",
+ " | 996 | \n",
+ " 99600.0 | \n",
+ " 4.744674 | \n",
+ "
\n",
+ " \n",
+ " | 997 | \n",
+ " 99700.0 | \n",
+ " 4.749416 | \n",
+ "
\n",
+ " \n",
+ " | 998 | \n",
+ " 99800.0 | \n",
+ " 4.754158 | \n",
+ "
\n",
+ " \n",
+ " | 999 | \n",
+ " 99900.0 | \n",
+ " 4.758900 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
1000 rows × 2 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Spatial Resolution [m] Pointing Accuracy Constraint [deg]\n",
+ "0 0.0 0.000000\n",
+ "1 100.0 0.004775\n",
+ "2 200.0 0.009549\n",
+ "3 300.0 0.014324\n",
+ "4 400.0 0.019099\n",
+ ".. ... ...\n",
+ "995 99500.0 4.739932\n",
+ "996 99600.0 4.744674\n",
+ "997 99700.0 4.749416\n",
+ "998 99800.0 4.754158\n",
+ "999 99900.0 4.758900\n",
+ "\n",
+ "[1000 rows x 2 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "spatial_resolution_label = f\"Spatial Resolution [{spatial_resolution.unit}]\"\n",
+ "pointing_constraint_label = f\"Pointing Accuracy Constraint [{pointing_constraint.unit}]\"\n",
+ "\n",
+ "data = {\n",
+ " spatial_resolution_label: spatial_resolution,\n",
+ " pointing_constraint_label: pointing_constraint,\n",
+ "}\n",
+ "\n",
+ "df = pd.DataFrame.from_dict(data=data)\n",
+ "graph = plot.line(\n",
+ " df=df,\n",
+ " x=spatial_resolution_label,\n",
+ " y=pointing_constraint_label,\n",
+ " title=\"FINCH Eye Pointing Accuracy Constraint vs. Spatial Resolution\",\n",
+ " dark=True,\n",
+ ")\n",
+ "\n",
+ "graph.show()\n",
+ "display(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "interpreter": {
+ "hash": "a051636751d8b8c3fb678ae2c2b84596f57742a247cc1675aae9ee3b371aaacc"
+ },
+ "kernelspec": {
+ "display_name": "Python 3.10.4 ('.venv': poetry)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.4"
+ },
+ "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/notebooks/tradebook_template.ipynb b/notebooks/tradebook_template.ipynb
new file mode 100644
index 0000000..0965472
--- /dev/null
+++ b/notebooks/tradebook_template.ipynb
@@ -0,0 +1,129 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Tradebook Template\n",
+ "Use this notebook as a template to create a tradebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# imports"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Setup\n",
+ "Run this section onwards when a parameter is updated."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# region constants\n",
+ "\n",
+ "# endregion\n",
+ "\n",
+ "\n",
+ "# region variables\n",
+ "\n",
+ "# endregion"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Artifact Instantiation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# region components\n",
+ "\n",
+ "# endregion\n",
+ "\n",
+ "\n",
+ "# region systems\n",
+ "\n",
+ "# endregion"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Pipeline\n",
+ "The computational graph"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plots"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "interpreter": {
+ "hash": "a051636751d8b8c3fb678ae2c2b84596f57742a247cc1675aae9ee3b371aaacc"
+ },
+ "kernelspec": {
+ "display_name": "Python 3.10.4 ('.venv': poetry)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.4"
+ },
+ "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/payload_designer/components/foreoptics.py b/payload_designer/components/foreoptics.py
index 7654b27..983d4ad 100644
--- a/payload_designer/components/foreoptics.py
+++ b/payload_designer/components/foreoptics.py
@@ -144,3 +144,14 @@ def get_image_area(self):
a_i = math.pi * (self.d_i / 2) ** 2
return a_i
+
+
+class Chromar(Foreoptic):
+ def __init__(self):
+ super().__init__(
+ diameter=80 * unit.mm,
+ focal_length=100 * unit.mm,
+ mass=250 * unit.g,
+ length=100 * unit.mm,
+ transmittance=None,
+ )
diff --git a/payload_designer/systems/payloads.py b/payload_designer/systems/payloads.py
index 32c9f69..5a79cc7 100644
--- a/payload_designer/systems/payloads.py
+++ b/payload_designer/systems/payloads.py
@@ -40,12 +40,14 @@ def get_volume(self):
class HyperspectralImager(Payload):
def __init__(
self,
- sensor: Component,
- foreoptic: Component,
- slit: Component,
- diffractor: Component,
+ spatial_resolution=None,
+ sensor: Component = None,
+ foreoptic: Component = None,
+ slit: Component = None,
+ diffractor: Component = None,
**components: Component,
):
+ self.spatial_resolution = spatial_resolution
super().__init__(
sensor=sensor,
foreoptic=foreoptic,
@@ -107,11 +109,14 @@ def get_FOV(self) -> np.ndarray[float, float]:
def get_iFOV(self) -> np.ndarray[float, float]:
"""Get the instantaneous field of view."""
+ assert self.sensor is not None, "A sensor component must be specified."
+ assert self.foreoptic is not None, "A foreoptic component must be specified."
+
iFOV = 2 * np.arctan(self.sensor.pitch / (2 * self.foreoptic.focal_length))
return iFOV
- def get_sensor_spatial_resolution(self, target_distance, skew_angle):
+ def get_sensor_spatial_resolution(self, target_distance, skew_angle=0):
"""Get the sensor-limited spatial resolution."""
iFOV = self.get_iFOV()
@@ -141,8 +146,9 @@ def get_swath(
return swath
- def get_optical_spatial_resolution(self, wavelength, target_distance, skew_angle):
+ def get_optical_spatial_resolution(self, wavelength, target_distance, skew_angle=0):
"""Get the optically-limited spatial resolution."""
+ assert self.foreoptic is not None, "A foreoptic component must be specified."
optical_spatial_resolution = (
1.22
@@ -152,20 +158,22 @@ def get_optical_spatial_resolution(self, wavelength, target_distance, skew_angle
return optical_spatial_resolution
- def get_spatial_resolution(self, wavelength, target_distance, skew_angle):
- """Get the spatial resolution or ground sample distance of the
- system."""
+ def get_spatial_resolution(self, wavelength, target_distance, skew_angle=0):
+ """Get the spatial resolution of the system."""
+ if self.spatial_resolution is not None:
+ return self.spatial_resolution
sensor_spatial_resolution = self.get_sensor_spatial_resolution(
target_distance=target_distance, skew_angle=skew_angle
)
+
optical_spatial_resolution = self.get_optical_spatial_resolution(
wavelength=wavelength,
target_distance=target_distance,
skew_angle=skew_angle,
)
- spatial_resolution = np.max(
+ spatial_resolution = np.maximum(
sensor_spatial_resolution, optical_spatial_resolution
)
@@ -232,6 +240,19 @@ def get_spectral_resolution(
return spectral_resolution
+ def get_pointing_accuracy_constraint(
+ self, wavelength, target_distance, tolerance=0.5
+ ):
+ """Get the pointing accuracy constraint."""
+
+ spatial_resolution = self.get_spatial_resolution(
+ wavelength=wavelength, target_distance=target_distance
+ )
+
+ constraint_angle = np.arctan((tolerance * spatial_resolution) / target_distance)
+
+ return constraint_angle
+
class FINCHEye(HyperspectralImager):
def __init__(
diff --git a/tests/test_systems/test_payloads/test_HyperspectralImager.py b/tests/test_systems/test_payloads/test_HyperspectralImager.py
index da89ad6..678ecbc 100644
--- a/tests/test_systems/test_payloads/test_HyperspectralImager.py
+++ b/tests/test_systems/test_payloads/test_HyperspectralImager.py
@@ -1,31 +1,87 @@
+# stdlib
+import logging
+# external
import astropy.units as unit
import numpy as np
-import pandas as pd
-import logging
-from IPython.display import display
# project
from payload_designer import components, systems
-from payload_designer.libs import utillib
+from payload_designer.systems.payloads import HyperspectralImager
+LOG = logging.getLogger(__name__)
-from payload_designer.components.sensors import TauSWIR
-from payload_designer.components.foreoptics import Foreoptic
-from payload_designer.systems.payloads import HyperspectralImager
+def test_get_optical_spatial_resolution():
+ """Test the optically-limited spatial resolution method."""
+
+ # region params
+ wavelength = 400 * unit.nm
+ target_distance = 1 * unit.km
+ # endregion
+
+ # region instantiation
+ foreoptic = components.foreoptics.Chromar()
+ system = HyperspectralImager(foreoptic=foreoptic)
+ # endregion
+
+ # region pipeline
+ res = system.get_optical_spatial_resolution(
+ wavelength=wavelength, target_distance=target_distance
+ )
+ LOG.info(f"Optically-limited spatial resolution: {res}")
+ # endregion
+
+
+def test_get_sensor_spatial_resolution():
+ """Test the sensor-limited spatial resolution method."""
+
+ # region params
+ target_distance = 1 * unit.km
+ # endregion
+
+ # region instantiation
+ sensor = components.sensors.TauSWIR()
+ foreoptic = components.foreoptics.Chromar()
+ system = HyperspectralImager(sensor=sensor, foreoptic=foreoptic)
+ # endregion
+
+ # region pipeline
+ res = system.get_sensor_spatial_resolution(target_distance=target_distance)
+ LOG.info(f"Sensor-limited spatial resolution: {res}")
+ # endregion
+
+
+def test_get_spatial_resolution():
+ """Test the net spatial resolution method."""
+
+ # region params
+ wavelength = 400 * unit.nm
+ target_distance = 1 * unit.km
+ # endregion
+
+ # region instantiation
+ sensor = components.sensors.TauSWIR()
+ foreoptic = components.foreoptics.Chromar()
+ system = HyperspectralImager(sensor=sensor, foreoptic=foreoptic)
+ # endregion
+
+ # region pipeline
+ res = system.get_spatial_resolution(
+ wavelength=wavelength, target_distance=target_distance
+ )
+ LOG.info(f"Spatial resolution: {res}")
+ # endregion
-LOG = logging.getLogger(__name__)
def test_get_optical_spectral_resolution():
- '''Test of get_optical_spectral_resolution function'''
+ """Test of get_optical_spectral_resolution function."""
target_wavelength = 1650 * unit.nm
diameter = 100 * unit.mm
slit_size = np.array([3, 1]) * unit.mm
focal_length = 100 * unit.mm
- fringe_frequency = 600 * (1/unit.mm)
-
+ fringe_frequency = 600 * (1 / unit.mm)
sensor = TauSWIR()
foreoptic = Foreoptic(diameter=diameter, focal_length=focal_length)
@@ -33,10 +89,13 @@ def test_get_optical_spectral_resolution():
sr_grating = components.diffractors.SRTGrating(fringe_frequency=fringe_frequency)
- HP = HyperspectralImager(sensor=sensor, foreoptic=foreoptic, slit=slit, diffractor=sr_grating)
+ HP = HyperspectralImager(
+ sensor=sensor, foreoptic=foreoptic, slit=slit, diffractor=sr_grating
+ )
- optical_spectral_resolution = HP.get_optical_spectral_resolution(target_wavelength=target_wavelength, beam_diameter=25*unit.mm)
-
+ optical_spectral_resolution = HP.get_optical_spectral_resolution(
+ target_wavelength=target_wavelength, beam_diameter=25 * unit.mm
+ )
LOG.info(f"Optical Specral resolution: {optical_spectral_resolution}")
@@ -44,16 +103,14 @@ def test_get_optical_spectral_resolution():
def test_get_sensor_spectral_resolution():
- '''Test of get_optical_spectral_resolution function'''
+ """Test of get_optical_spectral_resolution function."""
-
diameter = 100 * unit.mm
upper_wavelength = 1700 * unit.nm
lower_wavelength = 900 * unit.nm
slit_size = np.array([3, 1]) * unit.mm
focal_length = 100 * unit.mm
- fringe_frequency = 600 * (1/unit.mm)
-
+ fringe_frequency = 600 * (1 / unit.mm)
sensor = TauSWIR()
foreoptic = Foreoptic(diameter=diameter, focal_length=focal_length)
@@ -61,17 +118,23 @@ def test_get_sensor_spectral_resolution():
sr_grating = components.diffractors.SRTGrating(fringe_frequency=fringe_frequency)
- HP = HyperspectralImager(sensor=sensor, foreoptic=foreoptic, slit=slit, diffractor=sr_grating)
+ HP = HyperspectralImager(
+ sensor=sensor, foreoptic=foreoptic, slit=slit, diffractor=sr_grating
+ )
- sensor_spectral_resolution = HP.get_sensor_spectral_resolution(upper_wavelength=upper_wavelength, lower_wavelength=lower_wavelength, beam_diameter=25*unit.mm)
-
+ sensor_spectral_resolution = HP.get_sensor_spectral_resolution(
+ upper_wavelength=upper_wavelength,
+ lower_wavelength=lower_wavelength,
+ beam_diameter=25 * unit.mm,
+ )
LOG.info(f"Sensor Specral resolution: {sensor_spectral_resolution}")
assert sensor_spectral_resolution == 1.5625 * unit.nm
+
def test_get_spectral_resolution():
- '''Test of get_optical_spectral_resolution function'''
+ """Test of get_optical_spectral_resolution function."""
target_wavelength = 1650 * unit.nm
diameter = 100 * unit.mm
@@ -79,8 +142,7 @@ def test_get_spectral_resolution():
lower_wavelength = 900 * unit.nm
slit_size = np.array([3, 1]) * unit.mm
focal_length = 100 * unit.mm
- fringe_frequency = 600 * (1/unit.mm)
-
+ fringe_frequency = 600 * (1 / unit.mm)
sensor = TauSWIR()
foreoptic = Foreoptic(diameter=diameter, focal_length=focal_length)
@@ -88,11 +150,40 @@ def test_get_spectral_resolution():
sr_grating = components.diffractors.SRTGrating(fringe_frequency=fringe_frequency)
- HP = HyperspectralImager(sensor=sensor, foreoptic=foreoptic, slit=slit, diffractor=sr_grating)
+ HP = HyperspectralImager(
+ sensor=sensor, foreoptic=foreoptic, slit=slit, diffractor=sr_grating
+ )
- spectral_resolution = HP.get_spectral_resolution(upper_wavelength=upper_wavelength, lower_wavelength=lower_wavelength, target_wavelength=target_wavelength, beam_diameter=[25, 25]*unit.mm)
-
+ spectral_resolution = HP.get_spectral_resolution(
+ upper_wavelength=upper_wavelength,
+ lower_wavelength=lower_wavelength,
+ target_wavelength=target_wavelength,
+ beam_diameter=[25, 25] * unit.mm,
+ )
LOG.info(f"Specral resolution: {spectral_resolution}")
- assert spectral_resolution == [1.5625, 1.5625] * unit.nm
\ No newline at end of file
+ assert spectral_resolution == [1.5625, 1.5625] * unit.nm
+
+
+def test_get_pointing_accuracy_constraint():
+ """Test the get pointing accuracy constraint method."""
+
+ # region params
+ wavelength = 400 * unit.nm
+ target_distance = 1 * unit.km
+ # endregion
+
+ # region instantiation
+ sensor = components.sensors.TauSWIR()
+ foreoptic = components.foreoptics.Chromar()
+ system = HyperspectralImager(sensor=sensor, foreoptic=foreoptic)
+ # endregion
+
+ # region pipeline
+ res = system.get_pointing_accuracy_constraint(
+ wavelength=wavelength,
+ target_distance=target_distance,
+ )
+ LOG.info(f"Pointing accuracy constraint: {res}")
+ # endregion