"""
Function to read a SLUG2 cluster_phot file.
"""
import numpy as np
from collections import namedtuple
from copy import deepcopy
import struct
import re
import errno
from .photometry_convert import photometry_convert
from .read_filter import read_filter
from .slug_open import slug_open
[docs]def read_cluster_phot(model_name, output_dir=None, fmt=None,
nofilterdata=False, photsystem=None,
verbose=False, read_info=None,
filters_only=False, read_filters=None,
read_nebular=None, read_extinct=None,
phot_only=False):
"""
Function to read a SLUG2 cluster_phot file.
Parameters
model_name : string
The name of the model to be read
output_dir : string
The directory where the SLUG2 output is located; if set to None,
the current directory is searched, followed by the SLUG_DIR
directory if that environment variable is set
fmt : 'txt' | 'ascii' | 'bin' | 'binary' | 'fits' | 'fits2'
Format for the file to be read. If one of these is set, the
function will only attempt to open ASCII-('txt' or 'ascii'),
binary ('bin' or 'binary'), or FITS ('fits' or 'fits2')
formatted output, ending in .txt., .bin, or .fits,
respectively. If set to None, the code will try to open
ASCII files first, then if it fails try binary files, and if
it fails again try FITS files.
nofilterdata : bool
If True, the routine does not attempt to read the filter
response data from the standard location
photsystem : None or string
If photsystem is None, the data will be returned in the same
photometric system in which they were read. Alternately, if it
is a string, the data will be converted to the specified
photometric system. Allowable values are 'L_nu', 'L_lambda',
'AB', 'STMAG', and 'Vega', corresponding to the options defined
in the SLUG code. If this is set and the conversion requested
involves a conversion from a wavelength-based system to a
frequency-based one, nofilterdata must be False so that the
central wavelength of the photometric filters is available.
verbose : bool
If True, verbose output is printed as code runs
read_info : dict
On return, this dict will contain the keys 'fname' and
'format', giving the name of the file read and the format it
was in; 'format' will be one of 'ascii', 'binary', or 'fits'
filters_only : bool
If True, the code only reads the data on the filters, not
any of the actual photometry. If combined with nofilterdata,
this can be used to return the list of available filters
and nothing else.
read_filters : None | string | listlike containing strings
If this is None, data on all filters is read. Otherwise only
filters whose name(s) match the input filter names ar
read.
read_nebular : None | bool
If True, only data with the nebular contribution is read; if
False, only data without it is read. Default behavior is to
read all data.
read_extinct : None | bool
If True, only data with extinction applied is read; if
False, only data without it is read. Default behavior is to
read all data.
phot_only : bool
If true, id, trial, time, and filter information are not
read, only photometry
Returns
A namedtuple, which can contain the following fields depending
on the input options, and depending on which fields are present
in the file being read:
id : array, dtype uint
unique ID of cluster
trial: array, dtype uint
which trial was this cluster part of
time : array
times at which cluster spectra are output, in yr
filter_names : list of string
a list giving the name for each filter
filter_units : list of string
a list giving the units for each filter
filter_wl_eff : list
effective wavelength of each filter; this is set to None for the
filters Lbol, QH0, QHe0, and QHe1; omitted if nofilterdata is
True
filter_wl : list of arrays
a list giving the wavelength table for each filter; this is
None for the filters Lbol, QH0, QHe0, and QHe1
filter_response : list of arrays
a list giving the photon response function for each filter;
this is None for the filters Lbol, QH0, QHe0, and QHe1
filter_beta : list
powerlaw index beta for each filter; used to normalize the
photometry
filter_wl_c : list
pivot wavelength for each filter; used to normalize the photometry
phot : array, shape (N_cluster, N_filter)
photometric value in each filter for each cluster; units are as
indicated in the units field
phot_neb : array, shape (N_filter, N_times, N_trials)
same as phot, but for the light after it has passed through
the HII region
phot_ex : array, shape (N_filter, N_times, N_trials)
same as phot, but after extinction has been applied
phot_neb_ex : array, shape (N_filter, N_times, N_trials)
same as phot, but for the light after it has passed through
the HII region and then had extinction applied
Raises
IOError, if no photometry file can be opened
ValueError, if photsystem is set to an unknown value
"""
# Open file
fp, fname = slug_open(model_name+"_cluster_phot",
output_dir=output_dir,
fmt=fmt)
# Print status
if verbose:
print("Reading cluster photometry for model "+model_name)
if read_info is not None:
read_info['fname'] = fname
# See if this file is a checkpoint file
if len(re.findall('_chk\d\d\d\d', model_name)) != 0:
checkpoint = True
else:
checkpoint = False
# Prepare holders for data
if not phot_only:
cluster_id = []
time = []
trial = []
phot = []
# Read data
if fname.endswith('.txt'):
########################################################
# ASCII mode
########################################################
if read_info is not None:
read_info['format'] = 'ascii'
# If this is a checkpoint file, skip the line stating how many
# trials it contains; this line is not guaranteed to be
# accurate, and is intended for the C++ code, not for us
if checkpoint:
fp.readline()
# Read the list of filters
line = fp.readline()
filters = line.split()[2:]
nfilter = len(filters)
# Read the list of units
line = fp.readline()
line = line.replace(')', '(').split('(') # split by ( and )
units = []
for l in line:
if (not l.isspace()) and (len(l) > 0):
units.append(l)
units = units[1:] # Get rid of the units for time
# Search for filters with names that end in _n, _ex, or _nex,
# indicating that they include the effects of the nebula,
# extinction, or both
neb = []
ex = []
for i in range(nfilter):
if len(filters[i]) > 2:
if filters[i][-2:] == '_n':
neb.append(i)
if len(filters[i]) > 3:
if filters[i][-3:] == '_ex':
ex.append(i)
if len(neb) > 0:
nebular = True
phot_neb = []
else:
nebular = False
if len(ex) > 0:
extinct = True
phot_ex = []
else:
extinct = False
if nebular and extinct:
phot_neb_ex = []
# If we have nebular emission or extinction, reshape filter
# and units lists
nuniq = nfilter // ((1+nebular)*(1+extinct))
nfilter = nuniq
filters = filters[:nfilter]
units = units[:nfilter]
# If given a list of filters to read, make sure that we
# haven't been given ones that are not available; if we have,
# raise an error now
if read_filters is not None:
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in read_filters:
if not f in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(f))
else:
if not read_filters in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(read_filters))
# If only reading filter data, don't read any further
if not filters_only:
# If requested to read only certain filters, figure out
# which ones are in our list to read
if read_filters is not None:
fread = []
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in filters:
if f in read_filters:
fread.append(True)
else:
fread.append(False)
else:
for f in filters:
if f == read_filters:
fread.append(True)
else:
fread.append(False)
# Burn a line
line = fp.readline()
# Read through data
trialptr = 0
for line in fp:
if line[:3] == '---':
trialptr = trialptr+1
continue
linesplit = line.split()
if not phot_only:
cluster_id.append(int(linesplit[0]))
time.append(float(linesplit[1]))
if read_nebular is not True and read_extinct is not True:
if read_filters is None:
phot.append(np.array(linesplit[2:2+nfilter],
dtype='float'))
else:
tmp = []
for i, j in enumerate(range(2,2+nfilter)):
if fread[i]:
tmp.append(linesplit[j])
phot.append(np.array(tmp, dtype='float'))
if nebular and read_nebular is not False and \
read_extinct is not True:
if read_filters is None:
phot_neb.append(np.array(
linesplit[nfilter+2:2*nfilter+2],
dtype='float'))
else:
tmp = []
for i, j in enumerate(range(nfilter+2,2+2*nfilter)):
if fread[i]:
tmp.append(linesplit[j])
phot_neb.append(np.array(tmp, dtype='float'))
if extinct and read_nebular is not True and \
read_extinct is not False:
tmp_ex = []
for i in range(nfilter):
substr = line[21*(2+(1+nebular)*nfilter+i):
21*(2+(1+nebular)*nfilter+i+1)]
if read_filters is None:
if substr.isspace():
tmp_ex.append(np.nan)
else:
tmp_ex.append(float(substr))
else:
if fread[i]:
if substr.isspace():
tmp_ex.append(np.nan)
else:
tmp_ex.append(float(substr))
phot_ex.append(np.array(tmp_ex, dtype='float'))
if nebular and extinct and read_nebular is not False \
and read_extinct is not False:
tmp_neb_ex = []
for i in range(nfilter):
substr = line[21*(2+3*nfilter+i):
21*(2+3*nfilter+i+1)]
if read_filters is None:
if substr.isspace():
tmp_neb_ex.append(np.nan)
else:
tmp_neb_ex.append(float(substr))
else:
if fread[i]:
if substr.isspace():
tmp_neb_ex.append(np.nan)
else:
tmp_neb_ex.append(float(substr))
phot_neb_ex.append(np.array(tmp_neb_ex, dtype='float'))
if not phot_only:
trial.append(trialptr)
elif fname.endswith('.bin'):
########################################################
# Binary mode
########################################################
if read_info is not None:
read_info['format'] = 'binary'
# If this is a checkpoint, skip the bytes specifying how many
# trials we have; this is inteded for the C++ code, not for
# us, since we will determine that on our own
if checkpoint:
data = fp.read(struct.calcsize('i'))
# Read number of filters
nfilter = int(fp.readline())
# Read filter names and units
filters = []
units = []
for i in range(nfilter):
line = fp.readline()
filters.append(line.split()[0].decode("utf-8"))
units.append(line.split()[1].decode("utf-8"))
# If given a list of filters to read, make sure that we
# haven't been given ones that are not available; if we have,
# raise an error now
if read_filters is not None:
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in read_filters:
if not f in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(f))
else:
if not read_filters in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(read_filters))
# Read the bits that tells us if we're using nebular emission
# and extinction
data = fp.read(struct.calcsize('b'))
nebular = struct.unpack('b', data)[0] != 0
data = fp.read(struct.calcsize('b'))
extinct = struct.unpack('b', data)[0] != 0
if nebular:
phot_neb = []
if extinct:
phot_ex = []
if nebular and extinct:
phot_neb_ex = []
nftot = nfilter*(1+nebular)*(1+extinct)
# If only reading the filters, skip the rest of this
if not filters_only:
# If requested to read only certain filters, figure out
# which ones are in our list to read
if read_filters is not None:
fread = []
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in filters:
if f in read_filters:
fread.append(True)
else:
fread.append(False)
else:
for f in filters:
if f == read_filters:
fread.append(True)
else:
fread.append(False)
# Go through the rest of the file
while True:
# Read number of clusters and time in next block, checking
# if we've hit eof
data = fp.read(struct.calcsize('LdL'))
if len(data) < struct.calcsize('LdL'):
break
trialptr, t, ncluster = struct.unpack('LdL', data)
# Skip if no clusters
if ncluster == 0:
continue
# Add to time and trial arrays
if not phot_only:
time.extend([t]*ncluster)
trial.extend([trialptr]*ncluster)
# Handle things differently if we're reading
# everything versus if we're reading just some filters
if read_filters is None:
# Read the next block of clusters
chunkstr = ('L'+'d'*nftot)*ncluster
data = fp.read(struct.calcsize(chunkstr))
data_list = struct.unpack(chunkstr, data)
# Pack clusters into data list
if not phot_only:
cluster_id.extend(data_list[::nftot+1])
if read_nebular is not True and \
read_extinct is not True:
phot.extend(
[data_list[(nftot+1)*i+1:
(nftot+1)*i+1+nfilter]
for i in range(ncluster)])
ptr = 1
if nebular:
if read_nebular is not False and \
read_extinct is not True:
phot_neb.extend(
[data_list[(nftot+1)*i+1+ptr*nfilter:
(nftot+1)*i+1+(ptr+1)*nfilter]
for i in range(ncluster)])
ptr = ptr+1
if extinct:
if read_nebular is not True and \
read_extinct is not False:
phot_ex.extend(
[data_list[(nftot+1)*i+1+ptr*nfilter:
(nftot+1)*i+1+(ptr+1)*nfilter]
for i in range(ncluster)])
ptr = ptr+1
if nebular and extinct:
if read_nebular is not False and \
read_extinct is not False:
phot_neb_ex.extend(
[data_list[(nftot+1)*i+1+ptr*nfilter:
(nftot+1)*i+1+(ptr+1)*nfilter]
for i in range(ncluster)])
ptr = ptr+1
else:
# Loop over clusters
for i in range(ncluster):
# Read cluster ID
if not phot_only:
data = fp.read(struct.calcsize('L'))
data_list = struct.unpack('L', data)
cluster_id.extend(data_list)
else:
fp.seek(struct.calcsize('L'), 1)
# Loop over filters
for j in range(nfilter):
if fread[j] and \
read_nebular is not True and \
read_extinct is not True:
data = fp.read(struct.calcsize('d'))
data_list = struct.unpack('d', data)
phot.extend(data_list)
else:
fp.seek(struct.calcsize('d'), 1)
# Repeat for nebular emission
if nebular:
for j in range(nfilter):
if fread[j] and \
read_nebular is not False and \
read_extinct is not True:
data = fp.read(struct.calcsize('d'))
data_list = struct.unpack('d', data)
phot_neb.extend(data_list)
else:
fp.seek(struct.calcsize('d'), 1)
# Repeat for extincted emission
if extinct:
for j in range(nfilter):
if fread[j] and \
read_nebular is not True and \
read_extinct is not False:
data = fp.read(struct.calcsize('d'))
data_list = struct.unpack('d', data)
phot_ex.extend(data_list)
else:
fp.seek(struct.calcsize('d'), 1)
# Repeat for nebular plus extincted emission
if nebular and extinct:
for j in range(nfilter):
if fread[j] and \
read_nebular is not False and \
read_extinct is not False:
data = fp.read(struct.calcsize('d'))
data_list = struct.unpack('d', data)
phot_neb_ex.extend(data_list)
else:
fp.seek(struct.calcsize('d'), 1)
elif fname.endswith('.fits'):
########################################################
# FITS mode
########################################################
if read_info is not None:
read_info['format'] = 'fits'
# Figure out which of the two fits formats we're using; if
# there's > 2 HDUs, we're using fits2, otherwise we're using
# fits1
if len(fp) == 2:
########################################################
# FITS1 format: all the data is stored in a single HDU
########################################################
# Get filter names and units
filters = []
units = []
i = 4
while 'TTYPE'+str(i) in fp[1].header.keys():
filters.append(fp[1].header['TTYPE'+str(i)])
units.append(fp[1].header['TUNIT'+str(i)])
i = i+1
nfilter = len(filters)
# If given a list of filters to read, make sure that we
# haven't been given ones that are not available; if we have,
# raise an error now
if read_filters is not None:
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in read_filters:
if not f in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(f))
else:
if not read_filters in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(read_filters))
# Search for filters with names that end in _neb, _ex, or
# _neb_ex, indicating that they include the effects of the
# nebula, extinction, or both
neb = []
ex = []
for i in range(nfilter):
if len(filters[i]) > 4:
if filters[i][-4:] == '_neb':
neb.append(i)
if len(filters[i]) > 3:
if filters[i][-3:] == '_ex':
ex.append(i)
if len(neb) > 0:
nebular = True
else:
nebular = False
if len(ex) > 0:
extinct = True
else:
extinct = False
# If we have nebular emission or extinction, reshape
# filter and units lists
nuniq = nfilter // ((1+nebular)*(1+extinct))
nfilter = nuniq
filters = filters[:nfilter]
units = units[:nfilter]
# If only reading filters, skip the rest
if not filters_only:
# If requested to read only certain filters, figure
# out which ones are in our list to read
if read_filters is not None:
fread = []
nf_final = 0
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in filters:
if f in read_filters:
fread.append(True)
nf_final = nf_final+1
else:
fread.append(False)
else:
for f in filters:
if f == read_filters:
fread.append(True)
nf_final = nf_final+1
else:
fread.append(False)
else:
fread = [True] * len(filters)
nf_final = len(filters)
# Get cluster ID, trial, time
if not phot_only:
cluster_id = fp[1].data.field('UniqueID')
trial = fp[1].data.field('Trial')
time = fp[1].data.field('Time')
# Get photometric data
if read_nebular is not True and \
read_extinct is not True:
phot = np.zeros((fp[1].header['NAXIS2'], nf_final))
if nebular and \
read_nebular is not False and \
read_extinct is not True:
phot_neb = np.zeros((fp[1].header['NAXIS2'], nf_final))
if extinct and \
read_nebular is not True and \
read_extinct is not False:
phot_ex = np.zeros((fp[1].header['NAXIS2'], nf_final))
if nebular and extinct and \
read_nebular is not False and \
read_extinct is not False:
phot_neb_ex = np.zeros((fp[1].header['NAXIS2'], nf_final))
ptr = 0
for i in range(len(filters)):
if fread[i]:
if read_nebular is not True and \
read_extinct is not True:
phot[:,ptr] = fp[1].data.field(filters[i])
if nebular and \
read_nebular is not False and \
read_extinct is not True:
phot_neb[:,ptr] = fp[1].data.field(
filters[i]+"_neb")
if extinct and \
read_nebular is not True and \
read_extinct is not False:
phot_ex[:,ptr] = fp[1].data.field(
filters[i]+"_ex")
if nebular and extinct and \
read_nebular is not False and \
read_extinct is not False:
phot_neb_ex[:,ptr] = fp[1].data. \
field(filters[i]+"_neb_ex")
ptr = ptr+1
else:
########################################################
# FITS2 format: each filter in its own HDU
########################################################
# Get filter names and units
filters = [fp[i].header['TTYPE1'] for i in
range(2,len(fp))]
units = [fp[i].header['TUNIT1'] for i in
range(2,len(fp))]
nfilter = len(filters)
# If given a list of filters to read, make sure that we
# haven't been given ones that are not available; if we have,
# raise an error now
if read_filters is not None:
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in read_filters:
if not f in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(f))
else:
if not read_filters in filters:
raise IOError(errno.EIO,
"requested filter {:s} not available!".
format(read_filters))
# Search for filters with names that end in _neb, _ex, or
# _neb_ex, indicating that they include the effects of the
# nebula, extinction, or both
neb = []
ex = []
for i in range(nfilter):
if len(filters[i]) > 4:
if filters[i][-4:] == '_neb':
neb.append(i)
if len(filters[i]) > 3:
if filters[i][-3:] == '_ex':
ex.append(i)
if len(neb) > 0:
nebular = True
else:
nebular = False
if len(ex) > 0:
extinct = True
else:
extinct = False
# If we have nebular emission or extinction, reshape
# filter and units lists
nuniq = nfilter // ((1+nebular)*(1+extinct))
nfilter = nuniq
filters = filters[:nfilter]
units = units[:nfilter]
# If only reading filters, skip the rest
if not filters_only:
# If requested to read only certain filters, figure
# out which ones are in our list to read
if read_filters is not None:
fread = []
nf_final = 0
if type(read_filters) is not str and \
type(read_filters) is not np.str_:
for f in filters:
if f in read_filters:
fread.append(True)
nf_final = nf_final+1
else:
fread.append(False)
else:
for f in filters:
if f == read_filters:
fread.append(True)
nf_final = nf_final+1
else:
fread.append(False)
else:
fread = [True] * len(filters)
nf_final = len(filters)
# Get cluster ID, trial, time
if not phot_only:
cluster_id = fp[1].data.field('UniqueID')
trial = fp[1].data.field('Trial')
time = fp[1].data.field('Time')
# Get photometric data
if read_nebular is not True and \
read_extinct is not True:
phot = np.zeros((fp[1].header['NAXIS2'], nf_final))
if nebular and \
read_nebular is not False and \
read_extinct is not True:
phot_neb = np.zeros((fp[1].header['NAXIS2'], nf_final))
if extinct and \
read_nebular is not True and \
read_extinct is not False:
phot_ex = np.zeros((fp[1].header['NAXIS2'], nf_final))
if nebular and extinct and \
read_nebular is not False and \
read_extinct is not False:
phot_neb_ex = np.zeros((fp[1].header['NAXIS2'], nf_final))
ptr1 = 0
ptr2 = 2
for i in range(len(filters)):
if fread[i] and \
read_nebular is not True and \
read_extinct is not True:
phot[:,ptr1] \
= fp[ptr2].data.field(filters[i])
ptr1 = ptr1 + 1
ptr2 = ptr2+1
ptr1 = 0
if nebular:
for i in range(len(filters)):
if fread[i] and \
read_nebular is not False and \
read_extinct is not True:
phot_neb[:,ptr1] \
= fp[ptr2].data.field(filters[i]+'_neb')
ptr1 = ptr1 + 1
ptr2 = ptr2+1
ptr1 = 0
if extinct:
for i in range(len(filters)):
if fread[i] and \
read_nebular is not True and \
read_extinct is not False:
phot_ex[:,ptr1] \
= fp[ptr2].data.field(filters[i]+'_ex')
ptr1 = ptr1 + 1
ptr2 = ptr2+1
ptr1 = 0
if nebular and extinct:
for i in range(len(filters)):
if fread[i] and \
read_nebular is not False and \
read_extinct is not False:
phot_neb_ex[:,ptr1] \
= fp[ptr2].data.field(filters[i]+'_neb_ex')
ptr1 = ptr1 + 1
ptr2 = ptr2+1
ptr1 = 0
########################################################
# End of file reading block
########################################################
# Close file
fp.close()
# If using only a subset of filters, truncate the filter list now
if read_filters is not None:
filters_tmp = []
units_tmp = []
for i in range(len(filters)):
if fread[i]:
filters_tmp.append(filters[i])
units_tmp.append(units[i])
filters = filters_tmp
units = units_tmp
# Convert to arrays
if not filters_only:
if not phot_only:
cluster_id = np.array(cluster_id, dtype='uint')
time = np.array(time, dtype='float')
trial = np.array(trial, dtype='uint')
if read_nebular is not True and \
read_extinct is not True:
phot = np.array(phot, dtype='float')
phot = np.reshape(phot, (phot.size//len(filters),
len(filters)))
if nebular and \
read_nebular is not False and \
read_extinct is not True:
phot_neb = np.array(phot_neb, dtype='float')
phot_neb = np.reshape(phot_neb, (phot_neb.size//len(filters),
len(filters)))
if extinct and \
read_nebular is not True and \
read_extinct is not False:
phot_ex = np.array(phot_ex, dtype='float')
phot_ex = np.reshape(phot_ex, (phot_ex.size//len(filters),
len(filters)))
if nebular and extinct and \
read_nebular is not False and \
read_extinct is not False:
phot_neb_ex = np.array(phot_neb_ex, dtype='float')
phot_neb_ex = np.reshape(phot_neb_ex,
(phot_neb_ex.size//len(filters),
len(filters)))
# Read filter data if requested
if not nofilterdata:
if verbose:
print("Reading filter data")
wl_eff, wavelength, response, beta, wl_c = read_filter(filters)
# Do photometric system conversion if requested
if photsystem is not None and not filters_only:
if verbose:
print("Converting photometric system")
if nofilterdata:
units_save = deepcopy(units)
if read_nebular is not True and \
read_extinct is not True:
photometry_convert(photsystem, phot, units, filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
if nebular and \
read_nebular is not False and \
read_extinct is not True:
photometry_convert(photsystem, phot_neb, units,
filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
if extinct and \
read_nebular is not True and \
read_extinct is not False:
photometry_convert(photsystem, phot_ex, units,
filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
if nebular and extinct and \
read_nebular is not False and \
read_extinct is not False:
photometry_convert(photsystem, phot_neb_ex, units,
filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
units = units_out
else:
units_save = deepcopy(units)
if read_nebular is not True and \
read_extinct is not True:
photometry_convert(photsystem, phot, units, wl_eff,
filter_names=filters, filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
if nebular and \
read_nebular is not False and \
read_extinct is not True:
photometry_convert(photsystem, phot_neb, units,
wl_eff, filter_names=filters,
filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
if extinct and \
read_nebular is not True and \
read_extinct is not False:
photometry_convert(photsystem, phot_ex, units, wl_eff,
filter_names=filters,
filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
if nebular and extinct and \
read_nebular is not False and \
read_extinct is not False:
photometry_convert(photsystem, phot_neb_ex, units,
wl_eff, filter_names=filters,
filter_last=True)
units_out = deepcopy(units)
units = deepcopy(units_save)
units = units_out
# Construct return object
if filters_only or phot_only:
fieldnames = ['filter_names', 'filter_units']
fields = [filters, units]
else:
fieldnames = ['id', 'trial', 'time', 'filter_names', 'filter_units']
fields = [cluster_id, trial, time, filters, units]
if not nofilterdata:
fieldnames = fieldnames + ['filter_wl_eff', 'filter_wl',
'filter_response', 'filter_beta',
'filter_wl_c']
fields = fields + [wl_eff, wavelength, response, beta, wl_c]
if not filters_only and read_nebular is not True and \
read_extinct is not True:
fieldnames = fieldnames + ['phot']
fields = fields + [phot]
if nebular and not filters_only and \
read_nebular is not False and \
read_extinct is not True:
fieldnames = fieldnames + ['phot_neb']
fields = fields + [phot_neb]
if extinct and not filters_only and \
read_nebular is not True and \
read_extinct is not False:
fieldnames = fieldnames + ['phot_ex']
fields = fields + [phot_ex]
if nebular and extinct and not filters_only and \
read_nebular is not False and \
read_extinct is not False:
fieldnames = fieldnames + ['phot_neb_ex']
fields = fields + [phot_neb_ex]
out_type = namedtuple('cluster_phot', fieldnames)
out = out_type(*fields)
# Return
return out