Commit 4ea26848 authored by Médéric Boquien's avatar Médéric Boquien

Use f-strings in pcigale rather than regular string as they are easier to read.

parent bd31c1de
......@@ -39,8 +39,8 @@ def check(config):
configuration = config.configuration
if configuration:
print("With this configuration cigale will compute {} "
"models.".format(ParametersManager(configuration).size))
print(f"With this configuration cigale will compute "
f"{ParametersManager(configuration).size} models.")
def run(config):
......@@ -55,8 +55,8 @@ def run(config):
def main():
if sys.version_info[:2] < (3, 6):
raise Exception("Python {}.{} is unsupported. Please upgrade to "
"Python 3.6 or later.".format(*sys.version_info[:2]))
raise Exception(f"Python {sys.version_info[0]}.{sys.version_info[1]} is"
f" unsupported. Please upgrade to Python 3.6 or later.")
# We set the sub processes start method to spawn because it solves
# deadlocks when a library cannot handle being used on two sides of a
......
......@@ -54,7 +54,7 @@ class AnalysisModule(object):
if os.path.exists('out/'):
name = datetime.now().strftime("%Y-%m-%d_%H:%M:%S") + '_out/'
os.rename('out/', name)
print("The out/ directory was renamed to {}".format(name))
print(f"The out/ directory was renamed to {name}")
os.mkdir('out/')
shutil.copy('pcigale.ini', 'out/')
......
......@@ -137,7 +137,7 @@ class PdfAnalysis(AnalysisModule):
results = []
nblocks = len(params.blocks)
for iblock in range(nblocks):
print('\nProcessing block {}/{}...'.format(iblock + 1, nblocks))
print(f"\nProcessing block {iblock + 1}/{nblocks}...")
# We keep the models if there is only one block. This allows to
# avoid recomputing the models when we do a mock analysis
if not hasattr(self, '_models'):
......@@ -205,7 +205,7 @@ class PdfAnalysis(AnalysisModule):
# For the mock analysis we do not save the ancillary files.
for k in ['best_sed', 'chi2']:
conf['analysis_params']["save_{}".format(k)] = False
conf['analysis_params'][f"save_{k}"] = False
# We replace the observations with a mock catalogue..
obs.generate_mock(results)
......
......@@ -21,8 +21,8 @@ def save_chi2(obs, variable, models, chi2, values):
"""Save the chi² and the associated physocal properties
"""
fname = 'out/{}_{}_chi2-block-{}.npy'.format(obs.id, variable.replace('/',
'_'), models.iblock)
fname = f"out/{obs.id}_{variable.replace('/', '_')}_chi2-block-" \
f"{models.iblock}.npy"
data = np.memmap(fname, dtype=np.float64, mode='w+',
shape=(2, chi2.size))
data[0, :] = chi2
......
......@@ -209,9 +209,9 @@ def analysis(idx, obs):
gbl_models.block.start)
else:
# It sometimes happens because models are older than the Universe's age
print("No suitable model found for the object {}. It may be that "
"models are older than the Universe or that your chi² are very "
"large.".format(obs.id))
print(f"No suitable model found for the object {obs.id}. It may be that"
f" models are older than the Universe or that your chi² are very "
f"large.")
gbl_counter.inc()
......@@ -269,6 +269,6 @@ def bestfit(oidx, obs):
* corr_dz
if gbl_conf['analysis_params']["save_best_sed"]:
sed.to_fits('out/{}'.format(obs.id), scaling * corr_dz)
sed.to_fits(f"out/{obs.id}", scaling * corr_dz)
gbl_counter.inc()
......@@ -71,8 +71,7 @@ class SaveFluxes(AnalysisModule):
def _compute_models(self, conf, obs, params):
nblocks = len(params.blocks)
for iblock in range(nblocks):
print('Computing models for block {}/{}...'.format(iblock + 1,
nblocks))
print(f"Computing models for block {iblock + 1}/{nblocks}...")
models = ModelsManager(conf, obs, params, iblock)
counter = Counter(len(params.blocks[iblock]), 50, 250)
......@@ -86,7 +85,7 @@ class SaveFluxes(AnalysisModule):
counter.pprint(len(params.blocks[iblock]))
print("Saving the models ....")
models.save('models-block-{}'.format(iblock))
models.save(f"models-block-{iblock}")
def process(self, conf):
......
......@@ -67,6 +67,6 @@ def fluxes(idx, midx):
gbl_models.intprop[prop][idx] = sed.info[prop]
if gbl_save is True:
sed.to_fits("out/{}".format(midx))
sed.to_fits(f"out/{midx}")
gbl_counter.inc()
......@@ -66,6 +66,5 @@ class Counter:
def pprint(self, n):
dt = time.time() - self.t0
print("{}/{} performed in {:.1f} seconds ({:.1f}/s)".
format(n, self.nmodels, dt, n / dt),
print(f"{n}/{self.nmodels} performed in {dt:.1f} seconds ({n/dt:.1f}/s)",
end="\n" if n == self.nmodels else "\r")
......@@ -367,8 +367,8 @@ class Database(object):
result.spec_table)
else:
raise DatabaseLookupError(
"The M2005 SSP for imf <{0}> and metallicity <{1}> is not in "
"the database.".format(imf, metallicity))
f"The M2005 SSP for imf <{imf}> and metallicity <{metallicity}>"
f" is not in the database.")
def get_m2005_parameters(self):
"""Get parameters for the Maraston 2005 stellar models.
......@@ -431,8 +431,8 @@ class Database(object):
result.spec_table)
else:
raise DatabaseLookupError(
"The BC03 SSP for imf <{0}> and metallicity <{1}> is not in "
"the database.".format(imf, metallicity))
f"The BC03 SSP for imf <{imf}> and metallicity <{metallicity}> "
f"is not in the database.")
def get_bc03_parameters(self):
"""Get parameters for the Bruzual & Charlot 2003 stellar models.
......@@ -499,8 +499,8 @@ class Database(object):
result.lumin)
else:
raise DatabaseLookupError(
"The DL2007 model for qpah <{0}>, umin <{1}>, and umax <{2}> "
"is not in the database.".format(qpah, umin, umax))
f"The DL2007 model for qpah <{qpah}>, umin <{umin}>, and umax "
f"<{umax}> is not in the database.")
def get_dl2007_parameters(self):
"""Get parameters for the DL2007 models.
......@@ -570,9 +570,8 @@ class Database(object):
result.wave, result.lumin)
else:
raise DatabaseLookupError(
"The DL2014 model for qpah <{0}>, umin <{1}>, umax <{2}>, and "
"alpha <{3}> is not in the database."
.format(qpah, umin, umax, alpha))
f"The DL2014 model for qpah <{qpah}>, umin <{umin}>, umax "
f"<{umax}>, and alpha <{alpha}> is not in the database.")
def get_dl2014_parameters(self):
"""Get parameters for the DL2014 models.
......@@ -638,8 +637,8 @@ class Database(object):
result.lumin)
else:
raise DatabaseLookupError(
"The Dale2014 template for frac_agn <{0}> and alpha <{1}> "
"is not in the database.".format(frac_agn, alpha))
f"The Dale2014 template for frac_agn <{frac_agn}> and alpha "
f"<{alpha}> is not in the database.")
def get_dale2014_parameters(self):
"""Get parameters for the Dale 2014 models.
......@@ -884,8 +883,8 @@ class Database(object):
result.lumin)
else:
raise DatabaseLookupError(
"The Schreiber2016 template for type <{0}> and tdust <{1}> "
"is not in the database.".format(type, tdust))
f"The Schreiber2016 template for type <{type}> and tdust "
f"<{tdust}> is not in the database.")
def get_schreiber2016_parameters(self):
"""Get parameters for the Scnreiber 2016 models.
......@@ -956,9 +955,8 @@ class Database(object):
result.wave, result.lumin)
else:
raise DatabaseLookupError(
"The THEMIS model for qhac <{0}>, umin <{1}>, umax <{2}>, and "
"alpha <{3}> is not in the database."
.format(qhac, umin, umax, alpha))
f"The THEMIS model for qhac <{qhac}>, umin <{umin}>, umax "
f"<{umax}>, and alpha <{alpha}> is not in the database.")
def _get_parameters(self, schema):
"""Generic function to get parameters from an arbitrary schema.
......@@ -1038,7 +1036,7 @@ class Database(object):
raise Exception('The database is not writable.')
else:
raise DatabaseLookupError(
"The filter <{0}> is not in the database".format(name))
f"The filter <{name}> is not in the database")
def get_filter(self, name):
"""
......@@ -1067,7 +1065,7 @@ class Database(object):
result.pivot_wavelength)
else:
raise DatabaseLookupError(
"The filter <{0}> is not in the database".format(name))
f"The filter <{name}> is not in the database")
def get_filter_names(self):
"""Get the list of the name of the filters in the database.
......
......@@ -66,6 +66,6 @@ class ModelsManager(object):
for prop in sorted(self.intprop.keys()):
table.add_column(Column(self.intprop[prop], name=prop))
table.write("out/{}.fits".format(filename))
table.write("out/{}.txt".format(filename), format='ascii.fixed_width',
table.write(f"out/{filename}.fits")
table.write(f"out/{filename}.txt", format='ascii.fixed_width',
delimiter=None)
......@@ -103,15 +103,15 @@ class ObservationsManagerPassbands(object):
"""
for item in self.tofit + self.tofit_err:
if item not in self.table.colnames:
raise Exception("{} to be taken in the fit but not present "
"in the observation table.".format(item))
raise Exception(f"{item} to be taken in the fit but not present"
f" in the observation table.")
for item in self.table.colnames:
if (item != 'id' and item != 'redshift' and item != 'distance' and
item not in self.tofit + self.tofit_err):
self.table.remove_column(item)
print("Warning: {} in the input file but not to be taken into"
" account in the fit.".format(item))
print(f"Warning: {item} in the input file but not to be taken "
f"into account in the fit.")
def _check_errors(self, defaulterror=0.1):
"""Check whether the error columns are present. If not, add them.
......@@ -148,9 +148,8 @@ class ObservationsManagerPassbands(object):
name=error)
self.table.add_column(colerr,
index=self.table.colnames.index(item)+1)
print("Warning: {}% of {} taken as errors.".format(defaulterror *
100.,
item))
print(f"Warning: {defaulterror * 100}% of {item} taken as "
f"errors.")
def _check_invalid(self, upperlimits=False, threshold=-9990.):
"""Check whether invalid data are correctly marked as such.
......@@ -194,8 +193,7 @@ class ObservationsManagerPassbands(object):
self.extprops.remove(item)
self.extprops_err.remove(item + '_err')
self.table.remove_columns([item, item + '_err'])
print("Warning: {} removed as no valid data was found.".format(
allinvalid))
print(f"Warning: {allinvalid} removed as no valid data was found.")
def _add_model_error(self, modelerror=0.1):
"""Add in quadrature the error of the model to the input error.
......@@ -256,9 +254,9 @@ class ObservationsManagerPassbands(object):
Root of the filename where to save the observations.
"""
self.table.write('out/{}.fits'.format(filename))
self.table.write('out/{}.txt'.format(filename),
format='ascii.fixed_width', delimiter=None)
self.table.write(f'out/{filename}.fits')
self.table.write(f'out/{filename}.txt', format='ascii.fixed_width',
delimiter=None)
class ObservationsManagerVirtual(object):
......
......@@ -313,9 +313,10 @@ class BestResultsManager(object):
chi2_red = self.chi2 / (nobs - 1)
# If low values of reduced chi^2, it means that the data are overfitted
# Errors might be under-estimated or not enough valid data.
print("\n{}% of the objects have chi^2_red~0 and {}% chi^2_red<0.5"
.format(np.round((chi2_red < 1e-12).sum() / chi2_red.size, 1),
np.round((chi2_red < 0.5).sum() / chi2_red.size, 1)))
print(f"\n{np.round((chi2_red < 1e-12).sum() / chi2_red.size, 1)}% of "
f"the objects have chi^2_red~0 and "
f"{np.round((chi2_red < 0.5).sum() / chi2_red.size, 1)}% "
f"chi^2_red<0.5")
class ResultsManager(object):
......@@ -405,6 +406,6 @@ class ResultsManager(object):
name="best."+band, unit=unit))
table.write("out/{}.txt".format(filename), format='ascii.fixed_width',
table.write(f"out/{filename}.txt", format='ascii.fixed_width',
delimiter=None)
table.write("out/{}.fits".format(filename), format='fits')
table.write(f"out/{filename}.fits", format='fits')
......@@ -37,10 +37,10 @@ def save_sed_to_fits(sed, prefix, norm=1.):
for name in sed.contribution_names:
table[name] = Column(norm * sed.get_lumin_contribution(name),
unit="W/nm")
table.write("{}_best_model.fits".format(prefix))
table.write(f"{prefix}_best_model.fits")
if sed.sfh is not None:
table = Table(meta=info)
table["time"] = Column(np.arange(sed.sfh.size), unit="Myr")
table["SFR"] = Column(norm * sed.sfh, unit="Msun/yr")
table.write("{}_SFH.fits".format(prefix))
table.write(f"{prefix}_SFH.fits")
......@@ -63,7 +63,7 @@ class BC03(SedModule):
elif self.imf == 1:
self.ssp = database.get_bc03('chab', self.metallicity)
else:
raise Exception("IMF #{} unknown".format(self.imf))
raise Exception(f"IMF #{self.imf} unknown")
def process(self, sed):
"""Add the convolution of a Bruzual and Charlot SSP to the SED
......
......@@ -56,7 +56,7 @@ class Fluxes(SedModule):
for filter_ in filter_list:
sed.add_info(
"param.{}".format(filter_),
f"param.{filter_}",
sed.compute_fnu(filter_),
True
)
......
......@@ -61,7 +61,7 @@ class M2005(SedModule):
with Database() as database:
self.ssp = database.get_m2005('krou', self.metallicity)
else:
raise Exception("IMF #{} unknown".format(self.imf))
raise Exception(f"IMF #{self.imf} unknown")
def process(self, sed):
"""Add the convolution of a Maraston 2005 SSP to the SED
......
......@@ -160,8 +160,8 @@ class Redshifting(SedModule):
# Raise an error when applying a negative redshift. This module is
# not for blue-shifting.
if self.redshift < 0.:
raise Exception("The redshift provided is negative <{}>."
.format(self.redshift))
raise Exception(f"The redshift provided is negative "
f"({self.redshift}).")
self.universe_age = cosmology.age(self.redshift).value * 1000.
if self.redshift == 0.:
......@@ -188,8 +188,8 @@ class Redshifting(SedModule):
# If the SED is already redshifted, raise an error.
if ('universe.redshift' in sed.info and
sed.info['universe.redshift'] > 0.):
raise Exception("The SED is already redshifted <z={}>."
.format(sed.info['universe.redshift']))
raise Exception(f"The SED is already redshifted (z="
f"{sed.info['universe.redshift']}).")
if redshift > 0.:
# We redshift directly the SED wavelength grid
......
......@@ -220,14 +220,14 @@ class RestframeParam(SedModule):
if 'nebular.lines_young' in sed.contribution_names:
for line, EW in self.EW(sed).items():
sed.add_info("param.EW({}/{})".format(*line), EW)
sed.add_info(f"param.EW({line[0]}/{line[1]})", EW)
for filt in self.lumin_filters:
sed.add_info("param.restframe_Lnu({})".format(filt),
sed.add_info(f"param.restframe_Lnu({filt}),
fluxes[filt] * self.to_lumin,
True)
for filt1, filt2 in self.colours:
sed.add_info("param.restframe_{}-{}".format(filt1, filt2),
sed.add_info(f"param.restframe_{filt1}-{filt2}",
2.5 * np.log10(fluxes[filt2]/fluxes[filt1]))
......
......@@ -90,7 +90,7 @@ class SfhPeriodic(SedModule):
burst = np.zeros_like(time_grid)
burst[:int(self.tau_bursts)+1] = 1.
else:
raise Exception("Burst type {} unknown.".format(self.type_bursts))
raise Exception(f"Burst type {self.type_bursts} unknown.")
for t_burst in np.arange(0, age, self.delta_bursts):
self.sfr += burst
......
......@@ -139,8 +139,8 @@ class Configuration(object):
self.config['cores'] = ""
self.config.comments['cores'] = [""] + wrap(
"Number of CPU cores available. This computer has {} cores."
.format(mp.cpu_count()))
f"Number of CPU cores available. This computer has "
f"{mp.cpu_count()} cores.")
self.spec['cores'] = "integer(min=1)"
self.config.write()
......@@ -187,9 +187,8 @@ class Configuration(object):
# band
for band in bands:
if band.endswith('_err') and (band[:-4] not in bands):
raise Exception("The observation table as a {} column "
"but no {} column.".format(band,
band[:-4]))
raise Exception(f"The observation table as a {band} column "
f"but no {band[:-4]} column.")
self.config['bands'] = bands
else:
......@@ -276,10 +275,10 @@ class Configuration(object):
for module, param, message in configobj.flatten_errors(self.config,
validity):
if len(module) > 0:
print("Module {}, parameter {}: {}".format('/'.join(module),
param, message))
print(f"Module {'/'.join(module)}, parameter {param}: "
f"{message}")
else:
print("Parameter {}: {}".format(param, message))
print(f"Parameter {param}: {message}")
print("Run the same command after having fixed pcigale.ini.")
return None
......@@ -327,8 +326,8 @@ class Configuration(object):
for module in modules:
if all([user_module not in modules[module] for user_module in
self.config['sed_modules']]):
print("{} Options are: {}.".
format(comments[module], ', '.join(modules[module])))
print(f"{comments[module]} Options are: "
f"{', '.join(modules[module])}.")
def complete_redshifts(self):
"""Complete the configuration when the redshifts are missing from the
......
......@@ -17,7 +17,7 @@ class VdtValueRepeatedError(vdt.VdtValueError):
Traceback (most recent call last):
VdtValueRepeatedError: the value "jedie" is too long.
"""
vdt.ValidateError.__init__(self, 'the value {} is repeated.'.format(value))
vdt.ValidateError.__init__(self, f"the value {value} is repeated.")
def is_cigale_list(inobject, dtype='float', minvalue=None, maxvalue=None,
......
......@@ -39,8 +39,8 @@ def read_table(file_):
try:
table = Table.read(file_, format="ascii", delimiter='\s')
except InconsistentTableError:
raise Exception("The file <{}> can not be parsed as a data "
"table.".format(file_))
raise Exception(f"The file {file_} can not be parsed as a data "
"table.")
# Convert all the integers to floats.
return Table([
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment