21cmfast / 21cmFAST

Official repository for 21cmFAST: a code for generating fast simulations of the cosmological 21cm signal
MIT License
58 stars 37 forks source link

[Question] I am not sure about how to use calibrate_photon_cons. Can I change the eff_factor with this? #334

Closed Andresfgomez970 closed 1 year ago

Andresfgomez970 commented 1 year ago

I am trying to change the eff_factor for the ionization in astro_params. However, I am not sure about how to do it. Any input would be really appreciate it!

Sorry, this is a very simple thing in fact. It would only be a matter of doing. I do leave it here, but if it is consider a trivial thing please proceed to remove the issue.

p21c.AstroParams.defaults['HII_EFF_FACTOR'] = 40

Thank again for the library.

steven-murray commented 1 year ago

@Andresfgomez970 I think you don't want to change the default, you want to change the parameter in a particular instance. So, you want to do something like

astro_params = p21c.AstroParams(HII_EFF_FACTOR=40.0)
p21c.calibrate_photon_cons(astro_params=astro_params)
Andresfgomez970 commented 1 year ago

I did try this but I get the following output:

/anaconda3/envs/21cmFast/lib/python3.11/site-packages/py21cmfast/_cfg.py:57: UserWarning: Your configuration file is out of date. Updating... warnings.warn( /anaconda3/envs/21cmFast/lib/python3.11/site-packages/py21cmfast/_cfg.py:41: UserWarning: Your configuration file is out of date. Updating... warnings.warn("Your configuration file is out of date. Updating...") Traceback (most recent call last): File "21cmFastLearning/constrained_evolution.py", line 26, in p21c.calibrate_photon_cons(astro_params=astro_params) ^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: module 'py21cmfast' has no attribute 'calibrate_photon_cons'

Any idea of why? I do have the version Using 21cmFAST version 3.2.0. I think it could be a bug then. If I can share any other information that could be useful please just let me know.

Thank you very much for the quick answer!

steven-murray commented 1 year ago

Try p21c.wrapper.calibrate_photon_cons

Andresfgomez970 commented 1 year ago

Thanks, this one worked. However it asks for all the paramters as input. That is, if I simply run

astro_params = p21c.AstroParams(HII_EFF_FACTOR=40.0) p21c.wrapper.calibrate_photon_cons(astro_params=astro_params)

I would get. It would be idea that the each parameter had the defaults as input. That is: user_params = p21c.UserParams.defaults and so on. Thanks again, at least with this I will not change the default and then forget it and have errors.

raceback (most recent call last): File "/home/AbacoGen01/21cmFastLearning/constrained_evolution.py", line 26, in p21c.wrapper.calibrate_photon_cons(astro_params=astro_params) TypeError: calibrate_photon_cons() missing 7 required positional arguments: 'user_params', 'cosmo_params', 'flag_options', 'init_box', 'regenerate', 'write', and 'direc'

Another thing that could become very useful is that when you call a class instance with dir(class_instance) it actually show you the method and parameters. I know this would probably make the wrapper more involved. But in my personal experience coding I find dir particularly useful.

qyx268 commented 1 year ago

Is there a reason to run photon conservation codes independently from run_lightcone or run_coeval? Normally these two functions are called with PHOTON_CONS=True, so that we will get a coeval or lightcone output which also has photon_nonconservation_data. Therefore, to have e.g. a different HII_EFF_FACTOR, normally we would specify it in astro_params for run_lightcone or run_coeval. This would also mean that if we don't need to specify the other inputs (e.g. user_params, etc), 21cmFAST will take the default.

With that being said, I believe calibrate_photon_cons can be run independently. However, we do need to specify all other inputs (which again are normally assigned inside run_lightcone or run_coeval). Because calibrate_photon_cons also requires a initial condition, so I think the easiest way is to run IC first with all user-specific parameters included and then pass the IC outputs to calibrate_photon_cons. Could you try something like this:

        init_box = p21c.initial_conditions(
            user_params = {"HII_DIM": 100, "BOX_LEN": 100},
            cosmo_params = p21c.CosmoParams(SIGMA_8=0.8),
            random_seed=54321
        )

        p21c.calibrate_photon_cons(astro_params = p21c.AstroParams(HII_EFF_FACTOR=40.0), # IC doesnt have Astro, so this is still needed
                                                      flag_options = p21c.FlagOptions(), # also needed
                                                      user_params = init_box.user_params,
                                                      cosmo_params = init_box.cosmo_params,
                                                      regenerate=init_box.regenerate,
                                                      write=init_box.write,
                                                      direc=init_box.direc
                                                    )

One thing to note is that, calibrate_photon_cons does not return anything. Everything it calculates is saved in RAM. We will need to call output = p21c.wrapper._get_photon_nonconservation_data to get an output.

Please note that given the fact (1) _get_photon_nonconservation_data has a function name starting with _, and (2) calibrate_photon_cons can only be called by p21c.wrapper.calibrate_photon_cons instead of p21c.calibrate_photon_cons, they are not designed to be called independently...

steven-murray commented 1 year ago

I agree with @qyx268 that this function was not designed to be called by the user, but is an internal function. You should think about whether you really need to call it.

Andresfgomez970 commented 1 year ago

Thank @qyx268 and @steven-murray. My initial question is totally solved and this issued have come to an end.

However, I think that I must amend my initial question answering @qyx268 of why to run independently, the idea is to change the HII_EFF_FACTOR on the run at different red-shifts to see how results would change and fit certain ionization values for example. I did opted to run for each redshift with a certain HII_EFF_FACTOR, however, I think this is time-consuming since this is really changing HII_EFF_FACTOR all the time, rater than from z to z + Delta(z). If there is any way to change HII_EFF_FACTOR consistently only from z to z + Delta(z) I would appreciate the input.

Again, thanks to both for answering my question clearly.

On the other hand, let me ask something out of curiosity: I didn't understand the point you are stressing by saying "which also has photon_nonconservation_data". I did search for the use of photon_nonconservation_data in the documentation but did not find much. Any feedback in this respect will also be appreciated as it would also help me get the most out of your work.

qyx268 commented 1 year ago

I am still not really following the procedure of your calculation, sorry. Are you doing something like a lightcone calculation and would like to change HII_EFF_FACTOR at different redshifts? This is completely physical but not currently supported by run_lightcone. However, as run_lightcone is essentially a list of run_coeval at different redshifts, you can in fact run a number of run_coeval programs with changing HII_EFF_FACTOR at different redshifts, something like

coevals = [run_coeval(redshift=redshift, astro_params={'HII_EFF_FACTOR': HII_EFF_FACTOR}) for redshift, HII_EFF_FACTOR in zip(redshifts, HII_EFF_FACTORs)]

Then later you can construct the lightcone using these coevals.

photon_nonconservation_data is a part of 21cmfast's HighLevelOutput classes: LightCone and Coeval. e.g., the output you will get after running coeval = run_coeval(args) or lightcone = run_lightcone(args). You can then grab photon_nonconservation_data by calling coeval.photon_nonconservation_data or lightcone.photon_nonconservation_data. photon_nonconservation_data contains the analytic results that 21cmfast needs in order to do photon conservation (check https://arxiv.org/abs/2112.05184):

      z_analytic: array of redshifts defining the analytic ionized fraction
      Q_analytic: array of analytic  ionized fractions corresponding to `z_analytic`
      z_calibration: array of redshifts defining the ionized fraction from 21cmFAST without recombinations
      nf_calibration: array of calibration ionized fractions corresponding to `z_calibration`
      delta_z_photon_cons: the change in redshift required to calibrate 21cmFAST, as a function of z_calibration
      nf_photoncons: the neutral fraction as a function of redshift
Andresfgomez970 commented 1 year ago

Thank you very much for your answer and making more clear what I was trying to say, I really appreciate it and it really helps me into reassuring and deepening my understanding! I did in fact made the routine you mentioned in a less compact manner.

Thank you very much for your answer and making more clear what I was trying to say, I really appreciate it and it really helps me into reassuring and deepening my understanding! I did in fact make the routine you mentioned in a less compact manner.

Also, thank you so much for the details about photon_nonconservation_data!


def run_with_efficiency(params):
    eff, z_value, initial_conditions = params
    astro_params = p21c.AstroParams(
        HII_EFF_FACTOR = eff
    )

    coeval = p21c.run_coeval(
        redshift=z_value, 
        init_box=initial_conditions,
        astro_params= astro_params
    )

    return coeval

eff_visual, z_visual = ...
params_z = [(eff, z_val, initial_conditions) for eff, z_val in zip(eff_visual, z_visual)]
coevals = [run_with_efficiency(params) for params in params_z]