44:Synopsis: Definition of the clik-based likelihoods using clipy
55:Author: Jesus Torrado (initially based on MontePython's version
66 by Julien Lesgourgues and Benjamin Audren)
7- Updated to use clipy by Antony Lewis
7+ Updated to use clipy by Antony Lewis and Jesus Torrado
88
99"""
1010
1111import os
1212
1313import numpy as np
14- from packaging import version
1514
1615from cobaya .component import ComponentNotInstalledError , load_external_module
1716from cobaya .input import get_default_info
18- from cobaya .install import download_file , pip_install
17+ from cobaya .install import download_github_release , pip_install
1918from cobaya .likelihood import Likelihood
2019from cobaya .log import LoggedError , get_logger
21- from cobaya .tools import (
22- VersionCheckError ,
23- are_different_params_lists ,
24- create_banner ,
25- )
2620
2721_deprecation_msg_2015 = create_banner ("""
2822The likelihoods from the Planck 2015 data release have been superseded
2923by the 2018 ones, and will eventually be deprecated.
3024""" )
25+ from cobaya .tools import VersionCheckError , are_different_params_lists
3126
3227pla_url_prefix = r"https://pla.esac.esa.int/pla-sl/data-action?COSMOLOGY.COSMOLOGY_OID="
33- clipy_url = "https://github.com/benabed/clipy/archive/refs/heads/main.zip"
28+
29+ # Clipy installation
30+ clipy_repo_name = "benabed/clipy"
31+ clipy_repo_min_version = "0.15"
3432
3533last_version_supp_data_and_covmats = "v2.1"
36- min_version_clipy = "0.11"
3734
3835
3936class PlanckClik (Likelihood ):
@@ -47,6 +44,7 @@ def initialize(self):
4744 if "2015" in self .get_name ():
4845 for line in _deprecation_msg_2015 .split ("\n " ):
4946 self .log .warning (line )
47+ msg_to_install = "run `cobaya-install planck_2018_highl_plik.TTTEEE`"
5048 try :
5149 install_path = (lambda p : self .get_code_path (p ) if p else None )(
5250 self .packages_path
@@ -61,11 +59,13 @@ def initialize(self):
6159 except ComponentNotInstalledError as excpt :
6260 raise ComponentNotInstalledError (
6361 self .log ,
64- (
65- f"Could not find clipy: { excpt } . To install it, "
66- f"run `cobaya-install planck_2018_highl_plik.TTTEEE`"
67- ),
68- )
62+ f"Could not find clipy: { excpt } . To install it, { msg_to_install } " ,
63+ ) from excpt
64+ except VersionCheckError as excpt :
65+ raise VersionCheckError (
66+ self .log ,
67+ f"{ excpt } . To install a new version, { msg_to_install } with `--upgrade`." ,
68+ ) from excpt
6969 # Loading the likelihood data
7070 data_path = get_data_path (self .__class__ .get_qualified_class_name ())
7171 if not os .path .isabs (self .clik_file ):
@@ -80,7 +80,7 @@ def initialize(self):
8080 # Disable JAX to avoid dependency issues
8181 os .environ ["CLIPY_NOJAX" ] = "1"
8282 self .clik = clik .clik (self .clik_file )
83- except Exception :
83+ except Exception as excpt :
8484 # Is it that the file was not found?
8585 if not os .path .exists (self .clik_file ):
8686 raise ComponentNotInstalledError (
@@ -90,7 +90,7 @@ def initialize(self):
9090 "Maybe the 'path' given is not correct? The full path where"
9191 " the .clik file was searched for is '%s'" ,
9292 self .clik_file ,
93- )
93+ ) from excpt
9494 # Else: unknown clipy error
9595 self .log .error (
9696 "An unexpected error occurred in clipy (possibly related to "
@@ -217,11 +217,11 @@ def install(
217217 ** _kwargs ,
218218 ):
219219 name = cls .get_qualified_class_name ()
220- log = get_logger (name )
220+ logger = get_logger (name )
221221 path_names = {"code" : common_path , "data" : get_data_path (name )}
222222 global _clipy_install_failed
223223 if _clipy_install_failed :
224- log .info ("Previous clipy install failed, skipping" )
224+ logger .info ("Previous clipy install failed, skipping" )
225225 return False
226226 # Create common folders: all planck likelihoods share install
227227 # folder for code and data
@@ -233,19 +233,18 @@ def install(
233233 os .makedirs (paths [s ])
234234 success = True
235235 # Install clipy to packages path (don't rely on global installation)
236- if code :
237- # Check if clipy is installed in the packages path specifically
238- clipy_path = os .path .join (paths ["code" ], "clipy" )
239- if not os .path .exists (clipy_path ) or force :
240- log .info ("Installing clipy." )
241- success *= install_clipy (paths ["code" ], no_progress_bars = no_progress_bars )
242- if not success :
243- log .warning ("clipy installation failed!" )
244- _clipy_install_failed = True
236+ if code and (not is_installed_clipy (paths ["code" ], logger = logger ) or force ):
237+ logger .info ("Installing clipy." )
238+ success *= install_clipy (
239+ paths ["code" ], no_progress_bars = no_progress_bars , logger = logger
240+ )
241+ if not success :
242+ logger .warning ("clipy installation failed!" )
243+ _clipy_install_failed = True
245244 if data :
246245 # 2nd test, in case the code wasn't there but the data is:
247246 if force or not cls .is_installed (path = path , code = False , data = True ):
248- log .info ("Downloading the likelihood data." )
247+ logger .info ("Downloading the likelihood data." )
249248 product_id , _ = get_product_id_and_clik_file (name )
250249 # Download and decompress the particular likelihood
251250 url = pla_url_prefix + product_id
@@ -264,10 +263,10 @@ def install(
264263 url ,
265264 paths ["data" ],
266265 size = size ,
267- logger = log ,
266+ logger = logger ,
268267 no_progress_bars = no_progress_bars ,
269268 ):
270- log .error ("Not possible to download this likelihood." )
269+ logger .error ("Not possible to download this likelihood." )
271270 success = False
272271 # Additional data and covmats, stored in same repo as the
273272 # 2018 python lensing likelihood
@@ -311,12 +310,10 @@ def get_clipy_import_path(path):
311310 clipy_path = os .path .join (path , "clipy" )
312311 if not os .path .exists (clipy_path ):
313312 raise FileNotFoundError (f"clipy installation not found at { clipy_path } " )
314-
315313 # Check if it has the proper structure
316314 init_file = os .path .join (clipy_path , "clipy" , "__init__.py" )
317315 if not os .path .exists (init_file ):
318316 raise FileNotFoundError (f"clipy package structure not found at { clipy_path } " )
319-
320317 return clipy_path
321318
322319
@@ -326,53 +323,75 @@ def load_clipy(
326323 logger = None ,
327324 not_installed_level = "error" ,
328325 reload = False ,
329- default_global = True ,
326+ default_global = False ,
330327):
331328 """
332329 Load clipy module and check that it's the correct one.
330+
331+ Returns
332+ -------
333+ clipy: module
334+ The imported clipy module
335+
336+ Raises
337+ ------
338+ ComponentNotInstalledError
339+ If clipy has not been installed
340+ VersionCheckError
341+ If clipy is found, but with a smaller version number.
333342 """
334- try :
335- clipy = load_external_module (
336- module_name = "clipy" ,
337- path = path ,
338- install_path = install_path ,
339- get_import_path = get_clipy_import_path if install_path else None ,
340- logger = logger ,
341- not_installed_level = not_installed_level ,
342- reload = reload ,
343- default_global = default_global ,
344- )
345- # Check that it has the expected clipy interface
346- if not hasattr (clipy , "clik" ):
347- raise ComponentNotInstalledError (
348- logger , "Loaded wrong clipy: missing clik class"
349- )
350- # Check version if possible
351- if hasattr (clipy , "__version__" ):
352- installed_version = version .parse (clipy .__version__ )
353- if installed_version < version .parse (min_version_clipy ):
354- raise VersionCheckError (
355- f"Installed version of clipy ({ installed_version } ) "
356- f"older than minimum required one ({ min_version_clipy } )."
357- )
358- return clipy
359- except ImportError :
343+ if logger is None :
344+ logger = get_logger ("clipy" )
345+ clipy = load_external_module (
346+ module_name = "clipy" ,
347+ path = path ,
348+ install_path = install_path ,
349+ get_import_path = get_clipy_import_path if install_path else None ,
350+ min_version = clipy_repo_min_version ,
351+ logger = logger ,
352+ not_installed_level = not_installed_level ,
353+ reload = reload ,
354+ default_global = default_global ,
355+ )
356+ # Check that it has the expected clipy interface
357+ if not hasattr (clipy , "clik" ):
360358 raise ComponentNotInstalledError (
361359 logger ,
362- "clipy not installed. Install with: cobaya-install planck_2018_highl_plik.TTTEEE" ,
360+ "Loaded wrong clipy: you may have pip-installed 'clipy' instead of "
361+ "'clipy-like'." ,
363362 )
363+ return clipy
364364
365365
366- def is_installed_clipy (path = None , reload = False ):
366+ def is_installed_clipy (path = None , reload = False , logger = None ):
367367 """
368- Check if clipy is installed and working in the specified path.
368+ Check if clipy is installed and working in the specified path. It should not raise any
369+ exception.
370+
371+ Parameters
372+ ----------
373+ path: str, optional
374+ Path where the clipy installation is tested, to which ``clipy`` will be appended
375+ before testing. If not defined, a test for a global python installation will be
376+ performed instead (``default_global=True`` will be passed to the module loader).
377+ reload: bool
378+ Whether to attemp to reload the ``clipy`` module before checking.
379+ logger: logging.Logger, optional
380+ Initialized logger. If note passed, one named ``clipy`` will be created.
381+
382+ Returns
383+ -------
384+ bool
385+ ``True`` if the installation was successful, and ``False`` otherwise.
369386 """
387+ if logger is None :
388+ logger = get_logger ("clipy" )
370389 try :
371390 # If path is specified, don't fall back to global import
372391 default_global = path is None
373392 load_clipy (
374- install_path = path ,
375- logger = get_logger ( "clipy" ) ,
393+ path = os . path . join ( path , "clipy" ) ,
394+ logger = logger ,
376395 not_installed_level = "debug" ,
377396 reload = reload ,
378397 default_global = default_global ,
@@ -382,67 +401,47 @@ def is_installed_clipy(path=None, reload=False):
382401 return False
383402
384403
385- def install_clipy (path , no_progress_bars = False ):
404+ def install_clipy (path , logger = None , no_progress_bars = False ):
386405 """
387406 Install clipy from GitHub repository to the specified path.
388- """
389- log = get_logger ("clipy" )
390- log .info ("Installing clipy from GitHub repository..." )
391407
408+ Parameters
409+ ----------
410+ path: str
411+ Path where clipy will be downloaded into, to which ``clipy`` will be appended.
412+
413+ logger: logging.Logger, optional
414+ Initialized logger. If note passed, one named ``clipy`` will be created.
415+
416+ no_progress_bars: bool
417+ Whether to show download/install progress bars.
418+
419+ Returns
420+ -------
421+ bool
422+ ``True`` if the installation was successful, and ``False`` otherwise.
423+ """
424+ if logger is None :
425+ logger = get_logger ("clipy" )
392426 # Install pre-requisites
393- log .info ("Installing pre-requisites..." )
394- for req in ("numpy" , " astropy" ):
427+ logger .info ("Installing pre-requisites..." )
428+ for req in ("astropy" , ):
395429 exit_status = pip_install (req )
396430 if exit_status :
397- log .error ("Failed installing '%s'." , req )
431+ logger .error ("Failed installing '%s'." , req )
398432 return False
399-
400- # Download clipy from GitHub
401- log .info ("Downloading clipy..." )
402- if not download_file (clipy_url , path , no_progress_bars = no_progress_bars , logger = log ):
403- log .error ("Not possible to download clipy." )
433+ logger .info ("Installing clipy from GitHub repository..." )
434+ success = download_github_release (
435+ path ,
436+ clipy_repo_name ,
437+ "clipy_" + clipy_repo_min_version , # TODO: check if "clipy_" still in release
438+ no_progress_bars = no_progress_bars ,
439+ logger = logger ,
440+ )
441+ if not success :
442+ logger .error ("Could not download clipy from GitHub." )
404443 return False
405-
406- # Extract and move clipy to the correct location
407- import shutil
408- import zipfile
409-
410- # The download_file function may name the file differently
411- zip_files = [os .path .join (path , "main.zip" ), os .path .join (path , "clipy-main.zip" )]
412-
413- zip_file = None
414- for potential_zip in zip_files :
415- if os .path .exists (potential_zip ):
416- zip_file = potential_zip
417- break
418-
419- if zip_file :
420- with zipfile .ZipFile (zip_file , "r" ) as zip_ref :
421- zip_ref .extractall (path )
422- # Move clipy-main to clipy
423- clipy_main_path = os .path .join (path , "clipy-main" )
424- clipy_path = os .path .join (path , "clipy" )
425- if os .path .exists (clipy_main_path ):
426- if os .path .exists (clipy_path ):
427- shutil .rmtree (clipy_path )
428- shutil .move (clipy_main_path , clipy_path )
429- # Clean up zip file
430- os .remove (zip_file )
431- else :
432- # If no zip file found, check if clipy-main directory already exists
433- clipy_main_path = os .path .join (path , "clipy-main" )
434- clipy_path = os .path .join (path , "clipy" )
435- if os .path .exists (clipy_main_path ):
436- if os .path .exists (clipy_path ):
437- shutil .rmtree (clipy_path )
438- shutil .move (clipy_main_path , clipy_path )
439-
440- # Verify installation
441- if not is_installed_clipy (path ):
442- log .error ("clipy installation verification failed." )
443- return False
444-
445- log .info ("clipy installation finished!" )
444+ logger .info ("clipy installation finished!" )
446445 return True
447446
448447
0 commit comments