diff --git a/.github/workflows/lightkurve-tests.yml b/.github/workflows/lightkurve-tests.yml index b25b6a8ea..c5736cf22 100644 --- a/.github/workflows/lightkurve-tests.yml +++ b/.github/workflows/lightkurve-tests.yml @@ -42,7 +42,7 @@ jobs: - name: "3.11" python-version: "3.11" pytest-command: ./poetry/bin/poetry run pytest - - name: "3.12-remote-data" + - name: "3.12" python-version: "3.12" pytest-command: ./poetry/bin/poetry run pytest - name: "3.13" diff --git a/CHANGES.rst b/CHANGES.rst index e61dadb9b..50b2e7923 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,9 @@ -2.5.2dev (unreleased) +2.6.1dev +===================== +- Update search URL for query_solar_system_objects [#1556] +- Fixed search result sort order for the cases involving TESS sectors 99 and 100, etc. [#1558] + +2.6.0 (2026-04-16) ===================== - Patch for changes to astroquery 0.4.11. Search results using GAIA DR2 now case insensitive. Integer searches converted to string. [#1511] - Added Folded lightcurve reader to open data saved with ``lk.FoldedLightCurve.to_fits()`` [#1488] @@ -7,8 +12,18 @@ - Include MOM_CENTR1 and MOM_CENTR2, if it exists, when saving fits files [#1488] - Fixed bugs in ``bin`` for ``flux_err`` column. Improved ``bin`` performance. [#1499] - Updated search result sort order [#1384] +- When reading in data saved with to_fits, change meta.flux_origin to reflect origin [#1371] - Convert flux and flux_err to Quantity objects when using ``select_flux`` [#1513] - Fixed bugs in ``FoldedLightCurve`` objects with normalized phase to support pickle / dill [#1529] +- Added support in ``read_generic_lightcurve()`` for FITS Standard reference time keywords like [M]JDREF [#1535] +- Capped pandas version at <3.0.0 for breaking changes [#1534] +- Added ability to download 20-s CBV products for TESS [#1537] +- Changed search so that it longer emits ERROR log message when the search result is empty [#1540] +- Fixed search by exact match for TICs with fewer than 9 digits, avoiding the extra + fallback cone search [#1541] +- Modified how SAP_QUALITY is treated when reading/writing TESS and Kepler data [#1538] +- Added ability to use nifty-ls for periodograms [#1550] +- Added new tutorial for read_generic_lightcurve [#1542] 2.5.1 (2025-05-20) ===================== diff --git a/docs/source/tutorials/2-creating-light-curves/2-4-using_the_to_fits_and_read_generic_lightcurve_function.ipynb b/docs/source/tutorials/2-creating-light-curves/2-4-using_the_to_fits_and_read_generic_lightcurve_function.ipynb new file mode 100644 index 000000000..7efed8226 --- /dev/null +++ b/docs/source/tutorials/2-creating-light-curves/2-4-using_the_to_fits_and_read_generic_lightcurve_function.ipynb @@ -0,0 +1,621 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c292a249-adc4-4ca8-9957-4df3d7fcb90d", + "metadata": {}, + "source": [ + "# Using the to_fits and read_generic_lightcurve functions\n", + "\n", + "## Learning Goals\n", + "\n", + "By the end of this tutorial you will: \n", + "\n", + "- Learn how to create a [LightCurve object](https://lightkurve.github.io/lightkurve/tutorials/1-getting-started/what-are-lightcurve-objects.html).\n", + "- Save the LightCurve object as a fits file using the [`to_fits`](https://lightkurve.github.io/lightkurve/reference/api/lightkurve.LightCurve.to_fits.html?highlight=to_fits#lightkurve.LightCurve.to_fits) function.\n", + "- Read in the same FITs file using the [`read_generic_lightcurve`](https://github.com/lightkurve/lightkurve/blob/f8e8c16ba5135b8811d908bb919815b93dcce2bd/src/lightkurve/io/generic.py#L20-L31) function.\n", + "\n", + "## Introduction\n", + "\n", + "The intent of the tutorial is to illustrate how one might use data from any mission (not just Kepler, K2, or TESS) and analize it within Lightkurve. \n", + "\n", + "## Imports\n", + "This tutorial requires:\n", + "\n", + "- [Lightkurve](https://lightkurve.github.io/lightkurve/index.html)\n", + "- [Matplotlib](https://matplotlib.org/)\n", + "- [numpy](https://numpy.org/)\n", + "- astropy [time](https://docs.astropy.org/en/stable/time/index.html) and [units](https://docs.astropy.org/en/latest/units/index.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "8e374a70-fdb3-431c-a96d-b5be40a87ab2", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import lightkurve as lk\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "from astropy.time import Time\n", + "import astropy.units as u" + ] + }, + { + "cell_type": "markdown", + "id": "7b016c47-2163-4902-8622-a78a80cf7de0", + "metadata": {}, + "source": [ + "## 1: Creating our lightcurve data and our LightCurve Object\n", + "\n", + "First we will create some fake lightcurve data to use as an example and convert this into a LightCurve Object. \n", + "You could also download a LightCurve Object via using [`search_lightcurve`](https://lightkurve.github.io/lightkurve/reference/api/lightkurve.search_lightcurve.html?highlight=search_lightcurve#lightkurve.search_lightcurve) and [`download()`](https://lightkurve.github.io/lightkurve/reference/api/lightkurve.SearchResult.download.html?highlight=download#lightkurve.SearchResult.download) if you wish, but for now we will create our simple data set." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "eebdab4d-0db0-41d6-800b-9c582f2db671", + "metadata": {}, + "outputs": [], + "source": [ + "#Create the time values and specify the format\n", + "time_values = Time(np.linspace(2458000, 2458000 + 10, 100), format='jd')\n", + "\n", + "#Create the flux and flux error values\n", + "flux_values = np.sin(time_values.value * 0.5) + 1000\n", + "flux_err_values = np.full_like(flux_values, 0.01, dtype=np.float32)\n", + "\n", + "#Specify the flux units \n", + "unit_flux = u.electron/u.second" + ] + }, + { + "cell_type": "markdown", + "id": "d67112b8-6fdc-42ee-a9b5-ab789abc7954", + "metadata": {}, + "source": [ + "Using this data set we then use the `LightCurve` function to create our object and look at the data. " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "977c745f-df64-43ec-800b-a18e345e0406", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
LightCurve length=100\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
timefluxflux_err
electron / selectron / s
Timefloat64float32
2458000.01000.45365490544710.009999999776482582
2458000.1010101011000.40808661657670.009999999776482582
2458000.2020202021000.36147761788350.009999999776482582
2458000.3030303031000.31394677225240.009999999776482582
2458000.4040404041000.26561529413830.009999999776482582
2458000.5050505051000.21660643912810.009999999776482582
2458000.6060606061000.16704519048440.009999999776482582
2458000.7070707071000.11705794019420.009999999776482582
2458000.80808080831000.0667721664090.009999999776482582
.........
2458009.19191919171000.83244443768360.009999999776482582
2458009.2929292931000.8593563636950.009999999776482582
2458009.3939393941000.88407674353620.009999999776482582
2458009.4949494951000.90654253497940.009999999776482582
2458009.5959595961000.92669644535940.009999999776482582
2458009.6969696971000.94448707781210.009999999776482582
2458009.7979797981000.95986906241190.009999999776482582
2458009.8989898991000.97280317160380.009999999776482582
2458010.01000.98325642066630.009999999776482582
" + ], + "text/plain": [ + "\n", + " time flux flux_err \n", + " electron / s electron / s \n", + " Time float64 float32 \n", + "------------------ ------------------ --------------------\n", + " 2458000.0 1000.4536549054471 0.009999999776482582\n", + " 2458000.101010101 1000.4080866165767 0.009999999776482582\n", + " 2458000.202020202 1000.3614776178835 0.009999999776482582\n", + " 2458000.303030303 1000.3139467722524 0.009999999776482582\n", + " 2458000.404040404 1000.2656152941383 0.009999999776482582\n", + " 2458000.505050505 1000.2166064391281 0.009999999776482582\n", + " 2458000.606060606 1000.1670451904844 0.009999999776482582\n", + " 2458000.707070707 1000.1170579401942 0.009999999776482582\n", + "2458000.8080808083 1000.066772166409 0.009999999776482582\n", + " ... ... ...\n", + "2458009.1919191917 1000.8324444376836 0.009999999776482582\n", + " 2458009.292929293 1000.859356363695 0.009999999776482582\n", + " 2458009.393939394 1000.8840767435362 0.009999999776482582\n", + " 2458009.494949495 1000.9065425349794 0.009999999776482582\n", + " 2458009.595959596 1000.9266964453594 0.009999999776482582\n", + " 2458009.696969697 1000.9444870778121 0.009999999776482582\n", + " 2458009.797979798 1000.9598690624119 0.009999999776482582\n", + " 2458009.898989899 1000.9728031716038 0.009999999776482582\n", + " 2458010.0 1000.9832564206663 0.009999999776482582" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Create the LightCurve object and look \n", + "my_lc = lk.LightCurve(time=time_values, flux=flux_values * unit_flux, flux_err=flux_err_values * unit_flux)\n", + "my_lc" + ] + }, + { + "cell_type": "markdown", + "id": "e9111b52-5097-402d-a10e-f59cc6769f06", + "metadata": {}, + "source": [ + "We can now access the column values directly as an attribute of the object. " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "206ab9c8-7b6a-47d5-9756-d08ce84944c3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$[1000.4537,~1000.4081,~1000.3615,~1000.3139,~1000.2656,~1000.2166,~1000.167,~1000.1171,~1000.0668,~1000.0163,~999.96582,~999.91541,~999.86521,~999.81536,~999.76598,~999.7172,~999.66914,~999.62192,~999.57566,~999.53049,~999.48652,~999.44385,~999.4026,~999.36288,~999.32478,~999.28841,~999.25384,~999.22119,~999.19051,~999.1619,~999.13543,~999.11117,~999.08917,~999.06949,~999.05219,~999.0373,~999.02487,~999.01492,~999.00749,~999.00259,~999.00023,~999.00042,~999.00316,~999.00845,~999.01626,~999.02658,~999.03938,~999.05463,~999.0723,~999.09233,~999.11467,~999.13927,~999.16607,~999.19499,~999.22597,~999.25892,~999.29376,~999.3304,~999.36875,~999.40871,~999.45018,~999.49305,~999.53721,~999.58255,~999.62896,~999.67631,~999.72449,~999.77337,~999.82283,~999.87274,~999.92297,~999.97341,~1000.0239,~1000.0743,~1000.1246,~1000.1745,~1000.224,~1000.2729,~1000.3211,~1000.3685,~1000.415,~1000.4604,~1000.5046,~1000.5476,~1000.5891,~1000.6292,~1000.6676,~1000.7043,~1000.7393,~1000.7723,~1000.8034,~1000.8324,~1000.8594,~1000.8841,~1000.9065,~1000.9267,~1000.9445,~1000.9599,~1000.9728,~1000.9833] \\; \\mathrm{\\frac{e^{-}}{s}}$" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "my_lc.flux" + ] + }, + { + "cell_type": "markdown", + "id": "2fc39037-a7cf-4f41-bde6-050ac695a486", + "metadata": {}, + "source": [ + "We can also plot the data. " + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "ae7a82f2-dcc9-4ff5-bed1-d7307fdabf0d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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XmP0MjrdHaGbYHUPSf369f2eEoAYc+TIERc8dO/e3c455xy/pwMgnIKILl26ZGiR89prr6X74xEcWrzGLl12qALrPn36uAsKq1ev7veUAMTQbdRPPPGE3XLLLValShW/pwMg3IKInTt3hnYmAEIqV65c7hK63r17u0e5cuX8nhKAKKcOjEqnbNSokdWpU8fv6QAIxyDi/fffD+1MAIScChkHDRrkbrXWnzQ3AJCZXn75ZTv//PPt6quv9nsqADIZzZqBKFesWDGXm6z0gr///tvv6QCIUpMnT7YcOXJY27Zt/Z4KgCxAEAHEABU2Pvjggy6YOHTokN/TARBl5syZY9u2bbO77rrL76kACPcgQukR7733Xor1EgcOHMjIvACEWKVKlVxDBAUSx44d83s6AKLEokWLbOnSpfbwww+7xikAYkO6ayJWrlxpJUqUSPZ9d955p1111VWutRv8Q4tXJFWzZk2Li4tzvdtVI6EuTgCQXsuXL3c1kkOGDDnj9w2A6JYjs7oz6AF/0eIVybn88svdSeGwYcOsX79+7BwCSJd169bZxIkT3WtJzpw5/Z4OgCzGtgEQg5o3b+46qKiTCgB4tXnzZhs1apRrI50nTx6/pwPABwQRQIxSBxXtHr7xxht+TwVABNmxY4dLX1JKpC6zBBCbCCKAGKb6pT179ti7777r91QARIC//vrLtYt+/PHHXftoALGLIAKIYaqHeOCBB1xu84cffuj3dACEsX379rngoW/fvnb22Wf7PR0AkVxYvWDBAvdIbmGS0vsCZs+enZFPDSBE9POqRYE6NqkQv1GjRn5PCUCYOXjwoGsPra6L5cqV83s6ACI9iKADU3ijxSuCpVav2mHU/S8qkqxbt67fUwIQJo4ePeoCCN0zU6VKFb+nAyDSgwj1hY4Uv/zyi7355pu2Zs0a9/+VK1e2Tp06ue406RnndWxyd2z0798/2fcNHz480Yv08ePHbcqUKbZw4ULX3187QB06dLBatWql+Xlo8QovcuTI4QoldSqRO3dud6cEgNim30HaYGjTpo1deOGFfk8HQBiJ+poILfb79Onjukm0a9fOdaTZvn2764//+++/ex7ndWxqrr32WndakPBRunTpRGNGjhxps2bNsgYNGrgiWJ0sKO1k9erVIfjqAImdddZZNnjwYBs/frz9/PPPfk8HgI9OnDhhAwYMcC2hOZ0EEHNBhHbxc+XK5Xb4b7jhBmvdurX7b6ViTZo0yfM4r2NTU61aNZd/nvCRsF3e+vXrbdGiRXbbbbdZ586drVmzZm6Bp5vCdcEPkBl0eqV/Z6NHj3YF1wBiz8mTJ93JZOPGja1hw4Z+TwdAGIr6IEI79jqCLVCgQPzbihQp4hbw3377rR0+fNjTOK9j03Lo0CH3Yp2cxYsXu5MHBQ8BCl6aNm1qa9eutV27dnn4SgDBy58/vz399NPuMimdvAGIHadOnXI//zp9aNKkid/TARCm/hEL+ZxK0UhKb9NRrW7d9DLO69jUaIGmPFOdZKhGYsOGDYnev3HjRitTpswZdQ2VKlVyf27atCmozwOkh07FdCLx3HPP2W+//eb3dABkAZ2o62S9Ro0ads011/g9HQDR2p0pEpQtW9alZGi3Xx1oAkGAUoVk9+7dnsZ5HZtSAWu9evWsdu3a7jRjy5YtNnPmTFfQ+swzz1iFChXcOF0CVrhw4TM+PvC2tD6PTjmCoVuL9QCS+7f25JNPus4s6tx0zjnn+D0lAJkYQKghhxqEXH/99X5PB0CYi/ogQjspL7/8sr3wwgt24403uhfJadOm2d69e937jx075mmc17HJqVq1qnsE1KlTx+rXr2/dunVzNRUqnA48T3KLe6U0BfN51C0qGCoOb9++fVBjEXt0K61yo9WhRQ8umQKij36PqQ6qZMmS9t///tfv6QCIAFEfRKirhGoHtNMfuPyuYsWKLoVo+vTprpWll3FexwZLCzPlny5ZsiT+hEPBgk44kgoED4FgIiUTJkwIqsUrpxBIi4r51aVFAe4TTzxhpUqV8ntKAEIYQLzyyiuWL18+10IcAIIR9UGEqLuRFviqVcibN6+7ayHQRUk1B17HeR3rZcdXNRW62EeLfxVrJ5eyFDjxKFq0aKrPp+fgngiEitoPK61JQQSBBBBdAYQumbz99tv9ng6ACBL1hdUB2mFR9yQt9mXFihVu0a76hvSM8zo2GLp3QqcLgZOM8uXL27Zt286obQi03dT7gaykf9uBQEL/XgFEdgAxZswYF0AEm/4KADEXRCT05Zdfuk5IrVq1ci1UMzoupbFHjhyxrVu32r59+xKNTfr/gU5Ly5YtczdRBz5edRJqtTd37tz4cUpvmj9/vrshu3jx4p7/7kCoAgmlNxFIAJEbQLz66quuqyABBID0iPp0plWrVtnUqVPd4ly977WLr0X4RRdd5Bb8Xsd5GaugQq1bkxYuqwOTThyqVKlihQoVct2Z5s2b517MO3bsGD9OgYICCaVJKfBQOolqMHbu3Gndu3fP9K8dkFogoSJrUpuAyA0g9HtIF5kCQHpEfRChugHt7M+YMcNdAqfOEyocU/u6QHtWL+O8jk2OujF98cUXNnv2bJeqpH78l112mQs2kna+6dmzp02ePNkWLlxocXFxLnVKi7fq1auH8KsEeKfan8cee8wFETqVUJALIPwDiLFjx7qGGgQQADIi22m9oiCqKDDRJXZa5CVNw2rRooV7AKGyffv2+K5NBBJA+NKve7UnV8MNUpgApLWO1PUFqTXoifqTiFimS4PozoTMptOzQPtXLqQDwjeAGDlypKulo40rgFCIycJqAKEPJHQh3eDBg12TAADhQw06VIun02kCCAChQhABIGQX0imIGD58uGsqAMB/urx0yJAhrlHHzTff7Pd0AEQRgggAIaOmA08//bRLm1izZo3f0wFimi4vffLJJ61mzZqu8QcAhBJBBICQUtvioUOHugLOH3/80e/pADFJdwqp2YHahNNMA0BmIIgAEHK6P0WBxPjx4+27777zezpATNFFp7qjqGnTpu4BAJmB7kxRTHdM0OIVfsmbN68NGzbM3SWhO04aNmzo95SAqKefNXVJu/XWW6127dp+TwdAFCOIiGK0eIXfcufO7Wok1LlJi5uWLVv6PSUgau3du9ceffRRu/fee7mQFECmI50JQKbSzbjKzV69erW9/fbbfk8HiEo7duxwKUw6gSaAAJAVCCIAZLrs2bNb79697e+//7YxY8a4i68AhMbmzZtdoK40pgoVKvg9HQAxgiACQJbIli2bS7PIly+fPfvss+4CLAAZo1bKqj166qmnrGzZsn5PB0AMIYgAkKV0Y64uvhowYIAdO3bM7+kAEeubb75xJ3vqhFasWDG/pwMgxhBEAMhyrVq1squvvtr69OnjCq4BePPRRx/Z+++/b88884wVKFDA7+kAiEF0Z4pitHhFOLv88svdxXSqlRg4cKAVL17c7ykBYU/1RG+++ab98ccf7jZq1RsBgB8IIqIYLV4R7tRFpl+/fu4uCQUT559/vt9TAsKW6ohGjBhhhQsXdj8vqjMCAL+QzgTAV+ecc44NHjzYBb0rVqzwezpA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88927NgxK1WqlF199dXWqlUrv6eGDNq+fbv7mdX39sCBA1a8eHFr0KCB3XDDDZY7d26/p4cgqHh5xowZ7netHlpD9ejRw5o0aRIRay1OIpBhI0eOtFmzZrkXrzvvvNNV8g8cONBWr17t99SQQe+9954tWbLELrzwQve9bdasmfu+PvDAA7Z582a/p4cQtoV+5513WHhEmeXLl9vDDz9s+/btszZt2thdd91ll1xyie3evdvvqSGDdu3aZT179rR169ZZixYt3OtzlSpV7K233rJnn33W7+khSPv377epU6fa1q1brXz58hG31uIkAhmiyHnRokXuXorWrVu7tzVu3Ni6du1qEydOtOHDh/s9RWTA9ddfb7169bKcOXPGv+2KK65w3993333XHnroIV/nh9AYP368O2FSe2j9UkPk02VRI0aMcEFD3759U23TiMij3eiDBw/asGHD7LzzznNv0yaPGm7q9Fg71fny5fN7mkiDWqhOmjTJChcubBs2bHCBYSSttXhVQYYsXrzY/XLSi1dArly5rGnTprZ27Vq3W4LIVbVq1UQBhJx99tku5UU7J4h8q1atcj/H2tlC9Pjiiy/s77//dqmHeo0+cuSICxIRHQI3ChcqVCjR27UY1fc7Rw72iCNBzpw53fcsUtdaBBHIkI0bN7rc+H/+85+J3l6pUiX356ZNm3yaGTKLdrq0OClQoIDfU0EGnTx50l599VX7z3/+4/JrET1WrFjhXpeVunTPPffYf//7X5fS9PLLL7vaCES2GjVquD9ffPFF93tYi8gvv/zSPv74Y2vZsiWpiVFmY5iutQhVkSG6GTu5KDrwNnJvo8/nn3/uvq+33HKL31NBBs2dO9ctPp566im/p4JMKLpVkKjvrXYrb7vtNlu5cqXNmTPHpcGoVgKR6+KLL3ZFtdOnT7elS5fGv/3mm292p0+ILnvCdK1FEIEM0Y5W0nSXwDFb4P2IHkphGjNmjCvgUz4mIpdqH9TpQ7vTBQsW9Hs6CDGlLx09etSaN29ud999t3tbvXr17MSJEy541CaAUhMRuUqUKGHVq1d331d1zvvuu+9cgwQtLHUagehxLEzXWgQRyBD9A1bbsaQC/6AD/8AR+fbu3WuDBg1yx6kq1MyePbvfU0IGqDWkCi9ZbESnwGvvlVdemejt6uyiIEJ51AQRkUtFti+99JJLRyxWrJh7m4IJ1b2o0Fbfd1JOo0euMF1rUROBDHcW0OIyqcDbihYt6sOsEGpKf3jiiSfcn2opx/c18lNd5s2bZ9dee607Jv/zzz/dQ7+klAKj/1bfeUT2a3NyhbeBUyd170Hk+uijj6xChQrxAURAnTp13AmUcugRPYqE6VqLkwhkiPoa6yIydYpIWPCj3tWB9yOyaafjySeftG3btrn8anVmQmRT/qx2LMeOHeseSXXp0sVdRkbHpshVsWJFV1yt73XZsmXj366gUdiljmxqbpFcC1elq4k2AxA9yofpWosgAhlSv359mzlzpjseD/Qu1m7m/PnzXd953aCJyKVfRM8884xLfXj00UddLQQinwLB/v37J5vipBtUFTyULl3al7khNC6//HJ3l8unn37qLosM+OSTT1wqYqC7DyKTUtF++OEHt7mjrj0J05zUCpRua9GlfpiutQgikCH6x6t/3LosRbeiauGhi2527txp3bt393t6CMElZOr8cemll7r0Fl1wlFCjRo18mxvSTyktl1122Rlvf//9992fyb0PkUWpLurKpCBCmwEqwFV3JvWbV7tXUhIjmxaS33//vatP043VKqz+9ttv3dvUspnvb+SY87+OaYEOS8uWLYv/b9Ws5c2bN2zXWtlOq+k7kMF0F+1gqvWn8my1A6LWcxdddJHfU0MG9evXz11GlpIPPvggS+eDzP9+q2vT6NGj/Z4KQkCpLerWo91KpTFpt1ILzuuuu87vqSEEdIvxW2+95eoftMlTsmRJ1zXvxhtvpPFFBLnjjjtcMJCccePGue9ruK61CCIAAAAAeEJ3JgAAAACeEEQAAAAA8IQgAgAAAIAnBBEAAAAAPCGIAAAAAOAJQQQAAAAAT7hsDgAAAIhB7733XvyFd7rEbsiQIfbPf/4zqI8liAAAAABizIcffmjLly+3YcOGucsof/vtN8uZM2fQH89lcwAAz6699lpP40uUKGGvv/56/C3oCW9iDXe68XnUqFHx/587d253E3RyX4+kt7gn/TrpJmHt8hUpUsQqVKhgl156qdWtWzfFG4bbtm3rdggDevToYU2aNAnJ3wtA7Dp58qR17tzZhg4d6k4g0oOTCACAZ40bNz7jbWvWrLE//vjDypcv7x4JFShQwCJd4O+VK1eudH+9tG936NAh27Ztmy1cuNAWLFjgfoH36tXLKlWqdMbHXXnllXb06FHbtGmTewCxYP369e5n46effrKdO3da/vz5rXLlynbrrbdamTJlPD/ftGnTbPLkyXbuuefa6NGjE71v5cqV1r9//2Q/bvjw4ValSpX4/9++fbt7np9//tkOHDjgdu8bNGhgN9xwg9tcyCyHDx+2GTNmuK+LHnFxcaluKBw/ftymTJniXmM0tly5ctahQwerVatW/Jjdu3e715bFixfb7NmzLW/evO7vcfXVVwc9L4IIAIBnDz744BlvGzFihAsitLPevn37FD9Ov7iKFi1qkSa1v1d6vl76Wk2aNMm++uort4h55pln7Pzzz0805r777nN/vvXWWwQRiKk8fW1K1K9f3y2A//77b5e3/8ADD9izzz5r5513XtDP9ddff7mTw7QW+To1vOCCCxK9LeEO/a5du6xnz55usd2iRQsX2Kxdu9b9bP7666/26KOPWmbZv3+/TZ061QUt2shQ4JOakSNHuuCgVatWdvbZZ9tnn31mAwcOtMGDB1u1atXigwidciow0smw/tTfoWzZsvFj0kIQAQDIMkprwv9foPTp08fy5Mljn376qUuZSpg2BUQrpTXqtSC54Fquv/56dzqXMD//iiuusK5du9q7775rDz30UNCfa/z48e4U49SpU24xnhItnBW0pES7+lp0q34gEMQ0a9bMnS7q1EQ7/vny5Uv2Y/U+narUq1cv2fd/8cUXVqdOnRQDHaU/asOhcOHCtmHDBhfMpEQnFYsWLbJOnTpZ69at409C9bWbOHGiO12RwImqUibPOussF5zo5PO7774LOoigxSsAIEsXD9rx+/PPPxO9XW+74447XJ6udtzuuusuu/HGG+3ee+91NQkBP/74o9u1v/nmm90vv+effz7FhYGe66OPPnKLEY3X83Xv3t0d3et94UJ/by0eNm7caKtXr/Z7OoDvqlatekaBr3bUlY60devWoJ9H9Vfakb/zzjuDGq9Uw5ReG/Q+KVSoUKK3Fy5c2P7xj39Yjhw5Ui1gVvDx9ddfn/G+Tz75xJ2u6LQgJfpa6PMEQ39fzUcBToAChqZNm7qTE52oiNLCUptzMAgiAABhQ79oZ82a5Xb6tBumYEO78wok9MtxwIAB7pf8RRdd5Bbe2h3UEX3SHiFKmXr88cftlVdeccf02omsWbOm7d271x3dq42hdibDgdIjLr74YvffaaUpALFK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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "my_lc.plot()" + ] + }, + { + "cell_type": "markdown", + "id": "1f06c822-bd67-4270-9626-7b59e662c294", + "metadata": {}, + "source": [ + "Additional meta data or keyword arguments may be added via a dictionary as part of `LightCurve` function. \n", + "\n", + "For example we could define the mission and the telescope we obtained the data from via the following: " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "31c5b6fc-0470-47e9-963f-a32d51cda915", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MY_FAKE_TELESCOPE MY_FAKE_MISSION\n" + ] + } + ], + "source": [ + "my_lc.meta['TELESCOP'] = \"MY_FAKE_TELESCOPE\"\n", + "my_lc.meta['MISSION'] = \"MY_FAKE_MISSION\"\n", + "print(my_lc.meta['TELESCOP'], my_lc.meta['MISSION'])" + ] + }, + { + "cell_type": "markdown", + "id": "b5ce174b-765c-4fac-a494-dd71bbd40406", + "metadata": {}, + "source": [ + "## 2: Saving the LightCurve Object as a FITS file\n", + "\n", + "We can now convert our object into a FITS file using the `to_fits` function. For this we simply need to state the file name and path.\n", + "Be sure to state if you want your file to be overwritten or not using either False or True." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "ed2bc5bb-f010-4b97-8feb-4da52cc0e131", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'LightCurve saved to ./my_custom_lightcurve.fits'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "output_filename = './my_custom_lightcurve.fits'\n", + "my_lc.to_fits(output_filename, overwrite=True)\n", + "f\"LightCurve saved to {output_filename}\"" + ] + }, + { + "cell_type": "markdown", + "id": "09d9d7da-5ffe-47e8-aff0-9c115eb8e024", + "metadata": {}, + "source": [ + "Note we can also add information to our fits file using an extra_data dictionary. Defined extra keywords or columns would then be included in the FITS file. Keywords would be stroed in the primary header and np.array data as columns in the 1st extension. As an example let's add an \"ORIGIN\" keyword which will indicate where got our data from." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "6f2ed2c7-094d-4222-a9ba-7bff957198db", + "metadata": {}, + "outputs": [], + "source": [ + "extra_data = {\"ORIGIN\": \"Tutorial\"}" + ] + }, + { + "cell_type": "markdown", + "id": "026c04c9-d418-4b71-b3c6-95c9a0734b59", + "metadata": {}, + "source": [ + "We can then overwrite our old file and add this so when we read it in, it will be there." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "8f78a39b-814d-4299-a5f0-a5d51300aaec", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[, ]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "my_lc.to_fits(output_filename, overwrite=True, **extra_data)" + ] + }, + { + "cell_type": "markdown", + "id": "534c2fb0-e262-4e0d-84d0-585eca7ae178", + "metadata": {}, + "source": [ + "## 3: Reading in a FITS file\n", + "\n", + "We can now use the `read_generic_lightcurve` funtion to read in our FITS file as a LightCurve Object. To do this we must specify the file and the relevent columns for our data." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "ebd49c8e-dcfc-48a2-a8cd-cc4c5b75fe2a", + "metadata": {}, + "outputs": [], + "source": [ + "read_lc = lk.io.generic.read_generic_lightcurve(filename='./my_custom_lightcurve.fits', time_column=\"time\", flux_column=\"flux\", flux_err_column=\"flux_err\", time_format=\"jd\")" + ] + }, + { + "cell_type": "markdown", + "id": "4f60b635-f2f9-4ff9-9a9b-08bec01fd449", + "metadata": {}, + "source": [ + "We can now query the object as done previously." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "b5ebba56-1476-45a5-9482-d2230a476338", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
LightCurve length=100 LABEL="None" FLUX_ORIGIN=lightkurve.LightCurve.to_fits()\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
timefluxflux_err
electron / selectron / s
Timefloat32float32
2458000.01000.45367431640620.009999999776482582
2458000.1010101011000.40808105468750.009999999776482582
2458000.2020202021000.36145019531250.009999999776482582
2458000.3030303031000.313964843750.009999999776482582
2458000.4040404041000.2656250.009999999776482582
2458000.5050505051000.21661376953120.009999999776482582
2458000.6060606061000.16705322265620.009999999776482582
2458000.7070707071000.11706542968750.009999999776482582
2458000.80808080831000.06677246093750.009999999776482582
.........
2458009.19191919171000.83245849609380.009999999776482582
2458009.2929292931000.8593750.009999999776482582
2458009.3939393941000.88409423828120.009999999776482582
2458009.4949494951000.90655517578120.009999999776482582
2458009.5959595961000.92669677734380.009999999776482582
2458009.6969696971000.94445800781250.009999999776482582
2458009.7979797981000.95983886718750.009999999776482582
2458009.8989898991000.97277832031250.009999999776482582
2458010.01000.98327636718750.009999999776482582
" + ], + "text/plain": [ + "\n", + " time flux flux_err \n", + " electron / s electron / s \n", + " Time float32 float32 \n", + "------------------ ------------------ --------------------\n", + " 2458000.0 1000.4536743164062 0.009999999776482582\n", + " 2458000.101010101 1000.4080810546875 0.009999999776482582\n", + " 2458000.202020202 1000.3614501953125 0.009999999776482582\n", + " 2458000.303030303 1000.31396484375 0.009999999776482582\n", + " 2458000.404040404 1000.265625 0.009999999776482582\n", + " 2458000.505050505 1000.2166137695312 0.009999999776482582\n", + " 2458000.606060606 1000.1670532226562 0.009999999776482582\n", + " 2458000.707070707 1000.1170654296875 0.009999999776482582\n", + "2458000.8080808083 1000.0667724609375 0.009999999776482582\n", + " ... ... ...\n", + "2458009.1919191917 1000.8324584960938 0.009999999776482582\n", + " 2458009.292929293 1000.859375 0.009999999776482582\n", + " 2458009.393939394 1000.8840942382812 0.009999999776482582\n", + " 2458009.494949495 1000.9065551757812 0.009999999776482582\n", + " 2458009.595959596 1000.9266967773438 0.009999999776482582\n", + " 2458009.696969697 1000.9444580078125 0.009999999776482582\n", + " 2458009.797979798 1000.9598388671875 0.009999999776482582\n", + " 2458009.898989899 1000.9727783203125 0.009999999776482582\n", + " 2458010.0 1000.9832763671875 0.009999999776482582" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "read_lc" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "dde547a9-4f4e-45fd-b2a9-7988ec105374", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$[1000.4537,~1000.4081,~1000.3615,~1000.314,~1000.2656,~1000.2166,~1000.1671,~1000.1171,~1000.0668,~1000.0163,~999.96582,~999.91541,~999.86523,~999.81537,~999.76599,~999.71722,~999.66913,~999.62195,~999.57568,~999.53052,~999.48651,~999.44385,~999.40259,~999.36285,~999.32477,~999.28839,~999.25385,~999.22119,~999.19049,~999.16193,~999.13544,~999.11115,~999.08917,~999.06952,~999.05219,~999.03729,~999.02484,~999.01489,~999.00751,~999.00256,~999.00024,~999.00043,~999.00317,~999.00842,~999.01624,~999.02655,~999.03937,~999.05463,~999.07233,~999.09235,~999.11469,~999.13928,~999.16608,~999.19501,~999.22595,~999.25891,~999.29376,~999.33038,~999.36877,~999.40869,~999.4502,~999.49304,~999.53723,~999.58258,~999.62897,~999.67633,~999.72449,~999.77338,~999.82281,~999.87274,~999.92297,~999.97339,~1000.0239,~1000.0743,~1000.1246,~1000.1745,~1000.224,~1000.2729,~1000.3212,~1000.3685,~1000.415,~1000.4604,~1000.5046,~1000.5475,~1000.5891,~1000.6292,~1000.6676,~1000.7043,~1000.7393,~1000.7723,~1000.8034,~1000.8325,~1000.8594,~1000.8841,~1000.9066,~1000.9267,~1000.9445,~1000.9598,~1000.9728,~1000.9833] \\; \\mathrm{\\frac{e^{-}}{s}}$" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "read_lc.flux" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "95d9db0a-d902-44ff-8d83-552c275f5f14", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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Vavm5p5QqVKl7IILLnCnKinRIlqBRqxSqpryRL/77ju/pwIAQEiotlTBg7IRSpYs6fd0gNioiQjWpk2bXK1B0iLjypUru183b95sxYoV8zTWy2sG2w9a19orkEjO6NGjXQ2IAhedSujk5VwXzyjoCIYCmqRBTThfRvfEE0+4UyjVkQAAEKlOnz7tTiCUkcDPNESamAgi9u7dm+yJReA5Fe56HevlNYPx5Zdfut9z9913J3peHYnq1q3rLprREefWrVvdjc59+vSxF154wSpUqJDia6aW4pU0VahNmzYWCZQnqnxR/fmfffZZdm0AABHr1VdftZo1a7qf80BMBhHaRQ9nx48fT3anXelHgY97HevlNc9FKUyvv/6667TUsGHDs1Kf9AioVauW1atXzzp37uzqQVJrATdhwoSgWrxGwilEQgULFrSnn37aBRMKpPLmzev3lAAA8EQ1kFmzZnV1kkBM1kRo5/2RRx6xcKaFvdqxJhVY6AcW/l7GennN1Ozbt88thrXY1+663lDORfUTtWvXdi1iU6uR0GsG84i0IELKlCljjz76qMsjPXnypN/TAQAgaF9//bW7Yyvc109AhgYRefLksaZNm1o4U/68FutJBZ4rUqSI57FeXjMlhw4dcik5+lUnCsH8noQ3OmvxrIKsWFW9enVr0aKFu4gu3E/DAAAI3AWhO66eeuop7j5CRIvo7kzB0h0S6r+ctNB4/fr18R/3OtbLayZHJxbPPfecew3tpqdUUJ2SHTt2uNOOXLlyWSy7/vrrXYH5m2++6fdUAABI1Z9//mljxoxxG4eRmAUAZEgQoR14Hc0l3Z3XN4zy1jt16uR23dX+NLOphkAdEObMmRP/nFKR5s2b57ohJOyiFOxYL6959OhRV/egPtCiFCT9nejvQilMqd06Hfg9Canz09KlS93N2NxoadaqVSt38eCnn37q91QAAEhWXFyc2zxUTR93QSAaZAtlgdDHH39sY8eOje9QpF363r17u4Ww0k20kFagoShcef2hoM+pdKBANyQtrgP/3bx5c5dupUW9Fv0qRNZcdNPzggULbNeuXdalS5dErxfsWC+vuXHjRuvbt298FyRdjrdkyRK7+uqr7eDBg7Zw4cJE43WRXICCDZ04KNBQQbG6M82dO9d1KWrfvn1I/g6jgfpr62i4RIkSrtMFAADhQunHyjpQLZ/a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zet2csePH+8KUpXilCtXLr+nBaTq+++/d804nnzyyVTr5gAg3MVMEHHzzTfb2LFjbcyYMXbnnXe6XX8VjOzbt899/Pjx457GeR17Lkphev31193JRcOGDROlPekRUKtWLbfz2rlzZ1d3MWDAgBRfc8KECUEVVnMKgUilk7kHHnjALcyU4qTgOrmTPCAc7n9QwKtufKp/IOAFEOliJoho2rSp7d692+3iq7WqVKxY0e644w6bPn16/Bt6sOO8jk2Ngg6lZWjBr0XQuS4XUu1E7dq1bfHixYlOQZLS69GdCbFA3w9qq6wTiRYtWlijRo38nhIQT2mqSl/SLewKegEgGsRMECHt2rVzC3zVKuTJk8flVWs3XxLezRDsOK9jk3Po0CF3kZZ+VWpGkSJFgvqzqCuN6i6OHTtGoAD89z4JXbD46quvum43Xbp04ZQNvtNdQDqxfvzxx7nXB0BUiakgIpBHrcLkgBUrVrgFedLc1GDHeR2bkNKd1JVj+/btbgfVSxqGCvPUXpYjccAS1RB17drVFi5caN26dXP3uJx//vl+TwsxSKfESinVBpPu/tHPCQCIJjHT4jU56je/ceNGl/6g3Or0jktprC6QU82DWvkl/AGjwuh169a5FKaUdqgS/p6AzZs329KlS61GjRrnnA8Qixo0aOAu7tLiTZc4xsidmggTO3fudHf9lChRwqWqEkAAiEYxcxKhfvJTp051C+98+fK5rkrz5s1ztz5rwe91nJexCip08VzCLki6nXTJkiV29dVX28GDB93OadJFkCjQ0ImDgoyCBQu67kxz5851bWTbt2+fwX9rQOQqWbKkS2/SbrAupuvVq5f7PgUykt7LdYGc/r1deOGFfk8HADJMzAQRqjXQrv2MGTPcfQvaIWrbtq27OTphYXKw47yOTWrTpk3uV50o6JFUIIhQN6avvvrKZs+e7e59KFCggNWpU8cFJCqwTo261SQ9qWjWrJl7ALFA34f333+/y0tXC9hHHnnELr/8cr+nhSikE2fd56MNnlGjRlGPAyDqZTnDOX/UUbDRsmVL126Womvg/8TFxbkL6nRCocCCRR5CRYX8r732mt17772uUxgAxMI6koR6ADFBeem6V0VtmFV8rXokID3UHU/3BM2aNcsFqAQQAGJJzKQzAYA0btzYatas6YqulbPesWNHTiXg2dq1a10Aod2666+/3u/pAECm4yQCQMwpXLiwu/yrXLly7lRCTRGAYJw4ccLeeOMNmzJlig0ZMoQAAkDM4iQCQEzKkiWL3Xjjje5UYsSIEe5UQjntKowFkqM7gMaNG+eaZzz00EN+TwcAfEUQASCmqcuaTiXUmlOnEkpvUutlIODAgQPuJnT1IRk6dKjlz5/f7ykBgO8IIqIYLV6B4E8lGjZs6FoqK1Xlk08+sS5durgAA7FLQcPnn3/uCqd18kB7YAD4/wgiopgu2qLFKxC8PHnyuOBbnZueffZZl+9+++23czN8DNq2bZu79+Giiy5yBdQU3wNAYvxkBIAkdEO8Lgw7ffq0S3FatWqV31NCJt4nouBB6UuB9DYCCAA4GycRAJDCbdf/8z//Y40aNXLFtO+99549+uij7rI6RJ9Tp07ZRx99ZHPnzrX27dtz5wMAnANBBACkolChQta7d2/79ddf3d0SFSpUcItMUgWjx3/+8x978803rX79+vbyyy9btmz8aASAc+GdEgCCoOBBtxJ/++231qNHD7vpppusefPmLDgjmAJDBQ8qoH/++eetQIECfk8JACIGP/0AwEMXp2uuucaluqhjT+fOne3WW291t2Ar/QmR4ffff3fBg76enTp1sjJlyvg9JQCIOFnOqIcdosrhw4etZcuWVrp0aVq8Ahno2LFjNmPGDPv666/trrvusgYNGriFKcLTrl27bPz48Xbw4EG7//77rXz58n5PCQDCdh05bdq0VFN3OYmIYrR4BTKWbrdu3bq1u8F4+vTp9thjj7k3Xp1W0BY2fPz55582ZcoU27lzp+u2VK1aNb+nBAARjyACANIpd+7crtj6zjvvdF2cpk6dak2bNrUmTZrQHtRHv/zyiwsejh8/bnfffbe78wEAEBoEEQAQInnz5rUOHTpYmzZt7LPPPnO3XtetW9ddWKePIXP89NNPLnhQofS9995rF154od9TAoCoQxABABmQ5qQUpxYtWtiiRYusb9++rruTTioo4s24+pR58+a5ex70d92zZ08rXry439MCgKhFEAEAGUR1Eddff717rF692hX1HjhwwLWGvfbaa2kPGwLbt2+3Dz74wNavX++6ZA0bNsyllwEAMhY/wQAgE1SvXt09FER88sknLtXp0ksvdScW3ILtzYkTJ9x9Hfp7zJMnjzvhUbtdOmMBQOYhiACATJQ/f37X0alVq1bupuTXXnvNBRbq6HTDDTdYwYIF/Z5iWDp9+rSrdfj0009dlyXVmihNTDeKAwAyH0FEFOvevTv3RABhSrvmV1xxhXscPXrU3TUxdOhQO3XqlLtvon79+m6XPZbpGqMNGza4Woc1a9bYZZddZvfcc49dcMEFfk8NAGJeTFw2pzZ/b7/9tq1du9b9f5UqVVwHlaQXDQU7zuvYlI7j1T1k4cKFFhcXZ2XLlrW2bdtajRo10jQuLZeEAAg/ughN3+8qyNbb81VXXeVOKWKlIFsF0j/88IMLqnSzdKVKldwJzcUXX0y6EgBkgmDXkVEfRGix37t3bytatKjr2a4/rvJotSAfMWJE/A/mYMd5HZuS4cOHu5xedW8pVaqUzZ8/3zZu3GiDBw92Pyy9jkuIIAKIDkeOHLFly5bZN9984wqIK1as6NJ4VEsRLcXDev/cvHmzS+1aunSp2zi58sorXeH5+eef7/f0ACDmHCaI+D8DBgywdevW2RtvvOFykWXv3r328MMP2+WXX+5yar2M8zo2OTqe79Gjhzu5uOOOO9xzugxJt92qr7kCBy/jkiKIAKKP3qp//fVXW7x4sa1atcrt2OtkUu85SvMpUqSIRYKTJ0+6jZDly5fbypUrXaBUrlw5d7pas2ZNy5cvn99TBICYdjjIdWTU10Qoj1Y5x4HFvhQuXNjt4muHTz/AtKMX7Dgvr5kSnSyoVkGnGAE5cuRw7QknTZpku3fvtmLFigU9DkD0UyqPTiL0CBQab9myxRUbv/zyy24jQ+87SqnUPQkap1NRP9vIKjVLAYM2RHSCq/csvacpRUlBgzpTxXrdBwBEqqgPInQ0roufktJz2hHTD+GqVasGPc7La6Zk06ZNVrp06bOiu8qVK7tfdbSv4CDYcQBijxbj2sHXQ4tx0QaG3hd0YjFr1izbunWrCzayZ8/u3ivUSrZEiRLxv2ojRIGH11oDnYroJERBgjpLKTj4448/7M8//3SPQ4cOuTEKEBQwBOoalAJKXQMARIeoDyK0E6dLiNTxJGvWrPFBgHbGZM+ePZ7GeR2bHO0YJteWMPBc4PcHOy6146hgaIGhB4DIpoDgoosuco+E9P60a9cu1xp1x44dLpVI/60gQIFHWrJac+XKZXnz5nWBiAKU8847zy655BL3q54HAES3qA8ibr75Zhs7dqyNGTPGXUikH5bK8dq3b198jYGXcV7HJkcfT27RrlSlhL8/2HEpUS1FMNSzvk2bNkGNBRB59D6iU009AAAIhagPIpo2beqO2mfOnGkLFixwzylXWIXK06dPd7tpXsZ5HZscBQHaGUwqEBQEgoRgx6VkwoQJQRVWcwoBAAAAL6I+iJB27dq5Bb5qFZSjq44mKkyWhDtzwY7zOjYpFWEnl4oUOMkIdFkJdlxKFEDQnQkAAAChlvg64yimHF11T9JiX1asWOGK/JLe6RDsOK9jE1IhpHq+J61ZUJ1F4ONexoULnZq88847yZ6eIPLx9Y1efG2jG1/f6MXXNrqdCPOvb8wEEQnpJlS1HdQFbupwkt5xKY09evSobdu2zfbv359obL169VzHlDlz5sQ/p38g8+bNczdfBzouBTsuXGhu7777btj+Y0f68PWNXnxtoxtf3+jF1za6nQjzr2/UpzOtXr3apk6d6nqS6xIj7eJrEa57HrTg9zrOy1gFFbp4LmnhsgIABQhKf1KAoW4mqq1Q95QuXbp4HgcAAABkpqgPIlQ3oJOBGTNmuFaG6o3etm1b11c90J7VyzivY1PSvXt3mzx5si1cuNDi4uJcSlT//v2tevXqaRoHAAAAZJaoDyK0ez9w4MCQjfMyVj3TP/roo2Q/ps5KHTt2dI/UBDsuOQpAkqZhNWvWzD0AAACAtIrJmohY8dJLL7n7LBI+ojWA+OSTT/i8UcyPPy9f28wRa3/PfH2j9/PyteXzxhqCCESFWHtTibU3s1haEPC15fNGk1j6e+Zry+eNNQQRAAAAADwhiAAAAADgCUEEAAAAAE+ivjtTLDpz5oz7NelN1xkt8Pky+/OKLuXj82asWPv68rXNHLH09+zX5+XrG72fk69tdH/ewz59fQOfL7CeTEmWM+cagYjz119/WYcOHfyeBgAAACLUhAkTrGjRoil+nCAiCila3rt3r+XOnduyZMni93QAAAAQIRQa6DLlwoULn3XfWEIEEQAAAAA8obAaAAAAgCcEEQAAAAA8IYgAAAAA4AktXpFuJ06csClTptjChQstLi7OypYta23btrUaNWr4PTWk04YNG2zBggW2cuVK27Vrl+XLl8+qVKli99xzj5UuXdrv6SGEpk2bZpMnT7YLLrjAXn31Vb+ngxD55Zdf7N1337Wff/7Zjh8/biVLlrSbbrrJWrRo4ffUkE5//PGH+57V1/bgwYNWrFgxq1+/vt1+++2WK1cuv6eHIKh4ecaMGe5nrR5aQ3Xt2tUaNWoUEWstTiKQbqNGjbJZs2a5N68HHnjAVfIPGDDA1qxZ4/fUkE4ffPCBLV682C677DL3tW3SpIn7uj7++OO2ZcsWv6eHELaFfu+991h4RJnly5fbE088Yfv377eWLVvagw8+aFdddZXt2bPH76khnXbv3m3du3e39evXW7Nmzdz7c9WqVe2dd96xF1980e/pIUgHDhywqVOn2rZt26xcuXIRt9biJALposh50aJF7l6KO+64wz3XsGFDe+yxx2zixIk2fPhwv6eIdLjtttusZ8+elj179vjnrr32Wvf1ff/9961Hjx6+zg+h8dZbb7kTJrWH1g81RD5dFjVy5EgXNPTp0yfVNo2IPNqNPnTokA0bNswuvPBC95w2edRwU6fH2qnOmzev39PEOaiF6qRJk6xQoUK2ceNGFxhG0lqLdxWky7fffut+OOnNKyBHjhzWuHFjW7dundstQeSqVq1aogBCSpUq5VJetHOCyLd69Wr3faydLUSPr776yv7++2+Xeqj36KNHj7ogEdEhcKNwwYIFEz2vxai+3tmysUccCbJnz+6+ZpG61iKIQLps2rTJ5cb/85//TPR85cqV3a+bN2/2aWbIKNrp0uIkf/78fk8F6XTq1Cl744037MYbb3T5tYgeK1ascO/LSl16+OGH7X/+539cStPYsWNdbQQi2yWXXOJ+ffnll93PYS0iv/76a/vss8+sefPmpCZGmU1hutYiVEW66Gbs5KLowHPk3kafL7/80n1d7777br+ngnSaM2eOW3wMGjTI76kgA4puFSTqa6vdynbt2tmqVavs448/dmkwqpVA5KpZs6Yrqp0+fbotWbIk/vl//etf7vQJ0WVvmK61CCKQLtrRSpruEjhmC3wc0UMpTK+//ror4FM+JiKXah/U6UO70wUKFPB7OggxpS8dO3bMmjZtag899JB7rm7dunby5EkXPGoTQKmJiFzFixe36tWru6+rOuf98MMPrkGCFpY6jUD0OB6may2CCKSL/gGr7VhSgX/QgX/giHz79u2zgQMHuuNUFWpmzZrV7ykhHdQaUoWXLDaiU+C997rrrkv0vDq7KIhQHjVBRORSke0rr7zi0hGLFi3qnlMwoboXFdrq607KafTIEaZrLWoikO7OAlpcJhV4rkiRIj7MCqGm9Idnn33W/aqWcnxdIz/VZe7cuXbLLbe4Y/KdO3e6h35IKQVG/62+84js9+bkCm8Dp07q3oPI9emnn1qFChXiA4iAWrVquRMo5dAjehQO07UWJxFIF/U11kVk6hSRsOBHvasDH0dk007Hc889Z9u3b3f51erMhMim/FntWI4bN849krr//vvdZWR0bIpcFStWdMXV+lqXKVMm/nkFjcIudWRTc4vkWrgqXU20GYDoUS5M11oEEUiXevXq2cyZM93xeKB3sXYz582b5/rO6wZNRC79IHrhhRdc6sPTTz/taiEQ+RQI9u3bN9kUJ92gquDhvPPO82VuCI1rrrnG3eXyxRdfuMsiAz7//HOXihjo7oPIpFS0//znP25zR117EqY5qRUo3daiS70wXWsRRCBd9I9X/7h1WYpuRdXCQxfd7Nq1y7p06eL39BCCS8jU+ePqq6926S264CihBg0a+DY3pJ1SWurUqXPW8x9++KH7NbmPIbIo1UVdmRREaDNABbjqzqR+82r3SkpiZNNC8scff3T1abqxWoXVy5Ytc8+pZTNf38jx8X87pgU6LC1dujT+v1WzlidPnrBda2U5o6bvQDrTXbSDqdafyrPVDohaz11xxRV+Tw3p9OSTT7rLyFLy0UcfZep8kPFfb3VtevXVV/2eCkJAqS3q1qPdSqUxabdSC85bb73V76khBHSL8TvvvOPqH7TJU6JECdc1784776TxRQS57777XDCQnDfffNN9XcN1rUUQAQAAAMATujMBAAAA8IQgAgAAAIAnBBEAAAAAPCGIAAAAAOAJQQQAAAAATwgiAAAAAHjCZXMAAABADPrggw/iL7zTJXZDhgyxf/7zn0H9XoIIAAAAIMZ88skntnz5chs2bJi7jPK3336z7NmzB/37uWwOAODZLbfc4ml88eLFbfz48fG3oCe8iTXc6cbn0aNHx/9/rly53E3Qyf19JL3FPenfk24S1i5f4cKFrUKFCnb11Vdb7dq1U7xhuFWrVm6HMKBr167WqFGjkPy5AMSuU6dOWceOHW3o0KHuBCItOIkAAHjWsGHDs55bu3at/fnnn1auXDn3SCh//vwW6QJ/rhw5cqT570v7docPH7bt27fbwoULbcGCBe4HeM+ePa1y5cpn/b7rrrvOjh07Zps3b3YPIBZs2LDBfW+sXLnSdu3aZfny5bMqVarYPffcY6VLl/b8etOmTbPJkyfbBRdcYK+++mqij61atcr69u2b7O8bPny4Va1aNf7///jjD/c6P//8sx08eNDt3tevX99uv/12t7mQUY4cOWIzZsxwfy96xMXFpbqhcOLECZsyZYp7j9HYsmXLWtu2ba1GjRrxY/bs2ePeW7799lubPXu25cmTx/05brrppqDnRRABAPCsW7duZz03cuRIF0RoZ71NmzYp/j794CpSpIhFmtT+XGn5+9Lf1aRJk+ybb75xi5gXXnjBypcvn2jMo48+6n595513CCIQU3n62pSoV6+eWwD//fffLm//8ccftxdffNEuvPDCoF/rr7/+cieH51rk69SwUqVKiZ5LuEO/e/du6969u1tsN2vWzAU269atc9+bv/76qz399NOWUQ4cOGBTp051QYs2MhT4pGbUqFEuOGjRooWVKlXK5s+fbwMGDLDBgwfbxRdfHB9E6JRTgZFOhvWr/gxlypSJH3MuBBEAgEyjtCb8/wVK7969LXfu3PbFF1+4lKmEaVNAtFJao94Lkguu5bbbbnOncwnz86+99lp77LHH7P3337cePXoE/bneeustd4px+vRptxhPiRbOClpSol19LbpVPxAIYpo0aeJOF3Vqoh3/vHnzJvt79TGdqtStWzfZj3/11VdWq1atFAMdpT9qw6FQoUK2ceNGF8ykRCcVixYtsg4dOtgdd9wRfxKqv7uJEye60xUJnKgqZTJnzpwuONHJ5w8//BB0EEGLVwBApi4etOO3c+fORM/rufvuu8/l6WrH7cEHH7Q777zTHnnkEVeTEPDTTz+5Xft//etf7offSy+9lOLCQK/16aefusWIxuv1unTp4o7u9bFwoT+3Fg+bNm2yNWvW+D0dwHfVqlU7q8BXO+pKR9q2bVvQr6P6K+3IP/DAA0GNV6phSu8N+pgULFgw0fOFChWyf/zjH5YtW7ZUC5gVfHz33Xdnfezzzz93pys6LUiJ/i70eYKhP6/mowAnQAFD48aN3cmJTlREaWGpzTkYBBEAgLChH7SzZs1yO33aDVOwod15BRL64fjMM8+4H/JXXHGFW3hrd1BH9El7hChlqn///vbaa6+5Y3rtRF5++eW2b98+d3SvNobamQwHSo+oWbOm++9zpSkAsUrf40prCra+Su8Tb7zxht14440uJepc9D7T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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "read_lc.plot()" + ] + }, + { + "cell_type": "markdown", + "id": "b2ff9422-1392-4f65-b56a-9e328e541857", + "metadata": {}, + "source": [ + "We can even check the meta data to make sure our telescope, mission, and origin information was saved correctly." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "7befd3bf-034f-4622-9fac-67bcf49e58a9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'EXTNAME': 'PRIMARY',\n", + " 'CHECKSUM': 'AaAiBX9ZAaAfAU7Z',\n", + " 'DATASUM': '0',\n", + " 'SIMPLE': True,\n", + " 'BITPIX': 8,\n", + " 'NAXIS': 0,\n", + " 'EXTEND': True,\n", + " 'NEXTEND': 2,\n", + " 'EXTVER': 1,\n", + " 'ORIGIN': 'Tutorial',\n", + " 'DATE': '2026-03-04',\n", + " 'CREATOR': 'lightkurve.LightCurve.to_fits()',\n", + " 'TELESCOP': 'MY_FAKE_TELESCOPE',\n", + " 'INSTRUME': None,\n", + " 'OBJECT': None,\n", + " 'RADESYS': 'ICRS',\n", + " 'RA_OBJ': None,\n", + " 'DEC_OBJ': None,\n", + " 'EQUINOX': 2000.0,\n", + " 'PROCVER': '2.5.2dev',\n", + " 'MISSION': 'MY_FAKE_MISSION',\n", + " 'LABEL': None,\n", + " 'RA': None,\n", + " 'DEC': None,\n", + " 'FILENAME': './my_custom_lightcurve.fits',\n", + " 'FLUX_ORIGIN': 'lightkurve.LightCurve.to_fits()'}" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "read_lc.meta" + ] + }, + { + "cell_type": "markdown", + "id": "09d64fbd-c8e7-4ecc-8b66-bb8a7030ebc1", + "metadata": {}, + "source": [ + "We now know how to create a LightCurve Object, save it as a FITS file, and read in a FITS file as a LightCurve Object." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyproject.toml b/pyproject.toml index 4fff36a30..d1e62b8a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "lightkurve" -version = "2.5.2dev" +version = "2.6.1dev" description = "A friendly package for Kepler & TESS time series analysis in Python." license = "MIT" authors = ["Geert Barentsen ", "TESS Science Support Center "] @@ -36,7 +36,7 @@ beautifulsoup4 = ">=4.6.0" requests = ">=2.22.0" urllib3 = { version = ">=1.23", python = ">=3.8,<4.0" } # necessary to make requests work on py310 tqdm = ">=4.25.0" -pandas = ">=1.3.6" +pandas = ">=1.3.6, <3.0.0" uncertainties = ">=3.1.4" patsy = ">=0.5.0" fbpca = ">=1.0" @@ -81,6 +81,7 @@ mistune = "<2.0.0" # Workaround for #1162 (not a true dependency) # See https://github.com/python-poetry/poetry/issues/9293 docutils = "!=0.21" lxml-html-clean = "^0.4.2" +ipython = ">=7.0" [build-system] requires = ["poetry-core"] diff --git a/src/lightkurve/correctors/cbvcorrector.py b/src/lightkurve/correctors/cbvcorrector.py index 0e051f58b..9024b08e0 100644 --- a/src/lightkurve/correctors/cbvcorrector.py +++ b/src/lightkurve/correctors/cbvcorrector.py @@ -96,7 +96,7 @@ class CBVCorrector(RegressionCorrector): """ def __init__(self, lc, interpolate_cbvs=False, extrapolate_cbvs=False, do_not_load_cbvs=False, - cbv_dir=None): + cbv_dir=None, fast_cadence=False): """Constructor This constructor will retrieve all relevant CBVs from MAST and then @@ -120,6 +120,8 @@ def __init__(self, lc, interpolate_cbvs=False, extrapolate_cbvs=False, do_not_lo cbv_dir : str Path to specific directory holding TESS CBVs. If this is None, will query MAST by default. + fast_cadence : bool + If True, then the 20-s fast cadence CBV file will be loaded """ if not isinstance(lc, LightCurve): raise Exception(' must be a LightCurve class') @@ -129,6 +131,11 @@ def __init__(self, lc, interpolate_cbvs=False, extrapolate_cbvs=False, do_not_lo if extrapolate_cbvs and (extrapolate_cbvs != interpolate_cbvs): raise Exception('interpolate_cbvs must be True if extrapolate_cbvs is True') + + # Check if the lightkurve has 20-s cadence. + if hasattr(lc, 'filename'): + if 'fast' in lc.filename: + fast_cadence = True # We do not want any NaNs lc = lc.remove_nans() @@ -151,7 +158,7 @@ def __init__(self, lc, interpolate_cbvs=False, extrapolate_cbvs=False, do_not_lo # For TESS we load multiple CBV types # Single-Scale cbvs.append(load_tess_cbvs(cbv_dir=cbv_dir,sector=self.lc.sector, - camera=self.lc.camera, ccd=self.lc.ccd, cbv_type='SingleScale')) + camera=self.lc.camera, ccd=self.lc.ccd, cbv_type='SingleScale', fast_cadence=fast_cadence)) # Multi-Scale # Although there has always been 3 bands, there could be more, @@ -162,7 +169,7 @@ def __init__(self, lc, interpolate_cbvs=False, extrapolate_cbvs=False, do_not_lo iBand += 1 cbvObj = load_tess_cbvs(cbv_dir=cbv_dir,sector=self.lc.sector, camera=self.lc.camera, ccd=self.lc.ccd, cbv_type='MultiScale', - band=iBand) + band=iBand, fast_cadence=fast_cadence) if (cbvObj.band == iBand): cbvs.append(cbvObj) else: @@ -170,7 +177,7 @@ def __init__(self, lc, interpolate_cbvs=False, extrapolate_cbvs=False, do_not_lo # Spike cbvs.append(load_tess_cbvs(cbv_dir=cbv_dir,sector=self.lc.sector, - camera=self.lc.camera, ccd=self.lc.ccd, cbv_type='Spike')) + camera=self.lc.camera, ccd=self.lc.ccd, cbv_type='Spike', fast_cadence=fast_cadence)) else: raise ValueError('Unknown mission type') @@ -1837,7 +1844,7 @@ def download_tess_cbvs(*args, **kwargs): def load_tess_cbvs(cbv_dir=None,sector=None, camera=None, - ccd=None, cbv_type='SingleScale', band=None): + ccd=None, cbv_type='SingleScale', band=None, fast_cadence=False): """Loads TESS cotrending basis vectors, either from a directory of CBV files already saved locally if cbv_dir is passed, or else will retrieve the relevant files programmatically from MAST. @@ -1863,6 +1870,8 @@ def load_tess_cbvs(cbv_dir=None,sector=None, camera=None, 'SingleScale' or 'MultiScale' or 'Spike' band : int Multi-scale band number + fast_cadence : bool + 'True' to get 20-s cadence CBVs. If False, defaults to the 2-min CBV file. Returns ------- @@ -1934,7 +1943,10 @@ def load_tess_cbvs(cbv_dir=None,sector=None, camera=None, else: curlBaseUrl = 'https://archive.stsci.edu/missions/tess/download_scripts/sector/tesscurl_sector_' - curlEndUrl = '_cbv.sh' + if fast_cadence: + curlEndUrl = '_fast-cbv.sh' + else: + curlEndUrl = '_cbv.sh' curlUrl = curlBaseUrl + str(sector) + curlEndUrl # This is the string to search for in the curl script file diff --git a/src/lightkurve/io/generic.py b/src/lightkurve/io/generic.py index a0bcd5061..c41c674a7 100644 --- a/src/lightkurve/io/generic.py +++ b/src/lightkurve/io/generic.py @@ -99,12 +99,29 @@ def read_generic_lightcurve( log.debug("Ignoring {} rows with NaN times".format(np.sum(nans))) tab = tab[~nans] + # Set default reference time value to 0.0 + reference_time_value = 0.0 + # Prepare a special time column if not time_format: + # Check for the Kepler and TESS special cases if hdulist[ext].header.get("BJDREFI") == 2454833: # Kepler specific time_format = "bkjd" elif hdulist[ext].header.get("BJDREFI") == 2457000: # TESS specific time_format = "btjd" + # Work through options from the FITS Standard v4.0 Section 9.2.2 + elif ("MJDREFI" in hdulist[ext].header) and ("MJDREFF" in hdulist[ext].header): # Check if MJDREFI and MJDREFF set + time_format = "mjd" + reference_time_value = hdulist[ext].header.get("MJDREFI") + hdulist[ext].header.get("MJDREFF") + elif "MJDREF" in hdulist[ext].header: # Check if MJDREF set + time_format = "mjd" + reference_time_value = hdulist[ext].header.get("MJDREF") + elif ("JDREFI" in hdulist[ext].header) and ("JDREFF" in hdulist[ext].header): # Check if JDREFI and JDREFF set + time_format = "jd" + reference_time_value = hdulist[ext].header.get("JDREFI") + hdulist[ext].header.get("JDREFF") + elif "JDREF" in hdulist[ext].header: # Check if JDREF set + time_format = "jd" + reference_time_value = hdulist[ext].header.get("JDREF") # make compatible with normalized light curves without absolute start sime (see #1502) elif hdulist[ext].header.get("TIMESYS") == "local": try: @@ -115,14 +132,19 @@ def read_generic_lightcurve( tab.remove_column("time") except: raise KeyError(f"Unclear unit for local time system: TUNIT1 must be astropy.unit value.") # Error handling for invalid astropy.unit value or if the TUNIT1 keyword is missing from header - + # Check for nonstandard, format-flavored values of TIMESYS elif hdulist[ext].header.get("TIMESYS") == "mjd": time_format = 'mjd' elif hdulist[ext].header.get("TIMESYS") == "jd": time_format = 'jd' + # Raise error if reference time (or related variants) not found else: - raise ValueError(f"Input file has unclear time format: {filename}") + raise ValueError(f"No reference time found in {filename}. Pass in a common time_format manually, or edit the FITS header.") if 'time' not in locals(): + if (tab["time"].unit is not None) and (tab["time"].unit != u.d) and (type(tab["time"].unit) is not u.UnrecognizedUnit): + # If time column is in a recognized unit other than days... + tab["time"] = tab["time"].to(u.d, copy=False) # ...convert to days. + tab["time"] += reference_time_value # Add reference time to the time column values time = Time( tab["time"].data, scale=hdulist[ext].header.get("TIMESYS", "tdb").lower(), @@ -156,7 +178,15 @@ def read_generic_lightcurve( tab.meta["RA"] = hdulist[0].header.get("RA_OBJ") tab.meta["DEC"] = hdulist[0].header.get("DEC_OBJ") tab.meta["FILENAME"] = filename - tab.meta["FLUX_ORIGIN"] = flux_column + # issue 1371 - + # When reading in a file saved with to_fits, the flux source is not known + # We could save the flux_origin keyword, but that is an incomplete story, + # as we don't know if other manipulation (like detrending) also occurred + # So, we populate the 'FLUX_ORIGIN' meta data with 'to_fits' to contain that ambiguity + if ("CREATOR" in hdulist[0].header) and (hdulist[0].header["CREATOR"] == 'lightkurve.LightCurve.to_fits()'): + tab.meta["FLUX_ORIGIN"] = "lightkurve.LightCurve.to_fits()" + else: + tab.meta["FLUX_ORIGIN"] = flux_column return LightCurve(time=time, data=tab) finally: diff --git a/src/lightkurve/io/kepler.py b/src/lightkurve/io/kepler.py index 98b56fb37..2f162d387 100644 --- a/src/lightkurve/io/kepler.py +++ b/src/lightkurve/io/kepler.py @@ -4,6 +4,8 @@ from .generic import read_generic_lightcurve +import numpy as np + def read_kepler_lightcurve( filename, flux_column="pdcsap_flux", quality_bitmask="default" @@ -38,6 +40,11 @@ def read_kepler_lightcurve( time_format="bkjd", ) + #RAH - To allow generic lightcurves to be read by Kepler read we need to add this work around + if "sap_quality" not in lc.columns: + lc['sap_quality'] = np.zeros(len(lc['time']), dtype=int) + + # Filter out poor-quality data # NOTE: Unfortunately Astropy Table masking does not yet work for columns # that are Quantity objects, so for now we remove poor-quality data instead diff --git a/src/lightkurve/io/tess.py b/src/lightkurve/io/tess.py index 0f833f58d..1dbc95646 100644 --- a/src/lightkurve/io/tess.py +++ b/src/lightkurve/io/tess.py @@ -4,6 +4,8 @@ from .generic import read_generic_lightcurve +import numpy as np + def read_tess_lightcurve( filename, flux_column="pdcsap_flux", quality_bitmask="default", time_format="btjd", @@ -32,6 +34,10 @@ def read_tess_lightcurve( """ lc = read_generic_lightcurve(filename, flux_column=flux_column, time_format=time_format) + #RAH - To allow generic lightcurves to be read by TESS read we need to add this work around + if "quality" not in lc.columns: + lc['quality'] = np.zeros(len(lc['time']), dtype=int) + # Filter out poor-quality data # NOTE: Unfortunately Astropy Table masking does not yet work for columns # that are Quantity objects, so for now we remove poor-quality data instead diff --git a/src/lightkurve/lightcurve.py b/src/lightkurve/lightcurve.py index 5bcad1343..d7ea14c8a 100644 --- a/src/lightkurve/lightcurve.py +++ b/src/lightkurve/lightcurve.py @@ -275,9 +275,9 @@ class LightCurve(TimeSeries): Time values. They can either be given directly as a `~astropy.time.Time` array or as any iterable that initializes the `~astropy.time.Time` class. - flux : `~astropy.units.Quantity` or iterable + flux : `~astropy.units.Quantity`, `~astropy.units.masked.MaskedQuantity`, or iterable Flux values for every time point. - flux_err : `~astropy.units.Quantity` or iterable + flux_err : `~astropy.units.Quantity`, `~astropy.units.masked.MaskedQuantity`, or iterable Uncertainty on each flux data point. **kwargs : dict Additional keyword arguments are passed to `~astropy.table.QTable`. @@ -579,8 +579,14 @@ def time(self, time): self["time"] = time @property - def flux(self) -> Quantity: - """Brightness values stored as an AstroPy `~astropy.units.Quantity` object.""" + def flux(self): + """Brightness values stored as an AstroPy `~astropy.units.Quantity` object. + + Note: In special circumstances, this may be an `~astropy.units.masked.MaskedQuantity` + object. Masked values are treated by lightkurve as missing data. Masked + data may be accessed via self.flux.unmasked, which returns the unmasked + Quantity object. + """ return self["flux"] @flux.setter @@ -588,8 +594,15 @@ def flux(self, flux): self["flux"] = flux @property - def flux_err(self) -> Quantity: - """Brightness uncertainties stored as an AstroPy `~astropy.units.Quantity` object.""" + def flux_err(self): + """Brightness uncertainties stored as an AstroPy `~astropy.units.Quantity` object. + + + Note: In special circumstances, this may be an `~astropy.units.masked.MaskedQuantity` + object. Masked values are treated by lightkurve as missing data. Masked + data may be accessed via self.flux_err.unmasked, which returns the unmasked + Quantity object. + """ return self["flux_err"] @flux_err.setter @@ -1844,7 +1857,7 @@ def query_solar_system_objects( the solar system objects (name, brightness, time) that passed in the vicinity of the target during the span of the light curve. - This method queries the `SkyBot API `_, + This method queries the `SkyBot API `_, which returns a list of asteroids/comets/planets given a location, time, and search cone. @@ -2537,7 +2550,11 @@ def to_seismology(self, **kwargs): return Seismology.from_lightcurve(self, **kwargs) def to_fits( - self, path=None, overwrite=False, flux_column_name="FLUX", **extra_data + self, + path=None, + overwrite=False, + flux_column_name="FLUX", + **extra_data ): """Converts the light curve to a FITS file in the Kepler/TESS file format. @@ -2576,12 +2593,14 @@ def to_fits( np.float64: "D", } + # If users give a dictionary of values, we first need to "remove" the values from the dictionary if extra_data.get('extra_data') is not None: for k in extra_data.get('extra_data').keys(): extra_data[k] = extra_data['extra_data'][k] extra_data.pop('extra_data') + def _header_template(extension): """Returns a template `fits.Header` object for a given extension.""" template_fn = os.path.join( @@ -2639,7 +2658,7 @@ def _make_lightcurve_extension(extra_data=None): ) ) if ~np.asarray( - [flux_column_name in k.upper() for k in extra_data.keys()] + [flux_column_name.upper() == k.upper() for k in extra_data.keys()] ).any(): cols.append( fits.Column( @@ -2687,15 +2706,12 @@ def _make_lightcurve_extension(extra_data=None): array=extra_data[kw], ) ) - if "SAP_QUALITY" not in extra_data: - cols.append( - fits.Column( - name="SAP_QUALITY", format="J", array=np.zeros(len(self.flux)) - ) - ) + coldefs = fits.ColDefs(cols) hdu = fits.BinTableHDU.from_columns(coldefs) hdu.header["EXTNAME"] = "LIGHTCURVE" + + return hdu def _hdulist(**extra_data): @@ -3382,8 +3398,6 @@ def to_fits( self, path=None, overwrite=False, - flux_column_name="FLUX", - aperture_mask=None, **extra_data, ): """Writes the FoldedLightCurve to a FITS file. @@ -3394,13 +3408,6 @@ def to_fits( File path, if `None` returns an astropy.io.fits.HDUList object. overwrite : bool Whether or not to overwrite the file - flux_column_name : str - The name of the label for the FITS extension, e.g. SAP_FLUX or FLUX - aperture_mask : array-like - Optional 2D aperture mask to save with this lightcurve object, if - defined. The mask can be either a boolean mask or an integer mask - mimicking the Kepler/TESS convention; boolean masks are - automatically converted to the Kepler/TESS conventions extra_data : dict Extra keywords or columns to include in the FITS file. Arguments of type str, int, float, or bool will be stored as @@ -3629,13 +3636,16 @@ def read(cls, *args, **kwargs): # Default to Kepler file format if kwargs.get("format") is None: kwargs["format"] = "kepler" + + return super().read(*args, **kwargs) + + def to_fits( self, path=None, overwrite=False, - flux_column_name="FLUX", aperture_mask=None, **extra_data, ): @@ -3647,8 +3657,6 @@ def to_fits( File path, if `None` returns an astropy.io.fits.HDUList object. overwrite : bool Whether or not to overwrite the file - flux_column_name : str - The name of the label for the FITS extension, e.g. SAP_FLUX or FLUX aperture_mask : array-like Optional 2D aperture mask to save with this lightcurve object, if defined. The mask can be either a boolean mask or an integer mask @@ -3759,7 +3767,6 @@ def to_fits( self, path=None, overwrite=False, - flux_column_name="FLUX", aperture_mask=None, **extra_data, ): @@ -3771,8 +3778,6 @@ def to_fits( File path, if `None` returns an astropy.io.fits.HDUList object. overwrite : bool Whether or not to overwrite the file - flux_column_name : str - The name of the label for the FITS extension, e.g. SAP_FLUX or FLUX aperture_mask : array-like Optional 2D aperture mask to save with this lightcurve object, if defined. The mask can be either a boolean mask or an integer mask @@ -3790,6 +3795,7 @@ def to_fits( hdu : astropy.io.fits Returns an astropy.io.fits object if path is None """ + tess_specific_data = { "OBJECT": "{}".format(self.targetid), "MISSION": self.meta.get("MISSION"), @@ -3800,9 +3806,9 @@ def to_fits( "SECTOR": self.meta.get("SECTOR"), "TARGETID": self.meta.get("TARGETID"), "DEC_OBJ": self.meta.get("DEC"), + "SAP_QUALITY": self.quality, } - - + # Not every HLSP has centroid col/row information, so only pass this along if the data exists if hasattr(self, 'centroid_col'): diff --git a/src/lightkurve/periodogram.py b/src/lightkurve/periodogram.py index 1009c2348..28e2f56cf 100644 --- a/src/lightkurve/periodogram.py +++ b/src/lightkurve/periodogram.py @@ -844,6 +844,7 @@ def from_lightcurve( ) time = lc.time.copy() + flux = lc.flux.copy() # Approximate Nyquist Frequency and frequency bin width in terms of days nyquist = 0.5 * (1.0 / (np.median(np.diff(time.value)))) * (1 / cds.d) @@ -912,6 +913,22 @@ def from_lightcurve( # Convert to desired units frequency = u.Quantity(frequency, freq_unit) + # Slight tweaks to support nifty-ls implementation + if ls_method[:9] == 'fastnifty': # nifty-ls + try: + import nifty_ls + # If using nifty_ls, flux must be float64 + flux = flux.value.astype('float64')*flux.unit + except ImportError: + oldmethod = ls_method + ls_method = {"fastnifty": "fast", "fastnifty_chi2": "fastchi2"}[ls_method] + log.warning( + "nifty_ls is not available.\n" + "Method has been changed from '{}' to '{}'.".format( + oldmethod, ls_method + ) + ) + # Change to compatible ls method if sampling not even in frequency if not implementations.main._is_regular(frequency) and ls_method in [ "fastchi2", @@ -940,11 +957,11 @@ def from_lightcurve( if float(astropy.__version__[0]) >= 3: LS = LombScargle( - time, lc.flux, nterms=nterms, normalization="psd", **kwargs + time, flux, nterms=nterms, normalization="psd", **kwargs ) power = LS.power(frequency, method=ls_method) else: - LS = LombScargle(time, lc.flux, nterms=nterms, **kwargs) + LS = LombScargle(time, flux, nterms=nterms, **kwargs) power = LS.power(frequency, method=ls_method, normalization="psd") if normalization == "psd": # Power spectral density diff --git a/src/lightkurve/search.py b/src/lightkurve/search.py index ca08df963..658b90553 100644 --- a/src/lightkurve/search.py +++ b/src/lightkurve/search.py @@ -138,7 +138,12 @@ def _sort_table(self): self.table["sort_order"] = [ sort_priority.get(author, 9) for author in self.table["author"] ] - self.table.sort(["distance", "sort_order", "author", "year", "exptime", "mission",]) + + # Columns "year", "sequence_number", "mission" together maintain chronological sub-order. + # We need all three columns because: + # - year + mission would fail for TESS sectors 99 and 100 (both in yr 2026, 100 would be ahead) + # - year + sequence_number would fail for Kepler (which has no value for sequence_number) + self.table.sort(["distance", "sort_order", "author", "year", "sequence_number", "mission", "exptime"]) def _add_columns(self): @@ -948,7 +953,7 @@ def _search_products( ) target = str(target) # see: https://archive.stsci.edu/k2/manuals/KSCI-19082-021.pdf - elif (target > 200000000) and (target < 252090718): + elif (target > 200000000) and (target < 252090718): log.warning( "Warning: {} may refer to a different K2 or TESS target. " "Please add the prefix 'EPIC' or 'TIC' to disambiguate." @@ -962,7 +967,7 @@ def _search_products( "".format(target) ) return None - + # astroquery 0.4.11 update breaks if passing an integer, so convert to string else: target = f"TIC {target}" @@ -1009,7 +1014,8 @@ def _search_products( "".format(len(observations)) ) if len(observations) == 0: - raise SearchError('No data found for target "{}".'.format(target)) + log.debug('No data found for target "{}".'.format(target)) + return SearchResult(None) # Light curves and target pixel files if filetype.lower() != "ffi": @@ -1182,7 +1188,7 @@ def _query_mast( # Was a TESS target ID passed? tess_match = re.match(r"^(tess|tic) ?(\d+)$", target_lower) if tess_match: - exact_target_name = f"{tess_match.group(2).zfill(9)}" + exact_target_name = f"{tess_match.group(2)}" # for TESS, the id is not zero-padded in MAST if exact_target_name and radius is None: log.debug( diff --git a/src/lightkurve/targetpixelfile.py b/src/lightkurve/targetpixelfile.py index add4c17f7..7e2b2c848 100644 --- a/src/lightkurve/targetpixelfile.py +++ b/src/lightkurve/targetpixelfile.py @@ -955,7 +955,7 @@ def query_solar_system_objects( the solar system objects (name, brightness, time) that passed in the vicinity of the target during the span of the light curve. - This method queries the `SkyBot API `_, + This method queries the `SkyBot API `_, which returns a list of asteroids/comets/planets given a location, time, and search cone. diff --git a/src/lightkurve/utils.py b/src/lightkurve/utils.py index 037eb6c3a..9189da800 100644 --- a/src/lightkurve/utils.py +++ b/src/lightkurve/utils.py @@ -22,6 +22,7 @@ LinearStretch, ) from astropy.time import Time +import time log = logging.getLogger(__name__) @@ -731,18 +732,21 @@ def _query_solar_system_objects( ------- result : `pandas.DataFrame` DataFrame containing the list of known solar system objects at the - requested time and location. + requested time and location. Note a unique line in the table is created for + each timestamp in which an object is present. """ # We import pandas locally, because it takes quite a bit of time to import, # and it is only required for this specific feature. import pandas as pd + from pandas.errors import EmptyDataError + from urllib.error import HTTPError if (location.lower() == "kepler") or (location.lower() == "k2"): location = "C55" elif location.lower() == "tess": location = "C57" - url = "http://vo.imcce.fr/webservices/skybot/skybotconesearch_query.php?" + url = "https://ssp.imcce.fr/webservices/skybot/api/conesearch.php?" url += "-mime=text&" url += "-ra={}&".format(ra) url += "-dec={}&".format(dec) @@ -753,14 +757,24 @@ def _query_solar_system_objects( times = np.atleast_1d(times) for time in tqdm(times, desc="Querying for SSOs", disable=~show_progress): url_queried = url + "EPOCH={}".format(time) - response = download_file(url_queried, cache=cache, show_progress=show_progress) + for attempt in range(5): + try: + response = download_file(url_queried, cache=cache, show_progress=show_progress) + break + except HTTPError: + log.info(f"HTTP error (Attempt {attempt+1} of 5). Trying again...") + time.sleep(1) + if open(response).read(10) == "# Flag: -1": # error code detected? raise IOError( "SkyBot Solar System query failed.\n" "URL used:\n" + url_queried + "\n" "Response received:\n" + open(response).read() ) - res = pd.read_csv(response, delimiter="|", skiprows=2) + try: + res = pd.read_csv(response, delimiter="|", skiprows=2) + except EmptyDataError: + res = [] if len(res) > 0: res["epoch"] = time res.rename( diff --git a/src/lightkurve/version.py b/src/lightkurve/version.py index 54e189b12..8069e7c3a 100644 --- a/src/lightkurve/version.py +++ b/src/lightkurve/version.py @@ -1,3 +1,3 @@ # It is important to store the version number in a separate file # so that we can read it from setup.py without importing the package -__version__ = "2.5.2dev" +__version__ = "2.6.1dev" diff --git a/tests/data/test-sparcs-jdref.fits b/tests/data/test-sparcs-jdref.fits new file mode 100644 index 000000000..8591ae120 --- /dev/null +++ b/tests/data/test-sparcs-jdref.fits @@ -0,0 +1,230 @@ +SIMPLE = T / conforms to FITS standard BITPIX = -32 / array data type NAXIS = 2 / number of array dimensions NAXIS1 = 32 NAXIS2 = 32 EXTEND = T IMG_TYPE= 'Subraster' / image type BUNIT = 'electron/s' / brightness unit for array values X_REF = 511 / ROI center pixel coordinate in FFI (x-axis) Y_REF = 511 / ROI center pixel coordinate in FFI (y-axis) EXTNAME = 'PRIMARY ' / name of extension OBSERVAT= 'SPARCS ' / observatory name TELESCOP= 'SPARCS ' / telescope name OBSERVER= 'SPARCS ' / observer name INSTRUME= 'SPARCS Photometer' / instrument name CAMERA = 'SPARCam ' / camera name CCD = 'NUV ' / detector name DOI = 'doi:10.17909/fwhs-qk10' / digital object identifier for mission LICENSE = 'CC BY 4.0' / license LICENURL= 'https://creativecommons.org/licenses/by/4.0/' / license URL VER = 'DR0 ' / data release version CAL_VER = '0.0.0 ' / data processing pipeline version CAMP_ID = 3 / observing campaign number OBJECT = 'AD Leo ' / target name RA_TARG = 154.9011700755108 / [deg] right ascension coordinate of the target DEC_TARG= 19.87000290182528 / [deg] declination coordinate of the target OBS_MODE= 'Dynamic ' / observing mode SIMULATD= 1 / 0: Actual observations; 1: Simulated TIMESYS = 'TDB ' / time scale of time-related keywords TREFPOS = 'BARYCENTER' / time reference position CHANNEL = 'NUV ' / observing channel (NUV or FUV) FILTER = 'NUV ' / SPARCS filter (NUV or FUV) WAVEBAND= 'UV ' / waveband for MAST DB LAM-MIN = 'N/A ' / [nm] minimum wavelength LAM-MAX = 'N/A ' / [nm] maximum wavelength WCSAXES = 2 / Number of coordinate axes CRPIX1 = 16.5 / Pixel coordinate of reference point CRPIX2 = 16.5 / Pixel coordinate of reference point CDELT1 = 0.0013638888888889 / [deg] Coordinate increment at reference point CDELT2 = 0.0013638888888889 / [deg] Coordinate increment at reference point CUNIT1 = 'deg' / Units of coordinate increment and value CUNIT2 = 'deg' / Units of coordinate increment and value CTYPE1 = 'RA---TAN' / Right ascension, gnomonic projection CTYPE2 = 'DEC--TAN' / Declination, gnomonic projection CRVAL1 = 154.90117007551 / [deg] Coordinate value at reference point CRVAL2 = 19.870002901825 / [deg] Coordinate value at reference point LONPOLE = 180.0 / [deg] Native longitude of celestial pole LATPOLE = 19.870002901825 / [deg] Native latitude of celestial pole MJDREF = 0.0 / [d] MJD of fiducial time RADESYS = 'ICRS' / Equatorial coordinate system PC1_1 = 1.0 / linear transformation matrix element cos(rho) PC1_2 = 0.0 / linear transformation matrix element -sin(rho) PC2_1 = 0.0 / linear transformation matrix element sin(rho) PC2_2 = 1.0 / linear transformation matrix element cos(rho) TEMP_CCD= 0.0 / [degrees celsius] average detector temperature TEMP_NUV= 0.0 / [degrees celsius] average NUV detector temp TEMP_FUV= 0.0 / [degrees celsius] average FUV detector temp TEMP_TEL= 0.0 / [degrees celsius] average telescope temp TEMP_TEC= 0.0 / [degrees celsius] average TEC temp TEMP_OPT= 0.0 / [degrees celsius] average optical bench temp XPOSURE = 377192.8849489689 / [s] duration of exposure, excluding dead time EXPTIME = 90.0 / [s] duration of single exposure in stack TSTART = 2459526.520800724 / [JD] time at start of first exposure DATE-OBS= '2021-11-08T00:29:57.183' / ISO 8601 TDB at start of first exposure JD-OBS = 2459526.520800724 / Julian Date (JD) at start of first exposure MJD-BEG = 59526.02080072416 / [d] modified JD at start of first exposure MJD-MID = 59528.52183985477 / [d] modified JD at mid-sequence MJD-END = 59531.02287898539 / [d] modified JD at end of last exposure ANNEAL = '' / TDB date of latest on-orbit annealing SAT_MET = -1144.977121014614 / mission elapsed time [Days] SAT_STAT= 'OK ' / satellite position status BJD = 2459529.020767412 / barycentric Julian Date at mid-exposure DATE = '2024-10-30T17:20:06.798' / TDB of file creation CHECKSUM= 'ZDS3bCS2ZCS2bCS2' / HDU checksum updated 2026-01-23T13:59:22 DATASUM = '3141787759' / data unit checksum updated 2026-01-23T13:59:22 REDLEAK = 1 / red leak correction factor APTCORR = 1 / aperture correction factor ABSCAL = 2.19258146405945E-15 / [erg/cm^2/electron/A]flux density calib factor END A.clA-\A-A/,A.A-A.A-wqA-A/,A. A.A-/A.KA-HA-A. aA.IA. A.]A-AA.A.}FA.+"A-)A.CA.[A.)KA/A.,A-yA/A.?A.27A.BA-{A-$A.QA.A-"{A.eA-A-A- A.pA-m*A.A-A.~nA.8IA.A.?A.D.A.FA.UA.A-A.A.3A-AA.A-5A.A-qA-A-A-aA-7A.SA-A-;A-A.YA.?aA-sA.GA-A.vA/A.A-A-LA.;A-ۅA. !A.QA-MA-A.C:A.jA-GA-A-#A.izA-eA-zA-3A.CA. A.>VA.A-{A.?[A.A.XWA-HA,A._A-A.8'A-.A-TA.%2A-CA-ٔA.9A.{A.#A,jA-A-A-A.BA.WkA-KA.kA.A.A.A-sA.9&A.KA.A.` A.uA-A-ŃA-KA.A-A.5A. +A-A.A.;A->A-XA-A.A.KA-ъA-A-A.SNA-A-A.& +A.fA-A.A.bA.A.ilA-A--A.׌A.7A.KA- A-]A.%A.ZA-A-JA.YA-A.A-dA.YA.+A.`A.\A-c>A.~A.A. A-A-A-A.]}A-ְA.jA.A-A.TA.]sA-A-sA->A.9A-]A-A.A.!A.rA-5A.BA-A-A.~A-A.WLA-'A-A.{A-1A.UA.uA-#A.nA.WBA-yA-A.A.WdA-zWA.mA.Z2A. A-A.UA.|\A-A.GuA/ A/bA0tA0dA/>A-aA/8A-A/fA-A.yA."A.bA.4A-A-A.iA.$A-A.VA.rA-A-A-sA-A.#A--A.*A.A-^A-uA-EA0jA6;A:A9A5TA1A/!A.)A.1WA-A.@A,A--A-4A.dA-A.A-oA-mA-mOA.A.]A.rA.cA-KoA-A-A-,A-KdA- A.zA/ףA6AD|APDAOAA-A4A/bA.rA-_A-`A-,A.PA.A.A.A. A.DA-qA.eA-^A-GCA,ƽA-CA.A.,A.I]A.tCA-A.;A.A.9BA0pA:uAPpAd>Ac}AMA9A0XjA.`A/tA-A.!A.LA-kA.A-VA-iA-QA.A.HyA-A-AGA.NA.&A.A-ȿA.)PA.A-cA-A.A.=A1IA:AO&AcPAbANA9!A1IA/Y_A- A-uA.A.2#A.A-\mA.A.A.A-{A-A.XA.}A.A.~A-aA-A.aA-A-A.*BA.TrA.A.A.A.A-A-A-xA/lA-A-A-A.]A.ܓA.A.A.dA-A-dA-`A-A.#6A.}iA.@A-CA.TA-uA. A.^A-EA-A.4A-uxA-ґA.tA.A-8A,ZA.HvA-A.):A.AA.A-ޞA-A-#A-XA-A-$A.-A-A.nA.A-A.A-A-A-^A-KA.bA-A.]A.-A.A.uA.2jA-HA-xA-A.(oA-A.A-xA- A.A/yA-IA.A.UA.>A.ƶA.A.A-A.A.A>A-A-A- A.]{A.4A.eAA.$A-A.PA-A-A.1A.sA-A.=A.8A- +A.kA..A.A.ZA-A.oA-q(A.ntA. +A.bA.A-A-DsA.KVA.BA-A-FA.3A-]*A-M/A.A-ZA/C}A-$A-WjA-A.A.[fA.tA.CA-A.QA.~A-A.RA-A.;A.A-qA.v A.A.+FA-BA-A-A.CA.tiA.A.ZA.>bA-fA.oA.BA.;A-aA.JA-:A.5A.A.҂A-tA.;A.2A-OA-ćA.)`A.A. ?A.A-A-zA.^A-%A-blA.=A.rJA-A-$A-A-A-dA-G +A-aA-6A-|A.A-A-A-{A.A-SXTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / array data type NAXIS = 2 / number of array dimensions NAXIS1 = 86 / length of dimension 1 NAXIS2 = 4253 / length of dimension 2 PCOUNT = 0 / number of group parameters GCOUNT = 1 / number of groups TFIELDS = 21 / number of table fields TCTYP1 = 'TDB ' / time scale TRPOS1 = 'BARYCENTER' / time reference position TTYPE1 = 'TIME ' / column name: time (BJD) at mid-exposure TFORM1 = 'D ' / column format: 64-bit floating point TUNIT1 = 'd ' / column unit: day TTYPE2 = 'TIMECORR' / column name: barycentric correction TFORM2 = 'E ' / column format: 32-bit floating point TUNIT2 = 'd ' / column unit: day TTYPE3 = 'CTR ' / column name: source count rates TFORM3 = 'E ' / column format: 32-bit floating point TUNIT3 = 'electron/s' / column unit: electron/s TTYPE4 = 'CTR_ERR ' / column name: source count rate errors TFORM4 = 'E ' / column format: 32-bit floating point TUNIT4 = 'electron/s' / column unit: electron/s TTYPE5 = 'FLUX ' / column name: source flux density TFORM5 = 'E ' / column format: 32-bit floating point TUNIT5 = 'erg/s/cm^2/A' / column unit: erg/s/cm^2/A TTYPE6 = 'FLUX_ERR' / column name: source flux density error TFORM6 = 'E ' / column format: 32-bit floating point TUNIT6 = 'erg/s/cm^2/A' / column unit: erg/s/cm^2/A TTYPE7 = 'EXPTIME ' / column name: detector exposure time TFORM7 = 'E ' / column format: 32-bit floating point TUNIT7 = 's ' / column unit: second TTYPE8 = 'GAIN ' / column name: detector gain TFORM8 = 'E ' / column format: 32-bit floating point TUNIT8 = 'electron/adu' / column unit: electron/adu TTYPE9 = 'TEMP_CCD' / column name: detector temperature TFORM9 = 'E ' / column format: 32-bit floating point TUNIT9 = 'Celsius ' / column unit: degree celsius TTYPE10 = 'TEMP_TEL' / column name: telescope temperature TFORM10 = 'E ' / column format: 32-bit floating point TUNIT10 = 'Celsius ' / column unit: degree celsius TTYPE11 = 'TEMP_TEC' / column name: TEC temperature TFORM11 = 'E ' / column format: 32-bit floating point TUNIT11 = 'Celsius ' / column unit: degree celsius TTYPE12 = 'TEMP_OPT' / column name: optical bench temperature TFORM12 = 'E ' / column format: 32-bit floating point TUNIT12 = 'Celsius ' / column unit: degree celsius TTYPE13 = 'CENX_WCS' / column name: WCS-based source centroid (axis 1)TFORM13 = 'E ' / column format: 32-bit floating point TUNIT13 = 'pixel ' / column unit: pixel TTYPE14 = 'CENY_WCS' / column name: WCS-based source centroid (axis 2)TFORM14 = 'E ' / column format: 32-bit floating point TUNIT14 = 'pixel ' / column unit: pixel TTYPE15 = 'CENX ' / column name: source centroid along axis 1 TFORM15 = 'E ' / column format: 32-bit floating point TUNIT15 = 'pixel ' / column unit: pixel TTYPE16 = 'CENY ' / column name: source centroid along axis 2 TFORM16 = 'E ' / column format: 32-bit floating point TUNIT16 = 'pixel ' / column unit: pixel TTYPE17 = 'RA_AVG ' / column name: average RA during exposure TFORM17 = 'E ' / column format: 32-bit floating point TUNIT17 = 'deg ' / column unit: degree TTYPE18 = 'RA_SIG ' / column name: stdev RA during exposure TFORM18 = 'E ' / column format: 32-bit floating point TUNIT18 = 'deg ' / column unit: degree TTYPE19 = 'DEC_AVG ' / column name: average DEC during exposure TFORM19 = 'E ' / column format: 32-bit floating point TUNIT19 = 'deg ' / column unit: degree TTYPE20 = 'DEC_SIG ' / column name: stdev DEC during exposure TFORM20 = 'E ' / column format: 32-bit floating point TUNIT20 = 'deg ' / column unit: degree TTYPE21 = 'QUALITY ' / column name: quality flag TFORM21 = 'I ' / column format: 16-bit integer EXTNAME = 'LIGHT CURVES' / extension name REDLEAK = 1 / red leak correction factor APTCORR = 1 / aperture correction factor ABSCAL = 2.19258146405945E-15 / [erg/cm^2/electron/A]flux density calib factor TIMESYS = 'TDB ' / time scale of time-related keywords TREFPOS = 'BARYCENTER' / time reference position TIMEPIXR= 0.5 / bin time beginning=0 middle=0.5 end=1 JDREF = 2400000.5 / BJD reference offset CHECKSUM= 'Sr4iSo2fSo2fSo2f' / HDU checksum updated 2026-01-23T13:59:22 DATASUM = '3846380264' / data unit checksum updated 2026-01-23T13:59:22 END @@B@vKAA<@^:Aj@#) 'UB@vKAA'ɫ+B@vKAA@B@vKAA<@\9@B @#z)7'4B@vKAAB@vKAA'B@vKAAD@A~p@!K)XP'+B@vKAA)'=B@vKAAAt@c@B@vKAA<@'A@"?)j'CB@vKAA@AA@$6=)J'ʰ_B@vKAALV'B@vKAAM):['BZB@vKAAB@vKAAB@vKAAЀAF@")i'*B@vKAAAS @$){'wLB@vKAA)Z'dB@vKAA)*'~B@vKAAA@%r)z +'̓>B@vKAA@A{@%-)'0B@vKAAA90@$)'cB@vKAA)G0'§B@vKAA@A+}@$̰)V'jB@vKAAB@vKAA@vKAA@"x) 'MB@vKAAWB@vKAAGAw@LCA& +C+`c(A}@vKAA@3m@Cq[@Y+?(h{ B#)@vKAA|@87C,:;@*ԕ,(2uBN1@vKAAAv(@҈A@"|)$K'B@vKAA' 2B@vKAA}B@vKAA<@HB:@)A*"b'ТMB@vKAAB@vKAA'%kB@vKAA)r'ʺB@vKAA@ÌB +Fa@!,)'}B@vKAAkArK@ؿ@Au@%)Bo'B@vKAAQA<@#'),|'B@vKAAAq1@HAB@%j)T'- B@vKAAAq@vKAAi(36BK@vKAA^B@vKAA@oA@@$>)M5y'&B@vKAA?' +B@vKAA@Aʝ-@%E)z'B@vKAAI@7c*MT'[tB@vKAA@%"\)E'B@vKAA@BvA@&5*0''B@vKAA'^B@vKAA@"` +)*'kB@vKAAAvW@Aݯ@$)v'˘4B@vKAAAtF@{tB@vKAA<@,A@")mŕ'.B@vKAAB@vKAA<@H@B@vKAA<@R @A@X)zR'ĮB@vKAA'B@vKAA@sA@)/_n'&B@vKAAeAa@"B)z'H&B@vKAA}'B@vKAA@ +)o'ƞ]B@vKAA@)4'·B@vKAA@Af@"N)l'Ȫ +B@vKAAB@vKAA<@ܨv@AC4@%s)XT3'8 B@vKAAB@vKAA<@ Aʽ@%SB@vKAA<@G7B@vKAA<@R=oA@"()U`d''B@vKAA)\q'B@vKAA)'ŸB@vKAA{'nB@vKAA@A-@!`)r%>'B@vKAA @7I4*`';{B@vKAAB[5@+<*)m'\dB@vKAA@!)87I'ƟB@vKAAB@vKAAM)x 'BZB@vKAA>B@vKAA<@Ak@%c)j'$NB@vKAAV@$\)N'2 B@vKAAv'4B@vKAA)lW';B@vKAA.'|B@vKAA@Aݛ@! )@'ǢB@vKAAAS@ hB@vKAA<@Ax) @$)'b'!CB@vKAAA|O@,A@%O)g' B@vKAA@ B@vKAA<@,B@vKAA<@rA@$-)'VB@vKAA)u'§B@vKAA)='>B@vKAA@jH#A@%)EL'NB@vKAAAwn@*@ARW@##)'\PB@vKAAAwsD@B@vKAA<@1@Aʿ?@#)z@'TB@vKAAB@vKAA<@H?A@$)i@'oB@vKAA(hO3B(@UAAB@vKAA*@rEA@%])!'kB@vKAAZ)'2ZB@vKAAB@vKAA*Ak@%))'̭B@vKAAB@vKAA<@ +F6AR@$)$'JYB@vKAAA͒Q@$l)}a'ˆ"B@vKAAAu>@ BEH{A7X,(NAj@vKAA@#H?)'ɊB@vKAA2@#6G)O!'tpB@vKAAvB@vKAA<@Ao4@")<&',B@vKAA,A@".){H'/^B@vKAAb@_At@!q) 'EB@vKAA@B@vKAA<@V"@AK@"9^)'AvN@QݕA@"s)L'B@vKAA|A|@oB@vKAA<@&B@vKAA<@1YVB@vKAA<@:A +@ +)U['B@vKAAZ@#W)'ɝB@vKAAAw@MB@vKAA<@%B@vKAA<@/zTB@vKAA<@9茀B@vKAA<@CdB@vKAA<@LߒA.@#Ǧ)[E''B@vKAAB@vKAAA}!@rAf@$ +)HtL'zB@vKAAF)'BRB@vKAAAyT@"G7B@vKAA<@+ºA[+@#~)]a'B@vKAA'wB@vKAA/A(@"\)J'#B@vKAA@##+)2 J'\B@vKAA8A=e@#)r8'OB@vKAAA@#c3)W{'ɫB@vKAAA| @VB@vKAA<@`J@B@vKAA<@jx΀B@vKAA<@sRAg@")'ȽB@vKAAB5"$@vKAA)x'gB@vKAA'LB@vKAAB@e)'AB@vKAA)Q'B@vKAA.Ar7@pB@vKAA<@i@A@)'dB@vKAAB@vKAA@!"0B@vKAA<@!+A@$)L'ˠ>B@vKAAi'FB@vKAA)O'&B@vKAAB@vKAA}+'0( A@vKAA*!=( B ޳@vKAA'B@vKAAA}z@&j@A<@%7l)I|.'B@vKAA!B@-*%'^B@vKAAZB@vKAAAtx@)PAB$@)4'B@vKAA@*|B(@-* 'քB@vKAAt'ɑB@vKAAA|9@,=E;@A@#E6)h$+'ɆB@vKAA@#R)'ΘB@vKAA'QB@vKAA){^V'B@vKAA@.{@A +@!)E3z'B@vKAAB@vKAA<@/B@vKAA<@/(~@A6@!)|'B@vKAA"As@/tX=@B@vKAA<@.GB@vKAA<@/}Aa@%+\)}:'B@vKAAAR@"B)'ȲB@vKAAA @#6)J'B@vKAA@")q'șkB@vKAAB@vKAA@"ʤ)]>'B@vKAAen@B@vKAA<@3GA@%O)g' B@vKAA)L5T'ʺB@vKAAlB@vKAAAyu~@5;2@AO>@#P)-C'ɕKB@vKAA6@$ u)y'|B@vKAAAsi@5~1B@vKAA<@5@AV@$)h"r'˜B@vKAAAy@7rB@vKAA<@6NA}@#)r'B@vKAA^@7mA@%f#):=''zB@vKAAAe@!)>'B@vKAA"*e'_B@vKAAp@Aߊ!@$)'ˣTB@vKAAA|$@;A!@$5)'YoB@vKAAA$[@$)'ːB@vKAA'B@vKAA%''B@vKAA)&'Ǿ6B@vKAA'lB@vKAAAuj@=QyB@vKAA<@<JB@vKAA<@=Z%ACe@"%)z'$;B@vKAA<B@vKAA<@=D)@B^9@%L)-'̟gB@vKAA TBr@"3)?'5B@vKAAAľ@#d*)rء'ɭB@vKAA>B@vKAA<@>(B@vKAA<@>3(@A'@ m)y'ŗB@vKAA<A@%1)a'B@vKAA]@>FJAҳ@"O)7'B@vKAAwnOB@vKAA<@>ԀAE@%?)g&D'8B@vKAA@>X@A@")'ȵcB@vKAAPAO@"D)P'ȓB@vKAAӔB@vKAA<@>OA@#)1L 'XkB@vKAAT@Aը@%H)e'˭uB@vKAA8ـAh@$)sB'˜{B@vKAA^C@Fm#+>'B@vKAAûpC@jE+"(oBE@vKAAj@B*@҉*g(:)B>π@vKAAZ +B@ )Z'NB@vKAAHBi@!*V'[B@vKAAB-@$)F')B@vKAA?Bz@"6)'9MB@vKAA@AͅU@!~c)}['UyB@vKAA6@AXLa@!)}q'ljB@vKAA&A@)/,'78B@vKAAcA@#)Y'B@vKAAm@A@$@&)c'ʼB@vKAA@ANsB@vKAA<@AXBQ@%)b'̾B@vKAAPAU(@%)'B@vKAAAs=@B̘KB)I@!)ѕ'`B@vKAA=9'ǙbB@vKAAv\B@vKAA<@FHB*A+@^2)%'ĵB@vKAA@F,B @%i)b'+B@vKAA)v'%B@vKAA@Fo`A @%a)['̳AB@vKAAB@vKAA@AՐ@#[)wv'ɢyB@vKAA @H {j@B@vKAA<@H餀AB@#)-'=B@vKAA4)'/B@vKAAB@vKAA'rB@vKAAB@vKAA)?'WB@vKAA$@!)~w'ƟB@vKAASB@vKAAuA}@$)p'rB@vKAAA|<@NֲBm@%#*$'գB@vKAA)c'&B@vKAA)~Y'2B@vKAA)Gz|'aB@vKAA}B@vKAA<@QITB@vKAA<@QR9A@@"ʽ)JK'B@vKAA)'B@vKAA@R>A i@$)E'+nB@vKAA8'B@vKAA?'[B@vKAAB@vKAAP@EdB+- )A@vKAA@vKAA'z_B@vKAAAp@T3A@$u)7'NB@vKAAB@vKAA<@VB@vKAA<@VFB@vKAA<@V@A-@$)@'gB@vKAA'B@vKAAA@#=K){b'}B@vKAA{@CA#f*-(CAr@vKAA*7hU(Y4B @vKAA@)%(=B?0@vKAA@!)]r'ǝ8B@vKAA@%y)8'>B@vKAAB@vKAA<@]G~AѨ@"4)'5B@vKAAAД\@#B)'B@vKAAN@]d@Ac@!) 6'rB@vKAA@%)m'˿VB@vKAA"'ʈB@vKAA' +B@vKAAB@vKAAB?p@2)L 'vSB@vKAA@B@vKAA 0 + # Ensure the log lines are absent, indicating the fallback cone search is not kicked in. + # The log lines for fallback cone search: + # No observations found. Now performing a cone search instead. + # Started querying MAST for observations within 0.0001 arcsec arcsec of objectname='TIC 74534430'. + assert "Started querying MAST for observations within" not in caplog.text, "Fallback cone search should not be used." + + # Do a control: to ensure that the log line for fallback cone search does exist in the codes. + caplog.clear() + search_lightcurve(f"TIC 0") # a non-existent TIC, the fallback cone search should kick in + assert "Started querying MAST for observations within" in caplog.text, "Fallback cone search expected." + + @pytest.mark.remote_data def test_search_tesscut(): # Cutout by target name @@ -259,6 +279,33 @@ def test_searchresult(): assert "kplr" in sr._repr_html_() +@pytest.mark.remote_data +def test_searchresult_sort_order(): + # Ensure the boundary cases of TESS sectors 99, 100, etc. are sorted chronologically + # the condition: 1) the same year, and 2) has 2-digit sectors (99) and 3-digit sectors (100, 101, etc.) + # https://github.com/lightkurve/lightkurve/issues/1557 + + def to_mission_exptime(sr): + return [f'{r["mission"]} | {r["exptime"]:.0f}' for r in sr.table] + + # restrict TESS sectors to have predictable output + sr = lk.search_lightcurve("TIC15445551", mission="TESS", author="SPOC", sector=[37, 99, 100, 101]) + + expected = [ + "TESS Sector 37 | 20", + "TESS Sector 37 | 120", + "TESS Sector 99 | 20", + "TESS Sector 99 | 120", + "TESS Sector 100 | 20", + "TESS Sector 100 | 120", + "TESS Sector 101 | 20", + "TESS Sector 101 | 120", + ] + + actual = to_mission_exptime(sr) + assert_array_equal(actual, expected) + + @pytest.mark.remote_data def test_month(): # In short cadence, if we specify both quarter and month