{
  "id": 609445,
  "title": "10th Place Solution – Solverworld part",
  "url": "/competitions/ariel-data-challenge-2025/discussion/609445",
  "author_name": "SolverWorld",
  "post_date": "2025-09-26T17:24:30.951000",
  "votes": 8,
  "comment_count": 1,
  "views": 0,
  "content": "<p>This competition was a wonderful experience – I got to learn some astrophysics and be part of a great team.  Thanks to <a href=\"https://www.kaggle.com/gordonyip\" target=\"_blank\">@gordonyip</a> for hosting the competition and my teammates <a href=\"https://www.kaggle.com/veshkinartem\" target=\"_blank\">@veshkinartem</a>, <a href=\"https://www.kaggle.com/pizzaboi\" target=\"_blank\">@pizzaboi</a>, and <a href=\"https://www.kaggle.com/vitalykudelya\" target=\"_blank\">@vitalykudelya</a>. </p>\n<p>Our approach involved a mixing of 3 different separate solutions, our ensembling technique and the other solutions are described in other discussion posts.</p>\n<p>My solution did not involve deep learning or training, I started by trying to understand the physics behind the light curves and never moved beyond that!</p>\n<p><strong>References</strong></p>\n<ol>\n<li>“Analytic solutions to the maximum and average exoplanet<br>\ntransit depth for common stellar limb darkening laws” by René Heller, arXiv:1901.01730v2, 21 Mar 2019</li>\n<li>Analytic Lightcurves For Planetary Transit Searches, by Kaisey Mandel and Eric Algol, arXiv:astro-ph/0210099v1, 2 Oct 2002</li>\n<li>Transits and Occultations, Joshua Winn, arXiv:1001.2010v5, 24 Sept 2014</li>\n</ol>\n<p>From Heller:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F855ac6ce74e025138566aa2975fe0618%2FScreenshot%20from%202025-09-25%2015-50-45.png?generation=1758905618847486&amp;alt=media\" alt=\"From Heller\"></p>\n<p>Here are the ranges from the data we were given.  rprs2 is the ground truth and rprs is its sqrt().</p>\n<p>Ground truth </p>\n<table>\n<thead>\n<tr>\n<th>x</th>\n<th>rprs2</th>\n<th>rprs</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>count</td>\n<td>311300</td>\n<td>311300</td>\n</tr>\n<tr>\n<td>mean</td>\n<td>0.014689</td>\n<td>0.115116</td>\n</tr>\n<tr>\n<td>std</td>\n<td>0.010661</td>\n<td>0.037912</td>\n</tr>\n<tr>\n<td>min</td>\n<td>0.003654</td>\n<td>0.060451</td>\n</tr>\n<tr>\n<td>max</td>\n<td>0.088650</td>\n<td>0.297742</td>\n</tr>\n</tbody>\n</table>\n<h1>The Physics</h1>\n<p>To help visualize the exoplanet detection and analysis problem, imagine a star as a circle of a certain brightness.  As an exoplanet crosses (transits) in front of the star, it will block some of the light coming from that star.  Since the star and the planet subtend an arc much smaller than the resolution of our imaging systems, we only can see this by measuring the dip in the total light reaching our instrument.</p>\n<p>There are some simplifying assumptions and some complicating factors involved with this model.  Since the organizers specifically called out ExoSim2 as the simulation model for the data provided, they forced some of these.<br>\n    1. The star is not actually uniformly bright when viewed from a distance. Because of different temperatures throughout the depth of the star and the different transmission/absorption at different depths, the star when viewed as a disk is not uniformly bright.  This effect is called limb-darkening.<br>\n    2. The ExoSim2 simulation assumes that the planet acts as black disk of a given radius.  An input file provides the assumed area of the planet disk per wavelength, which alters the star’s output spectrum differently at each wavelength – effectively, the planet has a different apparent size at each wavelength.  This would be the values in the EXOSIM2 planetary radius file:&nbsp;load_rp.  Note that this does not take into account any variation caused by the atmosphere of the planets causing the edge of the viewed planet to behave differently than the center.<br>\n    3. An exoplanet does not cross directly through the center of the star.  The offset is described by the impact parameter, which is p=sma*cos(i) in the contest terminology, where sma = radius of the planet’s orbit and i is the angle between orbit (perpendicular) axis and the path from the star to the viewer.  When sma is expressed in units of stellar radius, then p=0 means the planet passes through the center of the star, and p=1.0 mean the center of the planet just kisses the edge of the star.<br>\n    4. The data is quite noisy<br>\n    5. Sensors drift over time</p>\n<p>In what follows, rprs will mean Rp/Rs, the planet size in stellar radius units, and rprs2 will be the rprs^2, the ratio of the area of the planet to the area of the star.  </p>\n<p>The reason that it is difficult to determine the “true” rprs is that it from the Fig 1 above, the (Rp/Rs)^2 is not the maximum depth of the transit curve.  This has to do with limb-darkening.  Imagine a planet crossing just near the edge of a star with significant limb-darkening – the total light reaching a viewer will not decrease the same percentage even when the planet is fully inside the star envelope as it would if the planet were to pass near the (bright) center of the star.  In the absence of limb-darkening, rprs^2 is equal to delta - this was the case in the Ariel 2024 competition.</p>\n<p>Here are some illustrations of transits.  In the transit curves, the vertical red lines are where the planet center crosses the  star edge (roughly the middle of the ingress/outgress portion), and the horizontal dotted green line is the true rprs^2.  You can see that sometimes the true (Rp/Rs)^2 is above the maximum delta (for p=.1) but sometimes it is below the maximum delta (p=.8 or .9).  Hence the difficulty in predicting (Rp/Rs)^2.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F4a26b2c0bd07ee1213cfa281b58c2e66%2Fcurve_r0.06.png?generation=1758906134657482&amp;alt=media\" alt=\"planet transiting .06\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1265417bc258daed7d63e01027cc9bec%2Fcurve_r0.11.png?generation=1758906177953397&amp;alt=media\" alt=\"planet transiting .11\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F3a9715e8cb7d547a9955dc22c557f46c%2Ftransit_p0.1_r0.11.png?generation=1758906218072848&amp;alt=media\" alt=\"curve =.11\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2Fd971e58c9b207f4a415b0e1a1c0e90ec%2Ftransit_p0.9_r0.3.png?generation=1758906271176672&amp;alt=media\" alt=\"curve .3\"></p>\n<h1>Preprocessing</h1>\n<p>I used the organizer provided code with everything enabled.  For AIRS sensors, I summed positions [8:24] and ignored the other positions<br>\nFor FGS, I summed all 32x32 positions at each time step.  Time binning was at 5 original time steps for both.</p>\n<h1>Lightcurve</h1>\n<p>Using the mean of the AIRS data over all wavelengths “lightcurve” (first normalize by the mean level at each wavelength to account for a non-uniform star spectrum), I calculate some values.<br>\nI compute two initial points for the ingress/outgress points using the pretty standard gradient maximizing technique.  Smooth the data, take a gradient and look for a min (p1) and a max (p2) and hope that p1&lt;p2.</p>\n<p>Then, taking a hint from <a href=\"https://www.kaggle.com/egorgi21\" target=\"_blank\">@egorgi21</a> from the 2024 competition, I assume a form of the lightcurve with some parameters, and then use Nelder-Mead optimization to find the parameters that best fit the data on a least-squares basis.  I even used his function name: “secret”, although I used a different function.</p>\n<p>There are 2 types of secret function:</p>\n<p><strong>Type 1</strong>  My initial function was of the form:  Linear ingress-outgress regions, centered on p1,p2 of width t, and inside the transit region, I assumed that the star intensity depression followed a quadratic formula:<br>\nIntensity = delta<em>I(a,b,r) where I(a,b) = (1 – a(1-mu(r)) – b</em>(1-mu(r))^2), <br>\nwhere a,b are 2 parameters, mu(r)=sqrt(1-r^2), and r is a variable that represents the distance from the star center to the planet center.  Thus is goes from 1 at initial star edge crossing to sqrt(1-p_impact^2) at the center of the crossing.  This formula is a standard one from the references.  This secret function has some problems: (1) it assumes a straight line for ingress/outgress, which is wrong (see above curves), and it fudges a bit at the quadratic formula region.<br>\nThe other problem is the sensor drift.  I assumed that the sensor gain followed at 4th order polynomial gain in time.  A good calculation for the assumed limb-darkening is <br>\nRp/Rs)^2 = delta*(1-a/3-b/6) / I(a,b,p_impact)<br>\nand this done as a correction.  Of course, because the provided p_impact is not accurate, this causes errors in prediction, even with everything else correct.</p>\n<p>Here are what some fits look like.  The left curve is the AIRS lightcurve, the right is FGS.  Why the impact parameter for FGS should be different than AIRS, I have not been able to figure out.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F93f497a1776688da0f8b96cc4eca554c%2Fplt_1029552010_0_cie-1.png?generation=1758906904631821&amp;alt=media\" alt=\"\"><br>\nI use the p1,p2 from the initial fitting as the starting point for the optimization, which yields the best choices for p1,p2,t,a,b,delta, and drift polynomial coefficients.  </p>\n<p><strong>Type 2</strong>  There are some transits with high impact parameters where the above curve does not fit well.  The curves do not have well-defined ingress and outgress regions.  For these, I simply fit the transit depth curve by a polynomial of the form  S = a|x|^2 + b|x|^3 + c|x|^4 + q|x|^5, where the q is constrained so that the curve hits 1 at x=1.   Thus the transit function looks like 1 - delta*(1-S) and we can proceed as in Type 1.  The variable x goes from -1 to 1 over the transit region.  There is no x^1 term because we want a smooth bottom center, and the |x| guarantees a symmetric transit.  Even though this curve can fit reasonably well, there is no good way to predict (Rp/Rs)^2 from delta.<br>\nHere is an example where the Type 1 is worse than Type 2 fitting (sec1 vs sec2 in the caption).</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1d957035dfc94c1f6779663fef9a1937%2Fplt_131083252_0_avr-1.png?generation=1758907292755262&amp;alt=media\" alt=\"Type 1\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F11e5dd7aaa99349f50d3b522d7c1b2a6%2Fplt_131083252_0_avr-2.png?generation=1758907333915880&amp;alt=media\" alt=\"Type 2\"><br>\nI fit both curves and pick the one  that has lowest rmse fitting error.</p>\n<h1>FGS</h1>\n<p>I use the same technique to determine the optimal parameters for the FGS data, using as a starting point the parameters found for the AIRS lightcurve.</p>\n<h1>AIRS Wavelengths</h1>\n<p>The optimization routine is too slow to perform for each wavelength (282 per sample), so I borrowed another technique someone used last year:<br>\nI assume that the parameters p1,p2,t,a,b are the same for each wavelength and just want to compute a new delta.  By manipulating the equations correctly, you can write an equation that looks like (playing fast and loose with notation):<br>\nSince (1-delta<em>I(a,b))</em>poly = signal  (approx), then</p>\n<p>(poly-signal)/signal = delta * I(a,b)</p>\n<p>Which looks like a least-squares problem which can be solved directly by linear algebra, and in one big calculations for all wavelengths at once.<br>\nFor the matrix equation y=delta<em>x has least squares solution delta = (y</em>x).sum(axis=0)/(x*x).sum(axis=0)</p>\n<h1>NMF Smoothing</h1>\n<p>I used Nonnegative-Matrix Factorization to smooth the wavelength data<br>\nThis was done by taking the ground truth data provided and decomposing into the best 5 spectrums (determined through testing to be the best number), then reconstructing the data for each planet using those wavelengths.  In the 2024 competition, there was a confounding problem of gases being introduced in testing that were not in training, which was a problem.  But I couldn’t find a better technique, such as using smoothing over windows, or using an NMF decomposition of the actual resulting values during testing.</p>\n<h1>Predict RpRs^2</h1>\n<p>Because now I have predictions for the delta values, I need to convert those to RpRs predictions, which are different in the presence of limb-darkening.<br>\nI used a linear regression fit, over 3 buckets; (1) type=2 fitting, (2) high impact parameter, (3) everything else.  Buckets are m0,m1,m2 and used these features per planet, along with the wavelength dependent delta computed previously.:<br>\n    all_buckets[typ] = [ [m0, ['p_impact','gamma', 't','t2','a','b','a2','b2','delta','airs_delta']],<br>\n                         [m1,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],<br>\n                         [m2,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],</p>\n<p>Because some planets have 2 observations, I used weights of 0.5 on those, with weights of 1.0 otherwise.</p>\n<h1>Aggregate</h1>\n<p>I took the mean of the predictions for planets with 2 readings</p>\n<h1>Wavelength adjustment</h1>\n<p>Since the above linear fit does not take into account any differences in wavelength, a wavelength adjustment was performed:<br>\nThe adjustment for each wavelength is the mean (ground/predicted) value over the train set.</p>\n<h1>Predict Sigma</h1>\n<p>Because the competition metric is involves a sum over wavelengths, you can separately optimize for the sigma for FGS sensor (wavelength 0) and the AIRS sensors.</p>\n<p>Although the competition metric roughly expects the sigma to be the std deviation of the errors in your delta predictions, some simple Monte Carlo experiments show that it is not exactly correct.  Thus I do another Nelder-Mead search for the parameters that give the best score as followes.</p>\n<h1>Sigma0:</h1>\n<p>For the FGS sigma prediction I used:<br>\n<code>sigma0 = k0/1e4*dd + k1/1e4*dd*p_impact + k2*dd*noise1 + k3/1e3*p_impact</code></p>\n<p>where k0 to p.k3 are the learned parameters, and:<br>\ndd = 3.5  if the left or right margin is less than 80 time steps<br>\ndd = 6.5 if the left or right margin is less than 30 time steps<br>\ndd =1 otherwise<br>\nnoise1 = the standard deviation of the error in the transit curve fitting<br>\np_impact = impact parameter as calculated by the values provided in star_info.csv file.</p>\n<h1>Sigma</h1>\n<p>After computing the best sigm0 above, I searched for the best sigma predictions using <br>\nPer planet:<br>\n<code>sigma = [k0 + k1*dd*noise1 + k2*p_impact + k3*noise1**1.3]*[wts1**1.13]</code><br>\nwhere the first bracket is per planet and the second is per wavelength.<br>\nwts1=standard deviation of the errors in prediction shape=[planets, wavelengths] normalized to mean of 1.</p>\n<h1>Things I Tried:</h1>\n<pre><code>) Using a more accurate transit function.  From  Mandel  Algol paper,  exact transit function can be computed, assuming a quadratic  even th order limb-darkening law.  The problem  there was  enough  (both wall   understand  calculations  processor   compute  elliptic functions, etc.).  So I tried a simple graphical model  a circles drawn  a grid  simply summing  light intensity  pixels.  This model works well  can provide any desired level  accuracy  using more pixels.  The problem     quite slow.  After using a few tricks, I was able  speed  up x, which     realm  possible solutions,  contest  was  out.  I believe this method will eventually work,  can give surprisingly good estimation results  even fairly high impact parameters.  Note  this method uses information  I was  able  capture   simpler models, namely   taken   ingress  outgress curves – this  important information   planet size.\n) Using a bootstrap approach  determining sigmas.  People did this  ,  I was  able   useful results  \n) Non-rmse predictions.  Too late   competition I realized ( rather, @vitaly demonstrated)  minimizing  RMSE value  predictions      best score.  I was able demonstrate  a  better score  optimizing directly  score,  there was  enough   implement .\n) Better outlier removal  correction.  There are various spikes   raw instrument readings  a better algorithm here would probably be helpful.\n</code></pre>",
  "messages": [
    {
      "id": 3294775,
      "postDate": "2025-09-26T17:24:30.950Z",
      "content": "<p>This competition was a wonderful experience – I got to learn some astrophysics and be part of a great team.  Thanks to <a href=\"https://www.kaggle.com/gordonyip\" target=\"_blank\">@gordonyip</a> for hosting the competition and my teammates <a href=\"https://www.kaggle.com/veshkinartem\" target=\"_blank\">@veshkinartem</a>, <a href=\"https://www.kaggle.com/pizzaboi\" target=\"_blank\">@pizzaboi</a>, and <a href=\"https://www.kaggle.com/vitalykudelya\" target=\"_blank\">@vitalykudelya</a>. </p>\n<p>Our approach involved a mixing of 3 different separate solutions, our ensembling technique and the other solutions are described in other discussion posts.</p>\n<p>My solution did not involve deep learning or training, I started by trying to understand the physics behind the light curves and never moved beyond that!</p>\n<p><strong>References</strong></p>\n<ol>\n<li>“Analytic solutions to the maximum and average exoplanet<br>\ntransit depth for common stellar limb darkening laws” by René Heller, arXiv:1901.01730v2, 21 Mar 2019</li>\n<li>Analytic Lightcurves For Planetary Transit Searches, by Kaisey Mandel and Eric Algol, arXiv:astro-ph/0210099v1, 2 Oct 2002</li>\n<li>Transits and Occultations, Joshua Winn, arXiv:1001.2010v5, 24 Sept 2014</li>\n</ol>\n<p>From Heller:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F855ac6ce74e025138566aa2975fe0618%2FScreenshot%20from%202025-09-25%2015-50-45.png?generation=1758905618847486&amp;alt=media\" alt=\"From Heller\"></p>\n<p>Here are the ranges from the data we were given.  rprs2 is the ground truth and rprs is its sqrt().</p>\n<p>Ground truth </p>\n<table>\n<thead>\n<tr>\n<th>x</th>\n<th>rprs2</th>\n<th>rprs</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>count</td>\n<td>311300</td>\n<td>311300</td>\n</tr>\n<tr>\n<td>mean</td>\n<td>0.014689</td>\n<td>0.115116</td>\n</tr>\n<tr>\n<td>std</td>\n<td>0.010661</td>\n<td>0.037912</td>\n</tr>\n<tr>\n<td>min</td>\n<td>0.003654</td>\n<td>0.060451</td>\n</tr>\n<tr>\n<td>max</td>\n<td>0.088650</td>\n<td>0.297742</td>\n</tr>\n</tbody>\n</table>\n<h1>The Physics</h1>\n<p>To help visualize the exoplanet detection and analysis problem, imagine a star as a circle of a certain brightness.  As an exoplanet crosses (transits) in front of the star, it will block some of the light coming from that star.  Since the star and the planet subtend an arc much smaller than the resolution of our imaging systems, we only can see this by measuring the dip in the total light reaching our instrument.</p>\n<p>There are some simplifying assumptions and some complicating factors involved with this model.  Since the organizers specifically called out ExoSim2 as the simulation model for the data provided, they forced some of these.<br>\n    1. The star is not actually uniformly bright when viewed from a distance. Because of different temperatures throughout the depth of the star and the different transmission/absorption at different depths, the star when viewed as a disk is not uniformly bright.  This effect is called limb-darkening.<br>\n    2. The ExoSim2 simulation assumes that the planet acts as black disk of a given radius.  An input file provides the assumed area of the planet disk per wavelength, which alters the star’s output spectrum differently at each wavelength – effectively, the planet has a different apparent size at each wavelength.  This would be the values in the EXOSIM2 planetary radius file:&nbsp;load_rp.  Note that this does not take into account any variation caused by the atmosphere of the planets causing the edge of the viewed planet to behave differently than the center.<br>\n    3. An exoplanet does not cross directly through the center of the star.  The offset is described by the impact parameter, which is p=sma*cos(i) in the contest terminology, where sma = radius of the planet’s orbit and i is the angle between orbit (perpendicular) axis and the path from the star to the viewer.  When sma is expressed in units of stellar radius, then p=0 means the planet passes through the center of the star, and p=1.0 mean the center of the planet just kisses the edge of the star.<br>\n    4. The data is quite noisy<br>\n    5. Sensors drift over time</p>\n<p>In what follows, rprs will mean Rp/Rs, the planet size in stellar radius units, and rprs2 will be the rprs^2, the ratio of the area of the planet to the area of the star.  </p>\n<p>The reason that it is difficult to determine the “true” rprs is that it from the Fig 1 above, the (Rp/Rs)^2 is not the maximum depth of the transit curve.  This has to do with limb-darkening.  Imagine a planet crossing just near the edge of a star with significant limb-darkening – the total light reaching a viewer will not decrease the same percentage even when the planet is fully inside the star envelope as it would if the planet were to pass near the (bright) center of the star.  In the absence of limb-darkening, rprs^2 is equal to delta - this was the case in the Ariel 2024 competition.</p>\n<p>Here are some illustrations of transits.  In the transit curves, the vertical red lines are where the planet center crosses the  star edge (roughly the middle of the ingress/outgress portion), and the horizontal dotted green line is the true rprs^2.  You can see that sometimes the true (Rp/Rs)^2 is above the maximum delta (for p=.1) but sometimes it is below the maximum delta (p=.8 or .9).  Hence the difficulty in predicting (Rp/Rs)^2.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F4a26b2c0bd07ee1213cfa281b58c2e66%2Fcurve_r0.06.png?generation=1758906134657482&amp;alt=media\" alt=\"planet transiting .06\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1265417bc258daed7d63e01027cc9bec%2Fcurve_r0.11.png?generation=1758906177953397&amp;alt=media\" alt=\"planet transiting .11\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F3a9715e8cb7d547a9955dc22c557f46c%2Ftransit_p0.1_r0.11.png?generation=1758906218072848&amp;alt=media\" alt=\"curve =.11\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2Fd971e58c9b207f4a415b0e1a1c0e90ec%2Ftransit_p0.9_r0.3.png?generation=1758906271176672&amp;alt=media\" alt=\"curve .3\"></p>\n<h1>Preprocessing</h1>\n<p>I used the organizer provided code with everything enabled.  For AIRS sensors, I summed positions [8:24] and ignored the other positions<br>\nFor FGS, I summed all 32x32 positions at each time step.  Time binning was at 5 original time steps for both.</p>\n<h1>Lightcurve</h1>\n<p>Using the mean of the AIRS data over all wavelengths “lightcurve” (first normalize by the mean level at each wavelength to account for a non-uniform star spectrum), I calculate some values.<br>\nI compute two initial points for the ingress/outgress points using the pretty standard gradient maximizing technique.  Smooth the data, take a gradient and look for a min (p1) and a max (p2) and hope that p1&lt;p2.</p>\n<p>Then, taking a hint from <a href=\"https://www.kaggle.com/egorgi21\" target=\"_blank\">@egorgi21</a> from the 2024 competition, I assume a form of the lightcurve with some parameters, and then use Nelder-Mead optimization to find the parameters that best fit the data on a least-squares basis.  I even used his function name: “secret”, although I used a different function.</p>\n<p>There are 2 types of secret function:</p>\n<p><strong>Type 1</strong>  My initial function was of the form:  Linear ingress-outgress regions, centered on p1,p2 of width t, and inside the transit region, I assumed that the star intensity depression followed a quadratic formula:<br>\nIntensity = delta<em>I(a,b,r) where I(a,b) = (1 – a(1-mu(r)) – b</em>(1-mu(r))^2), <br>\nwhere a,b are 2 parameters, mu(r)=sqrt(1-r^2), and r is a variable that represents the distance from the star center to the planet center.  Thus is goes from 1 at initial star edge crossing to sqrt(1-p_impact^2) at the center of the crossing.  This formula is a standard one from the references.  This secret function has some problems: (1) it assumes a straight line for ingress/outgress, which is wrong (see above curves), and it fudges a bit at the quadratic formula region.<br>\nThe other problem is the sensor drift.  I assumed that the sensor gain followed at 4th order polynomial gain in time.  A good calculation for the assumed limb-darkening is <br>\nRp/Rs)^2 = delta*(1-a/3-b/6) / I(a,b,p_impact)<br>\nand this done as a correction.  Of course, because the provided p_impact is not accurate, this causes errors in prediction, even with everything else correct.</p>\n<p>Here are what some fits look like.  The left curve is the AIRS lightcurve, the right is FGS.  Why the impact parameter for FGS should be different than AIRS, I have not been able to figure out.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F93f497a1776688da0f8b96cc4eca554c%2Fplt_1029552010_0_cie-1.png?generation=1758906904631821&amp;alt=media\" alt=\"\"><br>\nI use the p1,p2 from the initial fitting as the starting point for the optimization, which yields the best choices for p1,p2,t,a,b,delta, and drift polynomial coefficients.  </p>\n<p><strong>Type 2</strong>  There are some transits with high impact parameters where the above curve does not fit well.  The curves do not have well-defined ingress and outgress regions.  For these, I simply fit the transit depth curve by a polynomial of the form  S = a|x|^2 + b|x|^3 + c|x|^4 + q|x|^5, where the q is constrained so that the curve hits 1 at x=1.   Thus the transit function looks like 1 - delta*(1-S) and we can proceed as in Type 1.  The variable x goes from -1 to 1 over the transit region.  There is no x^1 term because we want a smooth bottom center, and the |x| guarantees a symmetric transit.  Even though this curve can fit reasonably well, there is no good way to predict (Rp/Rs)^2 from delta.<br>\nHere is an example where the Type 1 is worse than Type 2 fitting (sec1 vs sec2 in the caption).</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1d957035dfc94c1f6779663fef9a1937%2Fplt_131083252_0_avr-1.png?generation=1758907292755262&amp;alt=media\" alt=\"Type 1\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F11e5dd7aaa99349f50d3b522d7c1b2a6%2Fplt_131083252_0_avr-2.png?generation=1758907333915880&amp;alt=media\" alt=\"Type 2\"><br>\nI fit both curves and pick the one  that has lowest rmse fitting error.</p>\n<h1>FGS</h1>\n<p>I use the same technique to determine the optimal parameters for the FGS data, using as a starting point the parameters found for the AIRS lightcurve.</p>\n<h1>AIRS Wavelengths</h1>\n<p>The optimization routine is too slow to perform for each wavelength (282 per sample), so I borrowed another technique someone used last year:<br>\nI assume that the parameters p1,p2,t,a,b are the same for each wavelength and just want to compute a new delta.  By manipulating the equations correctly, you can write an equation that looks like (playing fast and loose with notation):<br>\nSince (1-delta<em>I(a,b))</em>poly = signal  (approx), then</p>\n<p>(poly-signal)/signal = delta * I(a,b)</p>\n<p>Which looks like a least-squares problem which can be solved directly by linear algebra, and in one big calculations for all wavelengths at once.<br>\nFor the matrix equation y=delta<em>x has least squares solution delta = (y</em>x).sum(axis=0)/(x*x).sum(axis=0)</p>\n<h1>NMF Smoothing</h1>\n<p>I used Nonnegative-Matrix Factorization to smooth the wavelength data<br>\nThis was done by taking the ground truth data provided and decomposing into the best 5 spectrums (determined through testing to be the best number), then reconstructing the data for each planet using those wavelengths.  In the 2024 competition, there was a confounding problem of gases being introduced in testing that were not in training, which was a problem.  But I couldn’t find a better technique, such as using smoothing over windows, or using an NMF decomposition of the actual resulting values during testing.</p>\n<h1>Predict RpRs^2</h1>\n<p>Because now I have predictions for the delta values, I need to convert those to RpRs predictions, which are different in the presence of limb-darkening.<br>\nI used a linear regression fit, over 3 buckets; (1) type=2 fitting, (2) high impact parameter, (3) everything else.  Buckets are m0,m1,m2 and used these features per planet, along with the wavelength dependent delta computed previously.:<br>\n    all_buckets[typ] = [ [m0, ['p_impact','gamma', 't','t2','a','b','a2','b2','delta','airs_delta']],<br>\n                         [m1,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],<br>\n                         [m2,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],</p>\n<p>Because some planets have 2 observations, I used weights of 0.5 on those, with weights of 1.0 otherwise.</p>\n<h1>Aggregate</h1>\n<p>I took the mean of the predictions for planets with 2 readings</p>\n<h1>Wavelength adjustment</h1>\n<p>Since the above linear fit does not take into account any differences in wavelength, a wavelength adjustment was performed:<br>\nThe adjustment for each wavelength is the mean (ground/predicted) value over the train set.</p>\n<h1>Predict Sigma</h1>\n<p>Because the competition metric is involves a sum over wavelengths, you can separately optimize for the sigma for FGS sensor (wavelength 0) and the AIRS sensors.</p>\n<p>Although the competition metric roughly expects the sigma to be the std deviation of the errors in your delta predictions, some simple Monte Carlo experiments show that it is not exactly correct.  Thus I do another Nelder-Mead search for the parameters that give the best score as followes.</p>\n<h1>Sigma0:</h1>\n<p>For the FGS sigma prediction I used:<br>\n<code>sigma0 = k0/1e4*dd + k1/1e4*dd*p_impact + k2*dd*noise1 + k3/1e3*p_impact</code></p>\n<p>where k0 to p.k3 are the learned parameters, and:<br>\ndd = 3.5  if the left or right margin is less than 80 time steps<br>\ndd = 6.5 if the left or right margin is less than 30 time steps<br>\ndd =1 otherwise<br>\nnoise1 = the standard deviation of the error in the transit curve fitting<br>\np_impact = impact parameter as calculated by the values provided in star_info.csv file.</p>\n<h1>Sigma</h1>\n<p>After computing the best sigm0 above, I searched for the best sigma predictions using <br>\nPer planet:<br>\n<code>sigma = [k0 + k1*dd*noise1 + k2*p_impact + k3*noise1**1.3]*[wts1**1.13]</code><br>\nwhere the first bracket is per planet and the second is per wavelength.<br>\nwts1=standard deviation of the errors in prediction shape=[planets, wavelengths] normalized to mean of 1.</p>\n<h1>Things I Tried:</h1>\n<pre><code>) Using a more accurate transit function.  From  Mandel  Algol paper,  exact transit function can be computed, assuming a quadratic  even th order limb-darkening law.  The problem  there was  enough  (both wall   understand  calculations  processor   compute  elliptic functions, etc.).  So I tried a simple graphical model  a circles drawn  a grid  simply summing  light intensity  pixels.  This model works well  can provide any desired level  accuracy  using more pixels.  The problem     quite slow.  After using a few tricks, I was able  speed  up x, which     realm  possible solutions,  contest  was  out.  I believe this method will eventually work,  can give surprisingly good estimation results  even fairly high impact parameters.  Note  this method uses information  I was  able  capture   simpler models, namely   taken   ingress  outgress curves – this  important information   planet size.\n) Using a bootstrap approach  determining sigmas.  People did this  ,  I was  able   useful results  \n) Non-rmse predictions.  Too late   competition I realized ( rather, @vitaly demonstrated)  minimizing  RMSE value  predictions      best score.  I was able demonstrate  a  better score  optimizing directly  score,  there was  enough   implement .\n) Better outlier removal  correction.  There are various spikes   raw instrument readings  a better algorithm here would probably be helpful.\n</code></pre>",
      "rawMarkdown": "This competition was a wonderful experience – I got to learn some astrophysics and be part of a great team.  Thanks to @gordonyip for hosting the competition and my teammates @veshkinartem, @pizzaboi, and @vitalykudelya. \n\nOur approach involved a mixing of 3 different separate solutions, our ensembling technique and the other solutions are described in other discussion posts.\n\nMy solution did not involve deep learning or training, I started by trying to understand the physics behind the light curves and never moved beyond that!\n\n**References**\n1. “Analytic solutions to the maximum and average exoplanet\ntransit depth for common stellar limb darkening laws” by René Heller, arXiv:1901.01730v2, 21 Mar 2019\n2. Analytic Lightcurves For Planetary Transit Searches, by Kaisey Mandel and Eric Algol, arXiv:astro-ph/0210099v1, 2 Oct 2002\n3. Transits and Occultations, Joshua Winn, arXiv:1001.2010v5, 24 Sept 2014\n\nFrom Heller:\n![From Heller](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F855ac6ce74e025138566aa2975fe0618%2FScreenshot%20from%202025-09-25%2015-50-45.png?generation=1758905618847486&alt=media)\n\nHere are the ranges from the data we were given.  rprs2 is the ground truth and rprs is its sqrt().\n\nGround truth \nx | rprs2 | rprs |\n| --- | --- | --- |\n|count | 311300 | 311300 |\n|mean    |    0.014689    |   0.115116|\n|std |        0.010661   |    0.037912|\n| min    |     0.003654 |      0.060451 |\n| max   |      0.088650   |    0.297742|\n\n\n# The Physics\nTo help visualize the exoplanet detection and analysis problem, imagine a star as a circle of a certain brightness.  As an exoplanet crosses (transits) in front of the star, it will block some of the light coming from that star.  Since the star and the planet subtend an arc much smaller than the resolution of our imaging systems, we only can see this by measuring the dip in the total light reaching our instrument.\n\nThere are some simplifying assumptions and some complicating factors involved with this model.  Since the organizers specifically called out ExoSim2 as the simulation model for the data provided, they forced some of these.\n    1. The star is not actually uniformly bright when viewed from a distance. Because of different temperatures throughout the depth of the star and the different transmission/absorption at different depths, the star when viewed as a disk is not uniformly bright.  This effect is called limb-darkening.\n    2. The ExoSim2 simulation assumes that the planet acts as black disk of a given radius.  An input file provides the assumed area of the planet disk per wavelength, which alters the star’s output spectrum differently at each wavelength – effectively, the planet has a different apparent size at each wavelength.  This would be the values in the EXOSIM2 planetary radius file: load_rp.  Note that this does not take into account any variation caused by the atmosphere of the planets causing the edge of the viewed planet to behave differently than the center.\n    3. An exoplanet does not cross directly through the center of the star.  The offset is described by the impact parameter, which is p=sma*cos(i) in the contest terminology, where sma = radius of the planet’s orbit and i is the angle between orbit (perpendicular) axis and the path from the star to the viewer.  When sma is expressed in units of stellar radius, then p=0 means the planet passes through the center of the star, and p=1.0 mean the center of the planet just kisses the edge of the star.\n    4. The data is quite noisy\n    5. Sensors drift over time\n\nIn what follows, rprs will mean Rp/Rs, the planet size in stellar radius units, and rprs2 will be the rprs^2, the ratio of the area of the planet to the area of the star.  \n\nThe reason that it is difficult to determine the “true” rprs is that it from the Fig 1 above, the (Rp/Rs)^2 is not the maximum depth of the transit curve.  This has to do with limb-darkening.  Imagine a planet crossing just near the edge of a star with significant limb-darkening – the total light reaching a viewer will not decrease the same percentage even when the planet is fully inside the star envelope as it would if the planet were to pass near the (bright) center of the star.  In the absence of limb-darkening, rprs^2 is equal to delta - this was the case in the Ariel 2024 competition.\n\nHere are some illustrations of transits.  In the transit curves, the vertical red lines are where the planet center crosses the  star edge (roughly the middle of the ingress/outgress portion), and the horizontal dotted green line is the true rprs^2.  You can see that sometimes the true (Rp/Rs)^2 is above the maximum delta (for p=.1) but sometimes it is below the maximum delta (p=.8 or .9).  Hence the difficulty in predicting (Rp/Rs)^2.\n\n![planet transiting .06](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F4a26b2c0bd07ee1213cfa281b58c2e66%2Fcurve_r0.06.png?generation=1758906134657482&alt=media)\n\n![planet transiting .11](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1265417bc258daed7d63e01027cc9bec%2Fcurve_r0.11.png?generation=1758906177953397&alt=media)\n\n![curve =.11](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F3a9715e8cb7d547a9955dc22c557f46c%2Ftransit_p0.1_r0.11.png?generation=1758906218072848&alt=media)\n\n\n![curve .3](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2Fd971e58c9b207f4a415b0e1a1c0e90ec%2Ftransit_p0.9_r0.3.png?generation=1758906271176672&alt=media)\n\n\n# Preprocessing\nI used the organizer provided code with everything enabled.  For AIRS sensors, I summed positions [8:24] and ignored the other positions\nFor FGS, I summed all 32x32 positions at each time step.  Time binning was at 5 original time steps for both.\n\n# Lightcurve\nUsing the mean of the AIRS data over all wavelengths “lightcurve” (first normalize by the mean level at each wavelength to account for a non-uniform star spectrum), I calculate some values.\nI compute two initial points for the ingress/outgress points using the pretty standard gradient maximizing technique.  Smooth the data, take a gradient and look for a min (p1) and a max (p2) and hope that p1<p2.\n\nThen, taking a hint from @egorgi21 from the 2024 competition, I assume a form of the lightcurve with some parameters, and then use Nelder-Mead optimization to find the parameters that best fit the data on a least-squares basis.  I even used his function name: “secret”, although I used a different function.\n\nThere are 2 types of secret function:\n\n**Type 1**  My initial function was of the form:  Linear ingress-outgress regions, centered on p1,p2 of width t, and inside the transit region, I assumed that the star intensity depression followed a quadratic formula:\nIntensity = delta*I(a,b,r) where I(a,b) = (1 – a(1-mu(r)) – b*(1-mu(r))^2), \nwhere a,b are 2 parameters, mu(r)=sqrt(1-r^2), and r is a variable that represents the distance from the star center to the planet center.  Thus is goes from 1 at initial star edge crossing to sqrt(1-p_impact^2) at the center of the crossing.  This formula is a standard one from the references.  This secret function has some problems: (1) it assumes a straight line for ingress/outgress, which is wrong (see above curves), and it fudges a bit at the quadratic formula region.\nThe other problem is the sensor drift.  I assumed that the sensor gain followed at 4th order polynomial gain in time.  A good calculation for the assumed limb-darkening is \nRp/Rs)^2 = delta*(1-a/3-b/6) / I(a,b,p_impact)\nand this done as a correction.  Of course, because the provided p_impact is not accurate, this causes errors in prediction, even with everything else correct.\n\nHere are what some fits look like.  The left curve is the AIRS lightcurve, the right is FGS.  Why the impact parameter for FGS should be different than AIRS, I have not been able to figure out.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F93f497a1776688da0f8b96cc4eca554c%2Fplt_1029552010_0_cie-1.png?generation=1758906904631821&alt=media)\nI use the p1,p2 from the initial fitting as the starting point for the optimization, which yields the best choices for p1,p2,t,a,b,delta, and drift polynomial coefficients.  \n\n**Type 2**  There are some transits with high impact parameters where the above curve does not fit well.  The curves do not have well-defined ingress and outgress regions.  For these, I simply fit the transit depth curve by a polynomial of the form  S = a|x|^2 + b|x|^3 + c|x|^4 + q|x|^5, where the q is constrained so that the curve hits 1 at x=1.   Thus the transit function looks like 1 - delta*(1-S) and we can proceed as in Type 1.  The variable x goes from -1 to 1 over the transit region.  There is no x^1 term because we want a smooth bottom center, and the |x| guarantees a symmetric transit.  Even though this curve can fit reasonably well, there is no good way to predict (Rp/Rs)^2 from delta.\nHere is an example where the Type 1 is worse than Type 2 fitting (sec1 vs sec2 in the caption).\n\n![Type 1](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1d957035dfc94c1f6779663fef9a1937%2Fplt_131083252_0_avr-1.png?generation=1758907292755262&alt=media)\n\n![Type 2](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F11e5dd7aaa99349f50d3b522d7c1b2a6%2Fplt_131083252_0_avr-2.png?generation=1758907333915880&alt=media)\nI fit both curves and pick the one  that has lowest rmse fitting error.\n\n# FGS\nI use the same technique to determine the optimal parameters for the FGS data, using as a starting point the parameters found for the AIRS lightcurve.\n\n# AIRS Wavelengths\nThe optimization routine is too slow to perform for each wavelength (282 per sample), so I borrowed another technique someone used last year:\nI assume that the parameters p1,p2,t,a,b are the same for each wavelength and just want to compute a new delta.  By manipulating the equations correctly, you can write an equation that looks like (playing fast and loose with notation):\nSince (1-delta*I(a,b))*poly = signal  (approx), then\n\n(poly-signal)/signal = delta * I(a,b)\n\nWhich looks like a least-squares problem which can be solved directly by linear algebra, and in one big calculations for all wavelengths at once.\nFor the matrix equation y=delta*x has least squares solution delta = (y*x).sum(axis=0)/(x*x).sum(axis=0)\n\n# NMF Smoothing\nI used Nonnegative-Matrix Factorization to smooth the wavelength data\nThis was done by taking the ground truth data provided and decomposing into the best 5 spectrums (determined through testing to be the best number), then reconstructing the data for each planet using those wavelengths.  In the 2024 competition, there was a confounding problem of gases being introduced in testing that were not in training, which was a problem.  But I couldn’t find a better technique, such as using smoothing over windows, or using an NMF decomposition of the actual resulting values during testing.\n\n# Predict RpRs^2\nBecause now I have predictions for the delta values, I need to convert those to RpRs predictions, which are different in the presence of limb-darkening.\nI used a linear regression fit, over 3 buckets; (1) type=2 fitting, (2) high impact parameter, (3) everything else.  Buckets are m0,m1,m2 and used these features per planet, along with the wavelength dependent delta computed previously.:\n    all_buckets[typ] = [ [m0, ['p_impact','gamma', 't','t2','a','b','a2','b2','delta','airs_delta']],\n                         [m1,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],\n                         [m2,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],\n\nBecause some planets have 2 observations, I used weights of 0.5 on those, with weights of 1.0 otherwise.\n\n# Aggregate\nI took the mean of the predictions for planets with 2 readings\n\n# Wavelength adjustment\nSince the above linear fit does not take into account any differences in wavelength, a wavelength adjustment was performed:\nThe adjustment for each wavelength is the mean (ground/predicted) value over the train set.\n\n# Predict Sigma\nBecause the competition metric is involves a sum over wavelengths, you can separately optimize for the sigma for FGS sensor (wavelength 0) and the AIRS sensors.\n\nAlthough the competition metric roughly expects the sigma to be the std deviation of the errors in your delta predictions, some simple Monte Carlo experiments show that it is not exactly correct.  Thus I do another Nelder-Mead search for the parameters that give the best score as followes.\n\n\n# Sigma0:\nFor the FGS sigma prediction I used:\n```sigma0 = k0/1e4*dd + k1/1e4*dd*p_impact + k2*dd*noise1 + k3/1e3*p_impact```\n\nwhere k0 to p.k3 are the learned parameters, and:\ndd = 3.5  if the left or right margin is less than 80 time steps\ndd = 6.5 if the left or right margin is less than 30 time steps\ndd =1 otherwise\nnoise1 = the standard deviation of the error in the transit curve fitting\np_impact = impact parameter as calculated by the values provided in star_info.csv file.\n\n# Sigma\nAfter computing the best sigm0 above, I searched for the best sigma predictions using \nPer planet:\n```sigma = [k0 + k1*dd*noise1 + k2*p_impact + k3*noise1**1.3]*[wts1**1.13]```\nwhere the first bracket is per planet and the second is per wavelength.\nwts1=standard deviation of the errors in prediction shape=[planets, wavelengths] normalized to mean of 1.\n\n\n# Things I Tried:\n    1) Using a more accurate transit function.  From the Mandel and Algol paper, the exact transit function can be computed, assuming a quadratic or even 4th order limb-darkening law.  The problem in there was not enough time (both wall time to understand the calculations and processor time to compute the elliptic functions, etc.).  So I tried a simple graphical model with a circles drawn in a grid and simply summing the light intensity over pixels.  This model works well and can provide any desired level of accuracy by using more pixels.  The problem is that it is quite slow.  After using a few tricks, I was able to speed it up 100x, which put it in the realm of possible solutions, but contest time was running out.  I believe this method will eventually work, and can give surprisingly good estimation results with even fairly high impact parameters.  Note that this method uses information that I was not able to capture in the simpler models, namely the time taken for the ingress and outgress curves – this is important information on the planet size.\n    2) Using a bootstrap approach to determining sigmas.  People did this last year, but I was not able to get useful results from it\n    3) Non-rmse predictions.  Too late in the competition I realized (or rather, @vitaly demonstrated) that minimizing the RMSE value of predictions does not result in the best score.  I was able demonstrate about a .02 better score by optimizing directly for score, but there was not enough time to implement it.\n    4) Better outlier removal and correction.  There are various spikes in the raw instrument readings and a better algorithm here would probably be helpful.\n\n\n\n\n\n\n\n\n\n",
      "votes": 8
    },
    {
      "id": 3294798,
      "postDate": "2025-09-26T18:38:26.460Z",
      "content": "<p>One I forgot to mention.  When the in transit time was long (more than about .3 of the total time), I switched to a degree 2 polynomial.  Otherwise, the drift polynomial ends up compensating for the bottom of the trannsit curve.  I switch to degree 1 if the transit time even longer, leaving very small margins of out-of-transit time at the edges.</p>",
      "rawMarkdown": "One I forgot to mention.  When the in transit time was long (more than about .3 of the total time), I switched to a degree 2 polynomial.  Otherwise, the drift polynomial ends up compensating for the bottom of the trannsit curve.  I switch to degree 1 if the transit time even longer, leaving very small margins of out-of-transit time at the edges."
    }
  ],
  "comments": [
    {
      "id": 3294798,
      "author_name": "SolverWorld",
      "author_url": "",
      "post_date": "2025-09-26T18:38:26.460000",
      "content": "<p>One I forgot to mention.  When the in transit time was long (more than about .3 of the total time), I switched to a degree 2 polynomial.  Otherwise, the drift polynomial ends up compensating for the bottom of the trannsit curve.  I switch to degree 1 if the transit time even longer, leaving very small margins of out-of-transit time at the edges.</p>",
      "votes": 0,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "3294775": "This competition was a wonderful experience – I got to learn some astrophysics and be part of a great team.  Thanks to @gordonyip for hosting the competition and my teammates @veshkinartem, @pizzaboi, and @vitalykudelya. \n\nOur approach involved a mixing of 3 different separate solutions, our ensembling technique and the other solutions are described in other discussion posts.\n\nMy solution did not involve deep learning or training, I started by trying to understand the physics behind the light curves and never moved beyond that!\n\n**References**\n1. “Analytic solutions to the maximum and average exoplanet\ntransit depth for common stellar limb darkening laws” by René Heller, arXiv:1901.01730v2, 21 Mar 2019\n2. Analytic Lightcurves For Planetary Transit Searches, by Kaisey Mandel and Eric Algol, arXiv:astro-ph/0210099v1, 2 Oct 2002\n3. Transits and Occultations, Joshua Winn, arXiv:1001.2010v5, 24 Sept 2014\n\nFrom Heller:\n![From Heller](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F855ac6ce74e025138566aa2975fe0618%2FScreenshot%20from%202025-09-25%2015-50-45.png?generation=1758905618847486&alt=media)\n\nHere are the ranges from the data we were given.  rprs2 is the ground truth and rprs is its sqrt().\n\nGround truth \nx | rprs2 | rprs |\n| --- | --- | --- |\n|count | 311300 | 311300 |\n|mean    |    0.014689    |   0.115116|\n|std |        0.010661   |    0.037912|\n| min    |     0.003654 |      0.060451 |\n| max   |      0.088650   |    0.297742|\n\n\n# The Physics\nTo help visualize the exoplanet detection and analysis problem, imagine a star as a circle of a certain brightness.  As an exoplanet crosses (transits) in front of the star, it will block some of the light coming from that star.  Since the star and the planet subtend an arc much smaller than the resolution of our imaging systems, we only can see this by measuring the dip in the total light reaching our instrument.\n\nThere are some simplifying assumptions and some complicating factors involved with this model.  Since the organizers specifically called out ExoSim2 as the simulation model for the data provided, they forced some of these.\n    1. The star is not actually uniformly bright when viewed from a distance. Because of different temperatures throughout the depth of the star and the different transmission/absorption at different depths, the star when viewed as a disk is not uniformly bright.  This effect is called limb-darkening.\n    2. The ExoSim2 simulation assumes that the planet acts as black disk of a given radius.  An input file provides the assumed area of the planet disk per wavelength, which alters the star’s output spectrum differently at each wavelength – effectively, the planet has a different apparent size at each wavelength.  This would be the values in the EXOSIM2 planetary radius file: load_rp.  Note that this does not take into account any variation caused by the atmosphere of the planets causing the edge of the viewed planet to behave differently than the center.\n    3. An exoplanet does not cross directly through the center of the star.  The offset is described by the impact parameter, which is p=sma*cos(i) in the contest terminology, where sma = radius of the planet’s orbit and i is the angle between orbit (perpendicular) axis and the path from the star to the viewer.  When sma is expressed in units of stellar radius, then p=0 means the planet passes through the center of the star, and p=1.0 mean the center of the planet just kisses the edge of the star.\n    4. The data is quite noisy\n    5. Sensors drift over time\n\nIn what follows, rprs will mean Rp/Rs, the planet size in stellar radius units, and rprs2 will be the rprs^2, the ratio of the area of the planet to the area of the star.  \n\nThe reason that it is difficult to determine the “true” rprs is that it from the Fig 1 above, the (Rp/Rs)^2 is not the maximum depth of the transit curve.  This has to do with limb-darkening.  Imagine a planet crossing just near the edge of a star with significant limb-darkening – the total light reaching a viewer will not decrease the same percentage even when the planet is fully inside the star envelope as it would if the planet were to pass near the (bright) center of the star.  In the absence of limb-darkening, rprs^2 is equal to delta - this was the case in the Ariel 2024 competition.\n\nHere are some illustrations of transits.  In the transit curves, the vertical red lines are where the planet center crosses the  star edge (roughly the middle of the ingress/outgress portion), and the horizontal dotted green line is the true rprs^2.  You can see that sometimes the true (Rp/Rs)^2 is above the maximum delta (for p=.1) but sometimes it is below the maximum delta (p=.8 or .9).  Hence the difficulty in predicting (Rp/Rs)^2.\n\n![planet transiting .06](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F4a26b2c0bd07ee1213cfa281b58c2e66%2Fcurve_r0.06.png?generation=1758906134657482&alt=media)\n\n![planet transiting .11](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1265417bc258daed7d63e01027cc9bec%2Fcurve_r0.11.png?generation=1758906177953397&alt=media)\n\n![curve =.11](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F3a9715e8cb7d547a9955dc22c557f46c%2Ftransit_p0.1_r0.11.png?generation=1758906218072848&alt=media)\n\n\n![curve .3](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2Fd971e58c9b207f4a415b0e1a1c0e90ec%2Ftransit_p0.9_r0.3.png?generation=1758906271176672&alt=media)\n\n\n# Preprocessing\nI used the organizer provided code with everything enabled.  For AIRS sensors, I summed positions [8:24] and ignored the other positions\nFor FGS, I summed all 32x32 positions at each time step.  Time binning was at 5 original time steps for both.\n\n# Lightcurve\nUsing the mean of the AIRS data over all wavelengths “lightcurve” (first normalize by the mean level at each wavelength to account for a non-uniform star spectrum), I calculate some values.\nI compute two initial points for the ingress/outgress points using the pretty standard gradient maximizing technique.  Smooth the data, take a gradient and look for a min (p1) and a max (p2) and hope that p1<p2.\n\nThen, taking a hint from @egorgi21 from the 2024 competition, I assume a form of the lightcurve with some parameters, and then use Nelder-Mead optimization to find the parameters that best fit the data on a least-squares basis.  I even used his function name: “secret”, although I used a different function.\n\nThere are 2 types of secret function:\n\n**Type 1**  My initial function was of the form:  Linear ingress-outgress regions, centered on p1,p2 of width t, and inside the transit region, I assumed that the star intensity depression followed a quadratic formula:\nIntensity = delta*I(a,b,r) where I(a,b) = (1 – a(1-mu(r)) – b*(1-mu(r))^2), \nwhere a,b are 2 parameters, mu(r)=sqrt(1-r^2), and r is a variable that represents the distance from the star center to the planet center.  Thus is goes from 1 at initial star edge crossing to sqrt(1-p_impact^2) at the center of the crossing.  This formula is a standard one from the references.  This secret function has some problems: (1) it assumes a straight line for ingress/outgress, which is wrong (see above curves), and it fudges a bit at the quadratic formula region.\nThe other problem is the sensor drift.  I assumed that the sensor gain followed at 4th order polynomial gain in time.  A good calculation for the assumed limb-darkening is \nRp/Rs)^2 = delta*(1-a/3-b/6) / I(a,b,p_impact)\nand this done as a correction.  Of course, because the provided p_impact is not accurate, this causes errors in prediction, even with everything else correct.\n\nHere are what some fits look like.  The left curve is the AIRS lightcurve, the right is FGS.  Why the impact parameter for FGS should be different than AIRS, I have not been able to figure out.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F93f497a1776688da0f8b96cc4eca554c%2Fplt_1029552010_0_cie-1.png?generation=1758906904631821&alt=media)\nI use the p1,p2 from the initial fitting as the starting point for the optimization, which yields the best choices for p1,p2,t,a,b,delta, and drift polynomial coefficients.  \n\n**Type 2**  There are some transits with high impact parameters where the above curve does not fit well.  The curves do not have well-defined ingress and outgress regions.  For these, I simply fit the transit depth curve by a polynomial of the form  S = a|x|^2 + b|x|^3 + c|x|^4 + q|x|^5, where the q is constrained so that the curve hits 1 at x=1.   Thus the transit function looks like 1 - delta*(1-S) and we can proceed as in Type 1.  The variable x goes from -1 to 1 over the transit region.  There is no x^1 term because we want a smooth bottom center, and the |x| guarantees a symmetric transit.  Even though this curve can fit reasonably well, there is no good way to predict (Rp/Rs)^2 from delta.\nHere is an example where the Type 1 is worse than Type 2 fitting (sec1 vs sec2 in the caption).\n\n![Type 1](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F1d957035dfc94c1f6779663fef9a1937%2Fplt_131083252_0_avr-1.png?generation=1758907292755262&alt=media)\n\n![Type 2](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F651278%2F11e5dd7aaa99349f50d3b522d7c1b2a6%2Fplt_131083252_0_avr-2.png?generation=1758907333915880&alt=media)\nI fit both curves and pick the one  that has lowest rmse fitting error.\n\n# FGS\nI use the same technique to determine the optimal parameters for the FGS data, using as a starting point the parameters found for the AIRS lightcurve.\n\n# AIRS Wavelengths\nThe optimization routine is too slow to perform for each wavelength (282 per sample), so I borrowed another technique someone used last year:\nI assume that the parameters p1,p2,t,a,b are the same for each wavelength and just want to compute a new delta.  By manipulating the equations correctly, you can write an equation that looks like (playing fast and loose with notation):\nSince (1-delta*I(a,b))*poly = signal  (approx), then\n\n(poly-signal)/signal = delta * I(a,b)\n\nWhich looks like a least-squares problem which can be solved directly by linear algebra, and in one big calculations for all wavelengths at once.\nFor the matrix equation y=delta*x has least squares solution delta = (y*x).sum(axis=0)/(x*x).sum(axis=0)\n\n# NMF Smoothing\nI used Nonnegative-Matrix Factorization to smooth the wavelength data\nThis was done by taking the ground truth data provided and decomposing into the best 5 spectrums (determined through testing to be the best number), then reconstructing the data for each planet using those wavelengths.  In the 2024 competition, there was a confounding problem of gases being introduced in testing that were not in training, which was a problem.  But I couldn’t find a better technique, such as using smoothing over windows, or using an NMF decomposition of the actual resulting values during testing.\n\n# Predict RpRs^2\nBecause now I have predictions for the delta values, I need to convert those to RpRs predictions, which are different in the presence of limb-darkening.\nI used a linear regression fit, over 3 buckets; (1) type=2 fitting, (2) high impact parameter, (3) everything else.  Buckets are m0,m1,m2 and used these features per planet, along with the wavelength dependent delta computed previously.:\n    all_buckets[typ] = [ [m0, ['p_impact','gamma', 't','t2','a','b','a2','b2','delta','airs_delta']],\n                         [m1,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],\n                         [m2,   ['p_impact', 'gamma','a','b','a2','b2','rprs','Rp_t2','dip_lr','dip_lr_adj','airs_delta']],\n\nBecause some planets have 2 observations, I used weights of 0.5 on those, with weights of 1.0 otherwise.\n\n# Aggregate\nI took the mean of the predictions for planets with 2 readings\n\n# Wavelength adjustment\nSince the above linear fit does not take into account any differences in wavelength, a wavelength adjustment was performed:\nThe adjustment for each wavelength is the mean (ground/predicted) value over the train set.\n\n# Predict Sigma\nBecause the competition metric is involves a sum over wavelengths, you can separately optimize for the sigma for FGS sensor (wavelength 0) and the AIRS sensors.\n\nAlthough the competition metric roughly expects the sigma to be the std deviation of the errors in your delta predictions, some simple Monte Carlo experiments show that it is not exactly correct.  Thus I do another Nelder-Mead search for the parameters that give the best score as followes.\n\n\n# Sigma0:\nFor the FGS sigma prediction I used:\n```sigma0 = k0/1e4*dd + k1/1e4*dd*p_impact + k2*dd*noise1 + k3/1e3*p_impact```\n\nwhere k0 to p.k3 are the learned parameters, and:\ndd = 3.5  if the left or right margin is less than 80 time steps\ndd = 6.5 if the left or right margin is less than 30 time steps\ndd =1 otherwise\nnoise1 = the standard deviation of the error in the transit curve fitting\np_impact = impact parameter as calculated by the values provided in star_info.csv file.\n\n# Sigma\nAfter computing the best sigm0 above, I searched for the best sigma predictions using \nPer planet:\n```sigma = [k0 + k1*dd*noise1 + k2*p_impact + k3*noise1**1.3]*[wts1**1.13]```\nwhere the first bracket is per planet and the second is per wavelength.\nwts1=standard deviation of the errors in prediction shape=[planets, wavelengths] normalized to mean of 1.\n\n\n# Things I Tried:\n    1) Using a more accurate transit function.  From the Mandel and Algol paper, the exact transit function can be computed, assuming a quadratic or even 4th order limb-darkening law.  The problem in there was not enough time (both wall time to understand the calculations and processor time to compute the elliptic functions, etc.).  So I tried a simple graphical model with a circles drawn in a grid and simply summing the light intensity over pixels.  This model works well and can provide any desired level of accuracy by using more pixels.  The problem is that it is quite slow.  After using a few tricks, I was able to speed it up 100x, which put it in the realm of possible solutions, but contest time was running out.  I believe this method will eventually work, and can give surprisingly good estimation results with even fairly high impact parameters.  Note that this method uses information that I was not able to capture in the simpler models, namely the time taken for the ingress and outgress curves – this is important information on the planet size.\n    2) Using a bootstrap approach to determining sigmas.  People did this last year, but I was not able to get useful results from it\n    3) Non-rmse predictions.  Too late in the competition I realized (or rather, @vitaly demonstrated) that minimizing the RMSE value of predictions does not result in the best score.  I was able demonstrate about a .02 better score by optimizing directly for score, but there was not enough time to implement it.\n    4) Better outlier removal and correction.  There are various spikes in the raw instrument readings and a better algorithm here would probably be helpful.\n\n\n\n\n\n\n\n\n\n",
    "3294798": "One I forgot to mention.  When the in transit time was long (more than about .3 of the total time), I switched to a degree 2 polynomial.  Otherwise, the drift polynomial ends up compensating for the bottom of the trannsit curve.  I switch to degree 1 if the transit time even longer, leaving very small margins of out-of-transit time at the edges."
  }
}