Skip to content

Feat time domain solar wind covariance - #1966

Open
jeremy-baier wants to merge 47 commits into
nanograv:masterfrom
jeremy-baier:feat/jgb-td-solar-wind-gp
Open

Feat time domain solar wind covariance#1966
jeremy-baier wants to merge 47 commits into
nanograv:masterfrom
jeremy-baier:feat/jgb-td-solar-wind-gp

Conversation

@jeremy-baier

@jeremy-baier jeremy-baier commented Feb 23, 2026

Copy link
Copy Markdown
Contributor

Needed for NG20.
Major changes

  • Making phi either 1d or 2d. Necessary for 2-dimensional kernels.
  • Addition of said 2d kernels for the solar wind only for now.
  • Time domain interpolation bases to go with the above. Both custom ( for Bayesian Blocking ) and uniform bins.
  • Since above, need to switch trivial phi inversion to use a cholesky decomposition with a np.linalg.inverse fallback.

More work should really explore additional caching of various parts of the GLS fit when the noise model is being held constant. This might be sub blocks of the design matrix. Or a refactorization of the GLS implementation.

TODO

  • unit tests
  • should check that our basis and phi matrix match those of discovery. (might consider adding tests for this).
  • additional model validations ?
  • Try refactoring so there is one TimeDomainSolarWindNoise class with a kernel parameter

Disclosure that I used co-pilot for generating the unit tests as well as some docstrings and type hinting.

@scottransom scottransom left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot in here and it is beyond me to go through carefully line-by-line! We definitely need to make sure that there are some test cases and/or examples available that provide results that you believe are correct.

Comment thread src/pint/models/noise_model.py Outdated
Comment thread src/pint/models/noise_model.py Outdated
Comment thread src/pint/models/noise_model.py Outdated
@jeremy-baier

Copy link
Copy Markdown
Contributor Author

thanks for the comments, Scott ! I will take a look and see about implementing them.

@dlakaplan

Copy link
Copy Markdown
Contributor

Maybe @abhisrkckl can look at this, since it involves changes to the noise model and some of the whitened residual pieces he put in recently?

@abhisrkckl

Copy link
Copy Markdown
Contributor

Is this ready to be looked at?

@jeremy-baier

Copy link
Copy Markdown
Contributor Author

Is this ready to be looked at?

Yes ! I just need to get the black to pass. I think I have been using the wrong line length settings.

@jeremy-baier

Copy link
Copy Markdown
Contributor Author

@abhisrkckl some of the tests are now failing but I think that is from the rebases above. this is still ready to be looked at, but in the mean time i will get the tests passing.

@scottransom

scottransom commented Jul 20, 2026

Copy link
Copy Markdown
Member

For the black issue, what version are you using? And are you overriding any of the default black settings? The requirements_dev.txt is saying black~=24.0, but black is over v26 now.

@jeremy-baier jeremy-baier changed the title WIP: feat time domain solar wind covariance Feat time domain solar wind covariance Jul 20, 2026
@jeremy-baier

Copy link
Copy Markdown
Contributor Author

For the black issue, what version are you using? And are you overriding any of the default black settings? The requirements_dev.txt is saying black~=24.0, but black is over v26 now.

Okay, yea. Somehow I had a bad version of black installed which was part of the issue. Seems to be fixed now as the black is passing.

Comment thread src/pint/models/noise_model.py Outdated
Comment on lines +93 to +95
def get_tdb_seconds(tbl) -> np.ndarray:
"""Return TOA TDB times in seconds as float64."""
return np.asarray((tbl["tdbld"].quantity * u.day).to(u.s).value, dtype=np.float64)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes more sense as a method in the TOAs class.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep. I have moved this to a method there !

Comment thread src/pint/models/noise_model.py Outdated
Comment on lines +86 to +90
def project_basis_covariance(U: np.ndarray, Phi: np.ndarray) -> np.ndarray:
"""Project basis-space covariance to data-space covariance."""
if np.ndim(Phi) == 1:
return np.dot(U * Phi[None, :], U.T)
return np.dot(U, np.dot(Phi, U.T))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an assert to make sure that Phi is 1D or 2D.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I have elaborated in that docstring on the cases in which Phi should be 1D or 2D as well as specifically checking that the dimensions match between phi and U appropriately.

Comment thread src/pint/models/noise_model.py Outdated
return np.asarray((tbl["tdbld"].quantity * u.day).to(u.s).value, dtype=np.float64)


def _add_tdsw_node_component(model, node, index=None):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our usual convention for utility functions like this is to put them as methods in the component class. For example, see add_dmx_range method in DispersionDMX. The code will be better organized that way.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good suggestion. The helper function is unnecessary and could be useful as a method.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done !

Comment thread src/pint/models/noise_model.py Outdated

def _add_tdsw_node_component(model, node, index=None):
"""Add one TDSWNODE_ prefix parameter to a time-domain SW noise component."""
dct = model.get_prefix_mapping_component("TDSWNODE_")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does dct stand for? maybe rename this variable?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just dictionary. updated !

Comment thread src/pint/models/noise_model.py Outdated
"""Add one TDSWNODE_ prefix parameter to a time-domain SW noise component."""
dct = model.get_prefix_mapping_component("TDSWNODE_")
if index is None:
available = [

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

available --> available_indices

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done !

Comment thread src/pint/models/noise_model.py Outdated
Comment on lines +1439 to +1448
"ridge": {"required": ["TDSWLOGSIG"], "optional": []},
"sqexp": {"required": ["TDSWLOGSIG", "TDSWLOGELL"], "optional": []},
"matern": {
"required": ["TDSWLOGSIG", "TDSWLOGELL"],
"optional": ["TDSWNU"],
},
"quasi_periodic": {
"required": ["TDSWLOGSIG", "TDSWLOGELL", "TDSWLOGGAMP", "TDSWLOGP"],
"optional": [],
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

par files usually use all caps by default for parameter names and values.

Comment thread src/pint/models/noise_model.py Outdated
self.add_param(
strParameter(
name="TDSWKERNEL",
value="ridge",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

par files usually use all caps by default.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I don’t understand this comment. Do you want ‘ridge’ to be in all caps ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah okay. the above comment seems to clarify my confusion. switching the kernel names and interpolation kinds to all caps.

Comment thread src/pint/models/noise_model.py Outdated
index : int or None
Integer index label for the node. If None, increments max index by 1.
"""
return _add_tdsw_node_component(self, node=node, index=index)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code can be brought inside the class.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done !

Comment thread src/pint/models/noise_model.py Outdated
Comment on lines +1880 to +1883
toas,
nodes=None,
dt=None,
kind="linear",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add type hints

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done !

Comment thread src/pint/models/noise_model.py Outdated
return K


def se_kernel(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

se_kernel ---> squared_exp_kernel (?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated as such. ( I copied se_kernel from enterprise extensions, but I agree that square_exponential_kernel is clearer )

@abhisrkckl

Copy link
Copy Markdown
Contributor

I haven't gone through the entire code yet.

@abhisrkckl

Copy link
Copy Markdown
Contributor

The black issue should be taken care if you pre-commit install.

@abhisrkckl

Copy link
Copy Markdown
Contributor

The new component does not appear in this documentation page:
https://nanograv-pint--1966.org.readthedocs.build/en/1966/timingmodels.html

@jeremy-baier

Copy link
Copy Markdown
Contributor Author

The new component does not appear in this documentation page: https://nanograv-pint--1966.org.readthedocs.build/en/1966/timingmodels.html

Okay I just added a docs page which describes the solar wind as well as the differences between the Fourier basis and the time domain bases.

@jeremy-baier

Copy link
Copy Markdown
Contributor Author

@abhisrkckl
Big thanks for your first round of comments. At this time, I think I have addressed them all and it looks like the tests are passing ( 🎉 ). Please let me know what you think. I am mostly happy with how the docs page ended up for the time domain models.
Please let me know if you have anymore concerns on this PR. Otherwise, it needs to be merged in the very near future for ng20 efforts.

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.53659% with 54 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.60%. Comparing base (c12e9be) to head (7d55691).
⚠️ Report is 18 commits behind head on master.

Files with missing lines Patch % Lines
src/pint/models/noise_model.py 85.02% 16 Missing and 15 partials ⚠️
src/pint/fitter.py 65.38% 5 Missing and 4 partials ⚠️
src/pint/utils.py 70.00% 4 Missing and 2 partials ⚠️
src/pint/residuals.py 75.00% 3 Missing and 1 partial ⚠️
src/pint/models/timing_model.py 96.07% 1 Missing and 1 partial ⚠️
src/pint/simulation.py 66.66% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1966      +/-   ##
==========================================
+ Coverage   70.45%   70.60%   +0.15%     
==========================================
  Files         109      109              
  Lines       25765    26051     +286     
  Branches     4114     4170      +56     
==========================================
+ Hits        18152    18393     +241     
- Misses       6441     6464      +23     
- Partials     1172     1194      +22     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants