{ "cells": [ { "cell_type": "markdown", "id": "sv-title", "metadata": {}, "source": [ "# Svalbard Ground Station Access\n", "\n", "Computes all contact windows between a sun-synchronous satellite and the\n", "**Svalbard Satellite Station (SvalSat)** over a 7-day period.\n", "\n", "**Scenario**\n", "- 550 km sun-synchronous orbit, LTDN 10:30 (descending node)\n", "- Ground station: SvalSat, 78.229°N / 15.407°E / 500 m altitude\n", "- Minimum elevation: 5°\n", "- Analysis window: 2025-03-01 → 2025-03-08 (7 days)" ] }, { "cell_type": "code", "execution_count": 1, "id": "sv-imports", "metadata": { "execution": { "iopub.execute_input": "2026-03-08T03:44:48.449112Z", "iopub.status.busy": "2026-03-08T03:44:48.448384Z", "iopub.status.idle": "2026-03-08T03:44:49.632632Z", "shell.execute_reply": "2026-03-08T03:44:49.631664Z" } }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import matplotlib.dates as mdates\n", "from datetime import datetime\n", "\n", "from missiontools import Spacecraft, GroundStation" ] }, { "cell_type": "markdown", "id": "sv-sc-md", "metadata": {}, "source": [ "## 1. Spacecraft\n", "\n", "A 550 km SSO with a 10:30 local time at descending node, propagated with J2." ] }, { "cell_type": "code", "execution_count": 2, "id": "sv-sc", "metadata": { "execution": { "iopub.execute_input": "2026-03-08T03:44:49.635273Z", "iopub.status.busy": "2026-03-08T03:44:49.634921Z", "iopub.status.idle": "2026-03-08T03:44:49.641218Z", "shell.execute_reply": "2026-03-08T03:44:49.640271Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Semi-major axis : 6928.1 km\n", "Altitude : 550.0 km\n", "Inclination : 97.593°\n", "RAAN at epoch : 139.643°\n", "Orbital period : 95.65 min\n", "Propagator : j2\n" ] } ], "source": [ "EPOCH = np.datetime64('2025-03-01T00:00:00', 'us')\n", "\n", "sc = Spacecraft.sunsync(\n", " altitude_km = 550.0,\n", " node_solar_time = '10:30',\n", " node_type = 'descending',\n", " epoch = EPOCH,\n", ")\n", "\n", "period_s = 2 * np.pi * np.sqrt(sc.a**3 / sc.central_body_mu)\n", "\n", "print(f\"Semi-major axis : {sc.a / 1e3:.1f} km\")\n", "print(f\"Altitude : {(sc.a - sc.central_body_radius) / 1e3:.1f} km\")\n", "print(f\"Inclination : {np.degrees(sc.i):.3f}°\")\n", "print(f\"RAAN at epoch : {np.degrees(sc.raan):.3f}°\")\n", "print(f\"Orbital period : {period_s / 60:.2f} min\")\n", "print(f\"Propagator : {sc.propagator_type}\")" ] }, { "cell_type": "markdown", "id": "sv-gs-md", "metadata": {}, "source": [ "## 2. Ground Station\n", "\n", "SvalSat sits on the island of Spitsbergen at 78.229°N — so far north that\n", "it can see every polar-orbiting satellite at least twice per day." ] }, { "cell_type": "code", "execution_count": 3, "id": "sv-gs", "metadata": { "execution": { "iopub.execute_input": "2026-03-08T03:44:49.643715Z", "iopub.status.busy": "2026-03-08T03:44:49.643450Z", "iopub.status.idle": "2026-03-08T03:44:49.648120Z", "shell.execute_reply": "2026-03-08T03:44:49.647162Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ground station : SvalSat\n", "Latitude : 78.229°N\n", "Longitude : 15.407°E\n", "Altitude : 500 m a.s.l.\n" ] } ], "source": [ "gs = GroundStation(lat=78.229, lon=15.407, alt=500.0)\n", "\n", "print(f\"Ground station : SvalSat\")\n", "print(f\"Latitude : {gs.lat:.3f}°N\")\n", "print(f\"Longitude : {gs.lon:.3f}°E\")\n", "print(f\"Altitude : {gs.alt:.0f} m a.s.l.\")" ] }, { "cell_type": "markdown", "id": "sv-access-md", "metadata": {}, "source": [ "## 3. Compute Access Windows\n", "\n", "`GroundStation.access()` scans the analysis window at the requested maximum time step\n", "and returns a list of `(AOS, LOS)` pairs as `datetime64[us]` tuples.\n", "A 20 s step is fine for detecting passes whose shortest duration exceeds 5 min." ] }, { "cell_type": "code", "execution_count": 4, "id": "sv-access", "metadata": { "execution": { "iopub.execute_input": "2026-03-08T03:44:49.650664Z", "iopub.status.busy": "2026-03-08T03:44:49.650421Z", "iopub.status.idle": "2026-03-08T03:44:49.697185Z", "shell.execute_reply": "2026-03-08T03:44:49.696154Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total passes found: 96\n" ] } ], "source": [ "T_START = np.datetime64('2025-03-01T00:00:00', 'us')\n", "T_END = np.datetime64('2025-03-08T00:00:00', 'us')\n", "\n", "passes = gs.access(\n", " sc,\n", " T_START, T_END,\n", " el_min = 5.0, # degrees\n", " max_step = np.timedelta64(20, 's'),\n", ")\n", "\n", "print(f\"Total passes found: {len(passes)}\")" ] }, { "cell_type": "markdown", "id": "sv-results-md", "metadata": {}, "source": [ "## 4. Access Report" ] }, { "cell_type": "code", "execution_count": 5, "id": "sv-results", "metadata": { "execution": { "iopub.execute_input": "2026-03-08T03:44:49.700063Z", "iopub.status.busy": "2026-03-08T03:44:49.699774Z", "iopub.status.idle": "2026-03-08T03:44:49.710783Z", "shell.execute_reply": "2026-03-08T03:44:49.709708Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " # AOS (UTC) LOS (UTC) Duration\n", " ─── ────────────────────────── ────────────────────────── ─────────\n", " 1 2025-03-01T01:10:53.750000 2025-03-01T01:18:22.500000 7m 28s\n", " 2 2025-03-01T02:46:01.250000 2025-03-01T02:55:08.125000 9m 06s\n", " 3 2025-03-01T04:21:03.750000 2025-03-01T04:30:53.750000 9m 50s\n", " 4 2025-03-01T05:55:56.250000 2025-03-01T06:05:52.500000 9m 56s\n", " 5 2025-03-01T07:30:36.250000 2025-03-01T07:40:21.250000 9m 45s\n", " 6 2025-03-01T09:05:02.500000 2025-03-01T09:14:42.500000 9m 40s\n", " 7 2025-03-01T10:39:23.750000 2025-03-01T10:49:11.250000 9m 47s\n", " 8 2025-03-01T12:13:56.875000 2025-03-01T12:23:53.750000 9m 56s\n", " 9 2025-03-01T13:49:03.125000 2025-03-01T13:58:48.750000 9m 45s\n", " 10 2025-03-01T15:25:00.000000 2025-03-01T15:33:52.500000 8m 52s\n", " 11 2025-03-01T17:01:57.500000 2025-03-01T17:09:00.625000 7m 03s\n", " 12 2025-03-01T18:39:59.375000 2025-03-01T18:44:07.500000 4m 08s\n", " 13 2025-03-01T23:30:31.250000 2025-03-01T23:35:25.000000 4m 53s\n", " 14 2025-03-02T01:05:40.000000 2025-03-02T01:13:12.500000 7m 32s\n", " 15 2025-03-02T02:40:47.500000 2025-03-02T02:49:55.625000 9m 08s\n", " 16 2025-03-02T04:15:49.375000 2025-03-02T04:25:40.625000 9m 51s\n", " 17 2025-03-02T05:50:41.875000 2025-03-02T06:00:37.500000 9m 55s\n", " 18 2025-03-02T07:25:21.250000 2025-03-02T07:35:06.250000 9m 45s\n", " 19 2025-03-02T08:59:47.500000 2025-03-02T09:09:26.875000 9m 39s\n", " 20 2025-03-02T10:34:08.125000 2025-03-02T10:43:56.250000 9m 48s\n", " 21 2025-03-02T12:08:42.500000 2025-03-02T12:18:39.375000 9m 56s\n", " 22 2025-03-02T13:43:50.000000 2025-03-02T13:53:34.375000 9m 44s\n", " 23 2025-03-02T15:19:48.125000 2025-03-02T15:28:38.125000 8m 50s\n", " 24 2025-03-02T16:56:48.125000 2025-03-02T17:03:46.875000 6m 58s\n", " 25 2025-03-02T18:34:51.250000 2025-03-02T18:38:53.750000 4m 02s\n", " 26 2025-03-02T23:25:17.500000 2025-03-02T23:30:16.250000 4m 58s\n", " 27 2025-03-03T01:00:25.625000 2025-03-03T01:08:01.875000 7m 36s\n", " 28 2025-03-03T02:35:33.125000 2025-03-03T02:44:43.750000 9m 10s\n", " 29 2025-03-03T04:10:35.625000 2025-03-03T04:20:26.875000 9m 51s\n", " 30 2025-03-03T05:45:27.500000 2025-03-03T05:55:23.125000 9m 55s\n", " 31 2025-03-03T07:20:06.250000 2025-03-03T07:29:51.250000 9m 45s\n", " 32 2025-03-03T08:54:32.500000 2025-03-03T09:04:11.875000 9m 39s\n", " 33 2025-03-03T10:28:53.125000 2025-03-03T10:38:41.250000 9m 48s\n", " 34 2025-03-03T12:03:28.125000 2025-03-03T12:13:25.000000 9m 56s\n", " 35 2025-03-03T13:38:36.875000 2025-03-03T13:48:20.000000 9m 43s\n", " 36 2025-03-03T15:14:36.875000 2025-03-03T15:23:24.375000 8m 47s\n", " 37 2025-03-03T16:51:38.125000 2025-03-03T16:58:32.500000 6m 54s\n", " 38 2025-03-03T18:29:43.125000 2025-03-03T18:33:39.375000 3m 56s\n", " 39 2025-03-03T21:45:31.250000 2025-03-03T21:45:55.625000 0m 24s\n", " 40 2025-03-03T23:20:03.750000 2025-03-03T23:25:07.500000 5m 03s\n", " 41 2025-03-04T00:55:11.875000 2025-03-04T01:02:51.250000 7m 39s\n", " 42 2025-03-04T02:30:19.375000 2025-03-04T02:39:31.875000 9m 12s\n", " 43 2025-03-04T04:05:21.250000 2025-03-04T04:15:13.125000 9m 51s\n", " 44 2025-03-04T05:40:13.125000 2025-03-04T05:50:08.125000 9m 55s\n", " 45 2025-03-04T07:14:51.875000 2025-03-04T07:24:36.250000 9m 44s\n", " 46 2025-03-04T08:49:16.875000 2025-03-04T08:58:56.875000 9m 40s\n", " 47 2025-03-04T10:23:38.125000 2025-03-04T10:33:26.875000 9m 48s\n", " 48 2025-03-04T11:58:13.125000 2025-03-04T12:08:10.000000 9m 56s\n", " 49 2025-03-04T13:33:23.125000 2025-03-04T13:43:06.250000 9m 43s\n", " 50 2025-03-04T15:09:25.000000 2025-03-04T15:18:10.625000 8m 45s\n", " 51 2025-03-04T16:46:28.125000 2025-03-04T16:53:18.750000 6m 50s\n", " 52 2025-03-04T18:24:35.000000 2025-03-04T18:28:25.625000 3m 50s\n", " 53 2025-03-04T21:40:09.375000 2025-03-04T21:40:56.250000 0m 46s\n", " 54 2025-03-04T23:14:49.375000 2025-03-04T23:19:58.750000 5m 09s\n", " 55 2025-03-05T00:49:58.125000 2025-03-05T00:57:40.625000 7m 42s\n", " 56 2025-03-05T02:25:05.625000 2025-03-05T02:34:19.375000 9m 13s\n", " 57 2025-03-05T04:00:06.875000 2025-03-05T04:09:59.375000 9m 52s\n", " 58 2025-03-05T05:34:58.750000 2025-03-05T05:44:53.750000 9m 55s\n", " 59 2025-03-05T07:09:36.875000 2025-03-05T07:19:20.625000 9m 43s\n", " 60 2025-03-05T08:44:01.875000 2025-03-05T08:53:41.875000 9m 40s\n", " 61 2025-03-05T10:18:23.125000 2025-03-05T10:28:11.875000 9m 48s\n", " 62 2025-03-05T11:52:58.750000 2025-03-05T12:02:55.625000 9m 56s\n", " 63 2025-03-05T13:28:10.000000 2025-03-05T13:37:51.875000 9m 41s\n", " 64 2025-03-05T15:04:13.750000 2025-03-05T15:12:56.250000 8m 42s\n", " 65 2025-03-05T16:41:18.125000 2025-03-05T16:48:05.000000 6m 46s\n", " 66 2025-03-05T18:19:26.875000 2025-03-05T18:23:11.250000 3m 44s\n", " 67 2025-03-05T21:34:50.625000 2025-03-05T21:35:53.125000 1m 02s\n", " 68 2025-03-05T23:09:35.625000 2025-03-05T23:14:50.000000 5m 14s\n", " 69 2025-03-06T00:44:44.375000 2025-03-06T00:52:30.000000 7m 45s\n", " 70 2025-03-06T02:19:51.250000 2025-03-06T02:29:06.875000 9m 15s\n", " 71 2025-03-06T03:54:52.500000 2025-03-06T04:04:45.625000 9m 53s\n", " 72 2025-03-06T05:29:43.750000 2025-03-06T05:39:38.750000 9m 55s\n", " 73 2025-03-06T07:04:21.875000 2025-03-06T07:14:05.625000 9m 43s\n", " 74 2025-03-06T08:38:46.875000 2025-03-06T08:48:26.875000 9m 40s\n", " 75 2025-03-06T10:13:08.125000 2025-03-06T10:22:56.875000 9m 48s\n", " 76 2025-03-06T11:47:44.375000 2025-03-06T11:57:41.875000 9m 57s\n", " 77 2025-03-06T13:22:56.875000 2025-03-06T13:32:38.125000 9m 41s\n", " 78 2025-03-06T14:59:01.875000 2025-03-06T15:07:42.500000 8m 40s\n", " 79 2025-03-06T16:36:08.125000 2025-03-06T16:42:51.250000 6m 43s\n", " 80 2025-03-06T18:14:18.750000 2025-03-06T18:17:56.875000 3m 38s\n", " 81 2025-03-06T21:29:33.125000 2025-03-06T21:30:48.750000 1m 15s\n", " 82 2025-03-06T23:04:21.875000 2025-03-06T23:09:41.250000 5m 19s\n", " 83 2025-03-07T00:39:30.625000 2025-03-07T00:47:19.375000 7m 48s\n", " 84 2025-03-07T02:14:37.500000 2025-03-07T02:23:55.000000 9m 17s\n", " 85 2025-03-07T03:49:38.750000 2025-03-07T03:59:31.875000 9m 53s\n", " 86 2025-03-07T05:24:29.375000 2025-03-07T05:34:23.750000 9m 54s\n", " 87 2025-03-07T06:59:06.875000 2025-03-07T07:08:50.625000 9m 43s\n", " 88 2025-03-07T08:33:31.250000 2025-03-07T08:43:11.875000 9m 40s\n", " 89 2025-03-07T10:07:53.125000 2025-03-07T10:17:42.500000 9m 49s\n", " 90 2025-03-07T11:42:30.625000 2025-03-07T11:52:27.500000 9m 56s\n", " 91 2025-03-07T13:17:43.750000 2025-03-07T13:27:23.750000 9m 40s\n", " 92 2025-03-07T14:53:50.625000 2025-03-07T15:02:28.750000 8m 38s\n", " 93 2025-03-07T16:30:58.750000 2025-03-07T16:37:37.500000 6m 38s\n", " 94 2025-03-07T18:09:10.625000 2025-03-07T18:12:43.125000 3m 32s\n", " 95 2025-03-07T21:24:16.875000 2025-03-07T21:25:43.750000 1m 26s\n", " 96 2025-03-07T22:59:08.125000 2025-03-07T23:04:32.500000 5m 24s\n", "\n", " Total passes : 96\n", " Total contact time : 12h 54m 58s\n", " Duty cycle : 7.69%\n", " Mean pass duration : 8.1 min\n" ] } ], "source": [ "print(f\" {'#':>3} {'AOS (UTC)':^26} {'LOS (UTC)':^26} {'Duration':>9}\")\n", "print(f\" {'─'*3} {'─'*26} {'─'*26} {'─'*9}\")\n", "\n", "total_s = 0\n", "for idx, (aos, los) in enumerate(passes, 1):\n", " dur_s = int((los - aos) / np.timedelta64(1, 's'))\n", " total_s += dur_s\n", " print(f\" {idx:>3} {str(aos):^26} {str(los):^26} \"\n", " f\"{dur_s // 60:3d}m {dur_s % 60:02d}s\")\n", "\n", "window_s = int((T_END - T_START) / np.timedelta64(1, 's'))\n", "print()\n", "print(f\" Total passes : {len(passes)}\")\n", "print(f\" Total contact time : {total_s // 3600}h \"\n", " f\"{(total_s % 3600) // 60}m {total_s % 60:02d}s\")\n", "print(f\" Duty cycle : {total_s / window_s * 100:.2f}%\")\n", "print(f\" Mean pass duration : {total_s / len(passes) / 60:.1f} min\")" ] }, { "cell_type": "markdown", "id": "sv-viz-md", "metadata": {}, "source": [ "## 5. Pass Timeline\n", "\n", "Each bar represents one contact window. The bar length is proportional to\n", "contact duration." ] }, { "cell_type": "code", "execution_count": 6, "id": "sv-viz", "metadata": { "execution": { "iopub.execute_input": "2026-03-08T03:44:49.714280Z", "iopub.status.busy": "2026-03-08T03:44:49.713943Z", "iopub.status.idle": "2026-03-08T03:44:50.384661Z", "shell.execute_reply": "2026-03-08T03:44:50.383789Z" } }, "outputs": [ { "data": { "image/png": "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iy++qB9//FGSVKlSJY0cOVKS9Nhjjzna2bBhQ0nSrFmzdO7cOT355JN65513FBMTo3feeUfdunVz2s/ff/+tu+66S4sXL9ajjz6qCRMmqG3btvruu+8kSe3bt1fXrl0lSW+//bZjP5GRkZmehwYNGshut2vZsmWOsvj4ePn4+Cg+Pt5RtnbtWiUlJTnaezUPPPCAzpw5o7Fjx+qBBx7Q1KlTM0zJfOSRRzR+/Hi1aNFCr776qvz8/NSqVasM29q0aZMaNGig9evXa+DAgRo2bJh27dqlRo0a6Y8//pAkhYWFqUqVKvrtt98cj1u2bJlsNptOnjypzZs3Ox1bgwYNJEmpqamKiYnR77//rqefflrvvfeeHnvsMe3cudOja7WcO3dOISEhCg0NVUREhPr27aukpKRM68bGxio4OFiBgYGqVatWhlD1wIEDOnr0qO68884Mj61du7bWrl3rVtvS0tLUo0cPTZs2TfPmzVP79u2d7n/66ae1fft2xcbGqnXr1vrwww81bNgw3X///UpLS9OYMWN09913a9y4cRmmuV0pPWBKf25cq64r15Rly5YpISFBDz74YJZTT9Ofc99///1Vt2WFjh07KigoKMPfVboUOnfr1k0fffSRDh48mGttSO8jV/ahYsWKqUSJEk596MCBA6pUqZIGDRqU6bZOnDiho0eP6q+//lLPnj0lSU2bNr3mvmrWrCkfHx+3+2u6xx9/XC+88ILq16+vCRMmqGfPnvriiy8UExOT4VruioIFC+rDDz9U/fr1VbhwYT388MP68ssvdfLkyWy1z5XnfKFChTRixAh16dJF5cqV06JFi7IdSAIArsGj47QA4D/ql19+Mb6+vsbX19fUrVvXDBw40Pz8888mNTXVqd7WrVuNJPPOO+84lffp08cEBwebc+fOOcou/78xxqSmppoqVaqYJk2aOJVfOX1v48aNJigoyDEF5ZlnnjFff/21OXv2bIZ2X7kPY4x5/PHHTd68ec358+cdZe5M39u+fbvx8fEx7dq1M2lpaU732e12Y4wxR48eNf7+/qZFixZOdd59910jyUyZMsVRFh0dbSSZadOmOcpSUlJMkSJFTIcOHRxlV5u+l9lxjh071thsNqdpVw0bNjT58+d3Kru83ca4N30vLS3NhISEmIEDBzq2U6BAAdOpUyfj6+trzpw5Y4wx5q233jI+Pj5O0z91xVS79OlMvXr1ctpHu3btTIECBRy3161bZySZPn36ONV78MEHM2yzbdu2xt/f3+zYscNRdvDgQZM/f37TsGFDR1nfvn1N4cKFHbf79+9vGjZsaAoVKmTef/99Y8yl6Uo2m81MmDDBGGPM2rVrs5w65SkvvfSSefHFF83MmTPNl19+abp3724kmfr16ztNndqzZ49p0aKFef/99823335rxo8fb0qVKmV8fHzM999/76iX3ucu75vpXnjhBSPJ6Xl0pcun7124cMF07tzZBAUFmZ9//tmpXvqUspiYGKe+WLduXWOz2cwTTzzhKLt48aIpUaKES9OkunXrZiSZ8PBw065dO/PGG29kOl3M1WvK+PHjjSQzb968LPd58uRJI8m0b9/+qm3L7el76apVq2bCw8Mdt9PP9apVq8yOHTtMnjx5TL9+/Rz3uzp973JXu2ak37d3794M99WqVcvUqVPHcTu9v1x+vb9cQECAkWQkmQIFCpiJEyc63d+3b1/j6+ub6WMjIyNNly5dXD+o/y8+Pt5IMl988YVT+U8//ZSh3J3pe2lpaWb58uVm8ODB5vbbbzeSjK+vr6lfv74ZM2aMWb9+vUvbcfU5n27//v3mzz//NMnJyS5tHwDgPkZKAUAuaN68uVauXKnWrVtr/fr1ev311xUTE6PixYvr22+/ddQrX768qlevrpkzZzrK0tLSNHv2bN1///0KCgpylF/+/4SEBJ06dUoNGjTQmjVrrtqWypUra926dXr44Ye1e/dux2ifwoUL66OPPnKqe/k+zpw5o+PHj6tBgwY6d+6c/vnnn2ydi6+//lp2u10vv/yyfHycX3ZsNpskaeHChUpNTdWzzz7rVOfRRx9VSEhIhtFgwcHBevjhhx23/f39Vbt2be3cudOlNl1+nGfPntXx48dVr149GWMcowOOHTum3377Tb169XKainV5u93l4+OjevXqOUYZbdmyRSdOnNBLL70kY4xWrlwp6dIIoypVqri0cPoTTzzhdLtBgwY6ceKEY2rK/PnzJV1a3PlyVy5Sn5aWpl9++UVt27bVLbfc4igvWrSoHnzwQS1btsyxzQYNGujIkSPaunWro70NGzZUgwYNHCO+li1bJmOMY6RU+kLCP//88zVH4lhl7NixevXVV/XAAw+oS5cumjp1qkaPHq3ly5c7TZMqVaqUfv75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qFGjFBUVpYCAAJUpU0aDBw9WSkqKYxtlypTRpk2b9Ouvvzoe36hRI0nSyZMnNWDAAFWtWlXBwcEKCQnRPffco/Xr17t0TJlJTEzUc889pzJlyiggIEAlSpRQt27ddPz4cUedo0ePqnfv3ipcuLACAwNVrVo1ffrpp07bSV/H6o033tCHH37oOMZatWpp1apVjno9evTQe++9J0mO47t8vaY33nhD9erVU4ECBRQUFKSaNWtmub7X559/rtq1aytv3rwKDw9Xw4YN9csvv1zzPF5p9+7dioyMlCTFxsY66qdPMcxsTSmbzaannnpKs2bN0m233aagoCDVrVtXGzZskCRNnjxZ5cqVU2BgoBo1auT0HE33xx9/qGXLlgoNDVXevHkVHR2t5cuXZ9pGAAD+q/jaBwBwU0lJSVFQUFCG8rx58yo1NVUbN25UnTp1tHnzZh08eFC33367HnvsMX366adKTU1V1apVNWHCBDVu3Nil/Y0ePVo2m00vvviijh49qvHjx6tZs2Zat26dox2zZs3SuXPn9OSTT6pAgQL6888/9c4772j//v2aNWuWY1sdOnTQpk2b9PTTT6tMmTI6evSoFixYoL179zput2jRQpGRkXrppZcUFham3bt3a+7cuU5tevzxxzV16lT17NlT/fr1065du/Tuu+9q7dq1Wr58ufz8/FzellUOHz4sSSpYsOBV66UHPFf+jfPmzSvp0npirnj11Vfl4+OjAQMG6NSpU3r99df10EMP6Y8//sjyMe3bt9e2bdv05Zdf6u2333a0NT3weOSRR/Tpp5+qY8eOev755/XHH39o7Nix2rJli+bNmydJGj9+vJ5++mkFBwdryJAhkqTChQtLknbu3Kmvv/5anTp1UtmyZXXkyBFNnjxZ0dHR2rx5s4oVK+bSsaVLSkpSgwYNtGXLFvXq1Ut33HGHjh8/rm+//Vb79+9XwYIFlZycrEaNGunff//VU089pbJly2rWrFnq0aOHEhMT9cwzzzhtc/r06Tpz5owef/xx2Ww2vf7662rfvr127twpPz8/Pf744zp48KAWLFigzz77LEObJkyYoNatW+uhhx5SamqqZsyYoU6dOun7779Xq1atHPViY2M1YsQI1atXTyNHjpS/v7/++OMPLV68WC1atLjqebxSZGSk3n//fT355JNq166d2rdvL0nXHFEXHx+v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bt26jtuVKlVSdHS0li5d6ih74IEHVKxYMd122206ffq0pkyZop07d+qHH35wWoA6N9SsWVOSNGTIEHXp0kV+fn66//77Va1aNXXv3l0ffvihEhMTFR0drT///FOffvqp2rZtq8aNGztt4/3339crr7yicuXKqVChQmrSpInuu+8+jRw5Uj179lS9evW0YcMGffHFF7rllluy1dYXXnhBs2fPVqdOndSrVy/VrFlTJ0+e1LfffqsPPvhA1apV02OPPabJkyerR48eWr16tcqUKaPZs2dr+fLlGj9+fLbOZ/o56tevn2JiYuTr66suXbqoVatWeuutt9SyZUs9+OCDOnr0qN577z2VK1dOf//9t+Px5cqV05AhQzRq1Cg1aNBA7du3V0BAgFatWqVixYpp7NixVz2PmQkKCtJtt92mmTNnqnz58oqIiFCVKlWuueZWdvj4+Ojjjz/WPffco8qVK6tnz54qXry4Dhw4oCVLligkJETfffddju8XAACv5JHf/AMAwEP+/fdf06JFC1OwYEETEBBgKlasaMaOHWtSUlIyrb969WrTrFkzky9fPpM/f37Tpk0bs23btmvuZ8mSJUaS+fLLL82gQYNMoUKFTFBQkGnVqpXZs2ePU93NmzebZs2ameDgYFOwYEHz6KOPmvXr1xtJJi4uzhhjzPHjx03fvn1NxYoVTb58+UxoaKi56667zFdffeXYzpo1a0zXrl1NqVKlTEBAgClUqJC57777zF9//ZWhfR9++KGpWbOmCQoKMvnz5zdVq1Y1AwcONAcPHnRrWx06dDBBQUEmISHhmuekdOnSRlKm/3bt2mWMMWbXrl1Z1pFkunfv7rRNSSY6Otqp7LXXXjMVK1Y0gYGBJjw83LRu3dqsXbv2mu0z5v/+brNmzXIqT29X+t/jakaNGmWKFy9ufHx8nI7twoULJjY21pQtW9b4+fmZkiVLmkGDBpnz5887Pf7w4cOmVatWJn/+/E7Hd/78efP888+bokWLmqCgIFO/fn2zcuVKEx0d7XQO3GnriRMnzFNPPWWKFy9u/P39TYkSJUz37t3N8ePHHXWOHDlievbsaQoWLGj8/f1N1apVM2w7fZ/jxo3LsA9JZvjw4Y7bFy9eNE8//bSJjIw0NpvNXP529JNPPjG33nqr47kZFxdnhg8fbjJ7yzplyhRTo0YNExAQYMLDw010dLRZsGDBNc9jVlasWGFq1qxp/P39ndqc2f4lmb59+7p0DrLqU2vXrjXt27c3BQoUMAEBAaZ06dLmgQceMIsWLbpqOwEA+C+xGXOdK3YCAIAMli5dqsaNG2vWrFnq2LGjp5uTawoXLqxu3bpp3Lhxnm4KAAAAbjCsKQUAALJl06ZNSk5O1osvvujppgAAAOAGxJpSAAAgWypXrqzTp097uhkAAAC4QTFSCgAAAAAAAJZjTSkAAAAAAABYjpFSAAAAAAAAsByhFAAAAAAAACznFQud2+12HTx4UPnz55fNZvN0cwAAAAAAAP6zjDE6c+aMihUrJh8fz41X8opQ6uDBgypZsqSnmwEAAAAAAHDT2Ldvn0qUKOGx/XtFKJU/f35J0p49exQWFubZxuCmY7fbdezYMUVGRno0IcbNiz4IT6L/wZPof/Ak+h88jT4IT0pMTFTp0qUdeYyneEUolT5lLyQkRCEhIR5uDW42drtd58+fV0hICC8G8Aj6IDyJ/gdPov/Bk+h/8DT6IDzJbrdLkseXUKLnAwAAAAAAwHKEUgAAAAAAALAcoRQAAAAAAAAsRygFAAAAAAAAyxFKAQAAAAAAwHKEUgAAAAAAALAcoRQAAAAAAAAsRygFAAAAAAAAyxFKAQAAAAAAwHKEUgAAAAAAALDcDRNK9Z66Ksfr3uzb9OT+vcHN/Lfy9N/f033qZu+n7tRlmzm7TXfr5gZPHxfbzNltulvX026U88rrOa+9OV3X03+rm3mb7tbNDZ4+LraZs9t0t25uuJHaei03TCgFAAAAAACA/w5CKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAACWI5QCAAAAAACA5QilAAAAAAAAYDlCKQAAAAAAAFiOUAoAAAAAAADWM17g1KlTRpJJ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AAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAAAADLEUoBAAAAAADAcoRSAAAAAAAAsByhFAAAAAAAACxHKAUAAAAA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4yObzeaok377yjWsspLtkVK+vr7asmWL4/9XCg8PV4ECBfThhx+qaNGi2rt3r1566aVs7Ss0NFS9e/dW//79FRERoZCQED399NOqW7eu6tSp46j377//KikpSYcPH1ZycrLWrVsn6dI3F8zn/m/xtv63ceNGNWnSRDExMerfv79jjq2vr68iIyOzeZTwZt7WB+fPn68jR46oVq1aCg4O1qZNm/TCCy+ofv36Li8yiBuHt/W/qKgop8ccP35cklSpUqUM6xDgxudt/e+7777TkSNHVKdOHQUGBmrBggUaM2aMBgwYkP2DhNfytv5Xvnx5tWnTRs8884w+/PBDhYSEaNCgQapYsaIaN26c/QOFV/K2/pdu5syZunjxItPobwLe1gebN2+uF154QX379tXTTz8tu92uV199VXny5HH5GpjtUEqSQkJCsrzPx8dHM2bMUL9+/VSlShVVqFBBEydOVKNGjbK1r7fffls+Pj7q0KGDUlJSFBMTo0mTJjnVeeSRR/Trr786bteoUUOStGvXLj6U/Qd5U/+bPXu2jh07ps8//1yff/65o7x06dLavXt3tvYJ7+dNfTAoKEgfffSRnnvuOaWkpKhkyZJq3759tl+E4P28qf/h5uNN/c/Pz0/vvfeennvuORljVK5cOb311lt69NFHs7U/eD9v6n/SpV88e+6559SqVSv5+PgoOjpaP/30k/z8/LK1T3g3b+t/0qUFztu3b88XQTcJb+qDFStW1HfffafY2FjVrVtXPj4+qlGjhn766SeXlw+xGX4vFwAAAAAAABbL9ppSAAAAAAAAQHYRSgEAAAAAAMByhFIAAAAAAACwHKEUAAAAAAAALEcoBQAAAAAAAMsRSgEAAAAAAMByhFIAAAAAAACwHKEUAAAAAAAALEcoBQAAAAAAAMsRSgEAAOSARYsWqVKlSkpLS/PI/uvUqaM5c+Z4ZN8AAADZQSgFAABuGD169JDNZpPNZpOfn58KFy6s5s2ba8qUKbLb7W5ta+rUqQoLC8uxtg0cOFBDhw6Vr6+vJGnEiBGqXr16hnq7d++WzWbTunXrnI4ns39lypSRJJ0+fVpDhgxRxYoVFRgYqCJFiqhZs2aaO3eujDGSpKFDh+qll15y+zwAAAB4CqEUAAC4obRs2VKHDh3S7t279eOPP6px48Z65plndN999+nixYseadOyZcu0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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Convert datetime64 to Python datetime for matplotlib\n", "def to_dt(t64):\n", " return t64.astype('datetime64[ms]').astype(datetime)\n", "\n", "fig, ax = plt.subplots(figsize=(12, 4))\n", "\n", "for idx, (aos, los) in enumerate(passes):\n", " dur_s = int((los - aos) / np.timedelta64(1, 's'))\n", " ax.barh(\n", " 0,\n", " left = to_dt(aos),\n", " width = to_dt(los) - to_dt(aos),\n", " height = 0.5,\n", " color = 'tab:blue',\n", " alpha = 0.7,\n", " )\n", " # Annotate short passes with their duration (min:ss)\n", " mid = to_dt(aos + (los - aos) // 2)\n", " ax.text(mid, 0, f\"{dur_s // 60}m{dur_s % 60:02d}s\",\n", " ha='center', va='center', fontsize=7, color='white', fontweight='bold')\n", "\n", "ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d'))\n", "ax.xaxis.set_major_locator(mdates.DayLocator())\n", "ax.set_yticks([])\n", "ax.set_xlim(to_dt(T_START), to_dt(T_END))\n", "ax.set_xlabel('Date (UTC)')\n", "ax.set_title(\n", " f'SvalSat contact windows — 550 km SSO LTDN 10:30, el ≥ 5°\\n'\n", " f'{len(passes)} passes, {total_s / 3600:.1f} h total contact time'\n", ")\n", "ax.grid(True, axis='x', alpha=0.3)\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "sv-perdaymd", "metadata": {}, "source": [ "## 6. Passes per Day" ] }, { "cell_type": "code", "execution_count": 7, "id": "sv-perday", "metadata": { "execution": { "iopub.execute_input": "2026-03-08T03:44:50.387960Z", "iopub.status.busy": "2026-03-08T03:44:50.387619Z", "iopub.status.idle": "2026-03-08T03:44:50.395937Z", "shell.execute_reply": "2026-03-08T03:44:50.394641Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Date Passes Contact\n", " ──────────── ─────── ────────────\n", " 2025-03-01 13 110m 09s\n", " 2025-03-02 13 110m 06s\n", " 2025-03-03 14 110m 27s\n", " 2025-03-04 14 110m 48s\n", " 2025-03-05 14 110m 58s\n", " 2025-03-06 14 111m 12s\n", " 2025-03-07 14 111m 18s\n" ] } ], "source": [ "from collections import defaultdict\n", "\n", "passes_per_day = defaultdict(list)\n", "for aos, los in passes:\n", " day = str(aos)[:10] # 'YYYY-MM-DD'\n", " dur_s = int((los - aos) / np.timedelta64(1, 's'))\n", " passes_per_day[day].append(dur_s)\n", "\n", "print(f\" {'Date':>12} {'Passes':>7} {'Contact':>12}\")\n", "print(f\" {'─'*12} {'─'*7} {'─'*12}\")\n", "for day in sorted(passes_per_day):\n", " n = len(passes_per_day[day])\n", " t = sum(passes_per_day[day])\n", " print(f\" {day:>12} {n:>7} {t // 60:3d}m {t % 60:02d}s\")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.13.12" } }, "nbformat": 4, "nbformat_minor": 5 }