def from_ini(cls, folder, ini_file='fpp.ini', ichrone='mist', recalc=False,
                refit_trap=False, **kwargs):
        """
        To enable simple usage, initializes a FPPCalculation from a .ini file

        By default, a file called ``fpp.ini`` will be looked for in the
        current folder.  Also present must be a ``star.ini`` file that
        contains the observed properties of the target star.

        ``fpp.ini`` must be of the following form::

            name = k2oi
            ra = 11:30:14.510
            dec = +07:35:18.21

            period = 32.988 #days
            rprs = 0.0534   #Rp/Rstar
            photfile = lc_k2oi.csv

            [constraints]
            maxrad = 10 #exclusion radius [arcsec]
            secthresh = 0.001 #maximum allowed secondary signal depth

            #This variable defines contrast curves
            #ccfiles = Keck_J.cc, Lick_J.cc

        Photfile must be a text file with columns ``(days_from_midtransit,
        flux, flux_err)``.  Both whitespace- and comma-delimited
        will be tried, using ``np.loadtxt``.  Photfile need not be there
        if there is a pickled :class:`TransitSignal` saved in the same
        directory as ``ini_file``, named ``trsig.pkl`` (or another name
        as defined by ``trsig`` keyword in ``.ini`` file).

        ``star.ini`` should look something like the following::

            B = 15.005, 0.06
            V = 13.496, 0.05
            g = 14.223, 0.05
            r = 12.858, 0.04
            i = 11.661, 0.08
            J = 9.763, 0.03
            H = 9.135, 0.03
            K = 8.899, 0.02
            W1 = 8.769, 0.023
            W2 = 8.668, 0.02
            W3 = 8.552, 0.025
            Kepler = 12.473

            #Teff = 3503, 80
            #feh = 0.09, 0.09
            #logg = 4.89, 0.1

        Any star properties can be defined; if errors are included
        then they will be used in the :class:`isochrones.StarModel`
        MCMC fit.
        Spectroscopic parameters (``Teff, feh, logg``) are optional.
        If included, then they will also be included in
        :class:`isochrones.StarModel` fit.  A magnitude for the
        band in which the transit signal is observed (e.g., ``Kepler``)
        is required, though need not have associated uncertainty.


        :param folder:
            Folder to find configuration files.

        :param ini_file:
            Input configuration file.

        :param star_ini_file:
            Input config file for :class:`isochrones.StarModel` fits.

        :param recalc:
            Whether to re-calculate :class:`PopulationSet`, if a
            ``popset.h5`` file is already present

        :param **kwargs:
            Keyword arguments passed to :class:`PopulationSet`.

        Creates:

            * ``trsig.pkl``: the pickled :class:`vespa.TransitSignal` object.
            * ``starfield.h5``: the TRILEGAL field star simulation
            * ``starmodel.h5``: the :class:`isochrones.StarModel` fit
            * ``popset.h5``: the :class:`vespa.PopulationSet` object
              representing the model population simulations.

        Raises
        ------
        RuntimeError :
            If single, double, and triple starmodels are
            not computed, then raises with admonition to run
            `starfit --all`.

        AttributeError :
            If `trsig.pkl` not present in folder, and
            `photfile` is not defined in config file.

        """

        # Check if all starmodel fits are done.
        # If not, tell user to run 'starfit --all'
        config = ConfigObj(os.path.join(folder, ini_file))

        # Load required entries from ini_file
        try:
            name = config['name']
            ra, dec = config['ra'], config['dec']
            period = float(config['period'])
            rprs = float(config['rprs'])
        except KeyError as err:
            raise KeyError('Missing required element of ini file: {}'.format(err))

        try:
            cadence = float(config['cadence'])
        except KeyError:
            logging.warning('Cadence not provided in fpp.ini; defaulting to Kepler cadence.')
            logging.warning('If this is not a Kepler target, please set cadence (in days).')
            cadence = 1626./86400 # Default to Kepler cadence

        def fullpath(filename):
            if os.path.isabs(filename):
                return filename
            else:
                return os.path.join(folder, filename)

        # Non-required entries with default values
        popset_file = fullpath(config.get('popset', 'popset.h5'))
        starfield_file = fullpath(config.get('starfield', 'starfield.h5'))
        trsig_file = fullpath(config.get('trsig', 'trsig.pkl'))

        # Check for StarModel fits
        starmodel_basename = config.get('starmodel_basename',
                                        '{}_starmodel'.format(ichrone))
        single_starmodel_file = os.path.join(folder,'{}_single.h5'.format(starmodel_basename))
        binary_starmodel_file = os.path.join(folder,'{}_binary.h5'.format(starmodel_basename))
        triple_starmodel_file = os.path.join(folder,'{}_triple.h5'.format(starmodel_basename))

        try:
            single_starmodel = StarModel.load_hdf(single_starmodel_file)
            binary_starmodel = StarModel.load_hdf(binary_starmodel_file)
            triple_starmodel = StarModel.load_hdf(triple_starmodel_file)
        except Exception as e:
            print(e)
            raise RuntimeError('Cannot load StarModels.  ' +
                               'Please run `starfit --all {}`.'.format(folder))

        # Create (or load) TransitSignal
        if os.path.exists(trsig_file):
            logging.info('Loading transit signal from {}...'.format(trsig_file))
            with open(trsig_file, 'rb') as f:
                trsig = pickle.load(f)
        else:
            try:
                photfile = fullpath(config['photfile'])
            except KeyError:
                raise AttributeError('If transit pickle file (trsig.pkl) ' +
                                     'not present, "photfile" must be' +
                                     'defined.')

            trsig = TransitSignal.from_ascii(photfile, P=period, name=name)
            if not trsig.hasMCMC or refit_trap:
                logging.info('Fitting transitsignal with MCMC...')
                trsig.MCMC()
                trsig.save(trsig_file)

        # Create (or load) PopulationSet
        do_only = DEFAULT_MODELS
        if os.path.exists(popset_file):
            if recalc:
                os.remove(popset_file)
            else:
                with pd.HDFStore(popset_file) as store:
                    do_only = [m for m in DEFAULT_MODELS if m not in store]

        # Check that properties of saved population match requested
        try:
            popset = PopulationSet.load_hdf(popset_file)
            for pop in popset.poplist:
                if pop.cadence != cadence:
                    raise ValueError('Requested cadence ({}) '.format(cadence) +
                                    'does not match stored {})! Set recalc=True.'.format(pop.cadence))
        except:
            raise

        if do_only:
            logging.info('Generating {} models for PopulationSet...'.format(do_only))
        else:
            logging.info('Populations ({}) already generated.'.format(DEFAULT_MODELS))

        popset = PopulationSet(period=period, cadence=cadence,
                               mags=single_starmodel.mags,
                               ra=ra, dec=dec,
                               trilegal_filename=starfield_file, # Maybe change parameter name?
                               starmodel=single_starmodel,
                               binary_starmodel=binary_starmodel,
                               triple_starmodel=triple_starmodel,
                               rprs=rprs, do_only=do_only,
                               savefile=popset_file, **kwargs)


        fpp = cls(trsig, popset, folder=folder)


        #############
        # Apply constraints

        # Exclusion radius
        maxrad = float(config['constraints']['maxrad'])
        fpp.set_maxrad(maxrad)
        if 'secthresh' in config['constraints']:
            secthresh = float(config['constraints']['secthresh'])
            if not np.isnan(secthresh):
                fpp.apply_secthresh(secthresh)

        # Odd-even constraint
        diff = 3 * np.max(trsig.depthfit[1])
        fpp.constrain_oddeven(diff)

        #apply contrast curve constraints if present
        if 'ccfiles' in config['constraints']:
            ccfiles = config['constraints']['ccfiles']
            if isinstance(ccfiles, string_types):
                ccfiles = [ccfiles]
            for ccfile in ccfiles:
                if not os.path.isabs(ccfile):
                    ccfile = os.path.join(folder, ccfile)
                m = re.search('(\w+)_(\w+)\.cc',os.path.basename(ccfile))
                if not m:
                    logging.warning('Invalid CC filename ({}); '.format(ccfile) +
                                     'skipping.')
                    continue
                else:
                    band = m.group(2)
                    inst = m.group(1)
                    name = '{} {}-band'.format(inst, band)
                    cc = ContrastCurveFromFile(ccfile, band, name=name)
                    fpp.apply_cc(cc)

        #apply "velocity contrast curve" if present
        if 'vcc' in config['constraints']:
            dv = float(config['constraints']['vcc'][0])
            dmag = float(config['constraints']['vcc'][1])
            vcc = VelocityContrastCurve(dv, dmag)
            fpp.apply_vcc(vcc)

        return fpp