-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Classy transfer_model #63
base: dev
Are you sure you want to change the base?
Conversation
Codecov Report
@@ Coverage Diff @@
## master #63 +/- ##
==========================================
- Coverage 65.41% 64.89% -0.52%
==========================================
Files 22 22
Lines 2495 2527 +32
==========================================
+ Hits 1632 1640 +8
- Misses 863 887 +24
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks really great so far -- it's definitely got the right usage of things.
I suggest adding a test for the new class, to convince ourselves it's doing the right thing. Aim for 100% coverage of this class! I can help with that if you need me to as well.
hmf/density_field/transfer_models.py
Outdated
import classy | ||
except ImportError as e: | ||
pass | ||
|
||
_allfits = ["CAMB", "FromFile", "EH_BAO", "EH_NoBAO", "BBKS", "BondEfs"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can add "CLASS" to this list
hmf/density_field/transfer_models.py
Outdated
super(CLASS, self).__init__(*args, **kwargs) | ||
self.spline_fn = None | ||
|
||
if self.params['class_obj'] is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put a check whether the actual class is an instance of classy.Class
?
hmf/density_field/transfer_models.py
Outdated
trans = self.class_obj.get_transfer(output_format='camb') | ||
if not trans: | ||
self.class_obj.compute() | ||
trans = self.class_obj.get_transfer(output_format='camb') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not very familiar with Class, but I feel like there might be a more elegant way to do this. Is there no other way to check if compute
has been called other than to get the transfer and check if it's not None? Ideally, you'd have:
if not self.class_obj.condition:
self.class_obj.compute()
trans = self.class_obj.get_transfer(output_format='camb')
hmf/density_field/transfer_models.py
Outdated
**class_object:** | ||
Custom class object. If not set, a new Class object will be | ||
created. | ||
**flip_t:** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The transfer function in hmf is only used to get the power spectrum (at this point). I think it's reasonable just to always take the absolute for now. It might be good to post an issue about this though, and we can think about returning the actual transfer function rather than the log. I chose the log because at the time I thought it must always be positive, and the log is easier to take a spline of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you'll need to remove flip_t
from the docsring as well :-)
hmf/density_field/transfer_models.py
Outdated
trans = self.class_obj.get_transfer(output_format='camb') | ||
|
||
_k, _t = trans['k (h/Mpc)'], trans['-T_tot/k2'] | ||
if self.params['flip_T']: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note point above about using absolute.
hmf/density_field/transfer_models.py
Outdated
try: | ||
import classy | ||
except ImportError as e: | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set HAVE_CLASS=False
here if it fails, then raise an error in the class __init__
if it's false.
Also, add a line to the setup.cfg
in the extras_require
section to the effect of
class =
classy
_defaults = {"class_params": None, "class_obj": None, | ||
"flip_T": False} | ||
|
||
def __init__(self, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the place to raise an error if HAVE_CLASS=False
Also, before we merge, you should:
We'll also have to resolve conflicts with master, but let's do those things first. |
Great! Implemented all of your suggestions and changed a few things:
Let me know if there's anything else, thanks! |
So I think this is failing my test because class is not installed on the test server. Do you have any idea how to add that? I think it needs to be manually installed. Cobaya-install can also be used to install a suite of cosmological packages which might be easier. I did run the tests locally and they passed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, this all looks good. To get tests working, you should do two things.
First, make sure the test doesn't run when CLASS is not installed. You can do this by using the pytest.importorskip
function as the first thing inside the test function. This means people don't have to have CLASS installed to run the tests, and it will just print out that it got skipped (to remind them that there are more tests they might want to run).
Second, you'll have to edit .github/workflows/test_suite.yaml
to add in installation of CLASSY. At around line 70 you should find an "Install" section. Add on the relevant commands to the end of that section (it seems like it's not going to just be pip install classy
unfortunately). It's just bash running there, so you can do whatever you need to do (you could also create a new section under "Install" and call it "Install CLASSY").
hmf/density_field/transfer_models.py
Outdated
|
||
|
||
class CLASS(FromFile): | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an r
just before the quotes to be able to use the \*\*
notation in the docstring (not that you have to do that).
hmf/density_field/transfer_models.py
Outdated
**class_object:** | ||
Custom class object. If not set, a new Class object will be | ||
created. | ||
**flip_t:** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you'll need to remove flip_t
from the docsring as well :-)
Hi @jlashner, did you progress with this? Can I assist in any way? |
Hi Steven, sorry for leaving this out for so long. So I stopped working on this because we were running into some consistency issues between our modified CLASS model and the cosmology that's used throughout hmf, which is an astropy cosmology model. It seems to me that in order to be consistent we'd have to make a new cosmology class that wraps our CLASS object and maps all of the used astropy methods to CLASS methods. Do you have any input on whether this is the right thing to do, and if there would be any lingering astropy cosmology dependence in HMF? Thanks! Anyway, after we figured out that we'd need to put more work into hmf for it to be consistent I decided to move ahead with other parts of the project while we looked into some other options or determined whether the CLASS wrapper was worth implementing in HMF. It looks like the only thing thats left is some minor docstring comments that I can implement. I was also holding off because the CLASS installation is not all that straightforward and I'm not sure the best way to do it through github actions. If you want to take a shot at it that would be super helpful! |
Hi @jlashner, thanks for the update! How bad is the inconsistency? Is it a fundamental inconsistency between astropy and CLASS, or between your modification of CLASS only? Could we get away with using the code as-is for now, and making an issue that we'll want to someday update the CLASS wrapper? The CLASS installation is indeed not straightforward. I think I can give it a go soon. |
Hi Steven, here's my first shot at a classy transfer model. It's behavior is as follows:
.compute()
has been run by checking to see if the transfer function exists yet.class_obj
is specified, a new class object is created. It uses a few default parameters likeomega_b
,omega_cdm
, andh
based on thecosmo
object, updated with any parameters passed viaclass_params
.With our modified class code, it is possible to obtain negative T(k), which will break this since you can't take
ln(T)
. If this transfer is only used to calculate the power spectrum, then it should be fine to returnln(|T|)
, since P(k)~T(k)^2. However if other parts of your code use T(k) (not squared) then this might be a problem. I did a quick scan of hmf and couldn't really find T(k) being used outside of calculating P(k). Do you have an opinion on the best way to handle this? In any case, I added aflip_T
transfer option which returns ln(|T|), but we should discuss if there is a better way to handle this.