Instruction:
How would you explain what the following Python 3 function does
def run_checks(self, **kwargs):

        # make sure all constraints have been run
        changed_params = self.run_delayed_constraints()

        hier = self.hierarchy
        if hier is None:
            return True, ''
        for component in hier.get_stars():
            kind = hier.get_kind_of(component)
            comp_ps = self.get_component(component)

            if not len(comp_ps):
                return False, "component '{}' in the hierarchy is not in the bundle".format(component)

            parent = hier.get_parent_of(component)
            parent_ps = self.get_component(parent)
            if kind in ['star']:
                # ignore the single star case
                if parent:
                    # contact systems MUST by synchronous
                    if hier.is_contact_binary(component):
                        if self.get_value(qualifier='syncpar', component=component, context='component', **kwargs) != 1.0:
                            return False,\
                                'contact binaries must by synchronous, but syncpar@{}!=1'.format(component)

                        if self.get_value(qualifier='ecc', component=parent, context='component', **kwargs) != 0.0:
                            return False,\
                                'contact binaries must by circular, but ecc@{}!=0'.format(component)

                        if self.get_value(qualifier='pitch', component=component, context='component', **kwargs) != 0.0:
                            return False,\
                                'contact binaries must be aligned, but pitch@{}!=0'.format(component)

                        if self.get_value(qualifier='yaw', component=component, context='component', **kwargs) != 0.0:
                            return False,\
                                'contact binaries must be aligned, but yaw@{}!=0'.format(component)

                    # MUST NOT be overflowing at PERIASTRON (d=1-ecc, etheta=0)

                    requiv = comp_ps.get_value('requiv', unit=u.solRad, **kwargs)
                    requiv_max = comp_ps.get_value('requiv_max', unit=u.solRad, **kwargs)

                    if hier.is_contact_binary(component):
                        if np.isnan(requiv) or requiv > requiv_max:
                            return False,\
                                '{} is overflowing at L2/L3 (requiv={}, requiv_max={})'.format(component, requiv, requiv_max)

                        requiv_min = comp_ps.get_value('requiv_min')

                        if np.isnan(requiv) or requiv <= requiv_min:
                            return False,\
                                 '{} is underflowing at L1 and not a contact system (requiv={}, requiv_min={})'.format(component, requiv, requiv_min)
                        elif requiv <= requiv_min * 1.001:
                            return False,\
                                'requiv@{} is too close to requiv_min (within 0.1% of critical).  Use detached/semidetached model instead.'.format(component)

                    else:
                        if requiv > requiv_max:
                            return False,\
                                '{} is overflowing at periastron (requiv={}, requiv_max={})'.format(component, requiv, requiv_max)

            else:
                raise NotImplementedError("checks not implemented for type '{}'".format(kind))

        # we also need to make sure that stars don't overlap each other
        # so we'll check for each pair of stars (see issue #70 on github)
        # TODO: rewrite overlap checks
        for orbitref in []: #hier.get_orbits():
            if len(hier.get_children_of(orbitref)) == 2:
                q = self.get_value(qualifier='q', component=orbitref, context='component', **kwargs)
                ecc = self.get_value(qualifier='ecc', component=orbitref, context='component', **kwargs)

                starrefs = hier.get_children_of(orbitref)
                if hier.get_kind_of(starrefs[0]) != 'star' or hier.get_kind_of(starrefs[1]) != 'star':
                    # print "***", hier.get_kind_of(starrefs[0]), hier.get_kind_of(starrefs[1])
                    continue
                if self.get_value(qualifier='pitch', component=starrefs[0])!=0.0 or \
                        self.get_value(qualifier='pitch', component=starrefs[1])!=0.0 or \
                        self.get_value(qualifier='yaw', component=starrefs[0])!=0.0 or \
                        self.get_value(qualifier='yaw', component=starrefs[1])!=0.0:

                    # we cannot run this test for misaligned cases
                   continue

                comp0 = hier.get_primary_or_secondary(starrefs[0], return_ind=True)
                comp1 = hier.get_primary_or_secondary(starrefs[1], return_ind=True)
                q0 = roche.q_for_component(q, comp0)
                q1 = roche.q_for_component(q, comp1)

                F0 = self.get_value(qualifier='syncpar', component=starrefs[0], context='component', **kwargs)
                F1 = self.get_value(qualifier='syncpar', component=starrefs[1], context='component', **kwargs)

                pot0 = self.get_value(qualifier='pot', component=starrefs[0], context='component', **kwargs)
                pot0 = roche.pot_for_component(pot0, q0, comp0)

                pot1 = self.get_value(qualifier='pot', component=starrefs[1], context='component', **kwargs)
                pot1 = roche.pot_for_component(pot1, q1, comp1)

                xrange0 = libphoebe.roche_xrange(q0, F0, 1.0-ecc, pot0+1e-6, choice=0)
                xrange1 = libphoebe.roche_xrange(q1, F1, 1.0-ecc, pot1+1e-6, choice=0)

                if xrange0[1]+xrange1[1] > 1.0-ecc:
                    return False,\
                        'components in {} are overlapping at periastron (change ecc@{}, syncpar@{}, or syncpar@{}).'.format(orbitref, orbitref, starrefs[0], starrefs[1])

        # check to make sure passband supports the selected atm
        for pbparam in self.filter(qualifier='passband').to_list():
            pb = pbparam.get_value()
            pbatms = _pbtable[pb]['atms']
            # NOTE: atms are not attached to datasets, but per-compute and per-component
            for atmparam in self.filter(qualifier='atm', kind='phoebe').to_list():
                atm = atmparam.get_value()
                if atm not in pbatms:
                    return False, "'{}' passband ({}) does not support atm='{}' ({}).".format(pb, pbparam.twig, atm, atmparam.twig)

        # check length of ld_coeffs vs ld_func and ld_func vs atm
        def ld_coeffs_len(ld_func, ld_coeffs):
            # current choices for ld_func are:
            # ['interp', 'uniform', 'linear', 'logarithmic', 'quadratic', 'square_root', 'power', 'claret', 'hillen', 'prsa']
            if ld_func == 'interp':
                return True,
            elif ld_func in ['linear'] and len(ld_coeffs)==1:
                return True,
            elif ld_func in ['logarithmic', 'square_root', 'quadratic'] and len(ld_coeffs)==2:
                return True,
            elif ld_func in ['power'] and len(ld_coeffs)==4:
                return True,
            else:
                return False, "ld_coeffs={} wrong length for ld_func='{}'.".format(ld_coeffs, ld_func)

        for component in self.hierarchy.get_stars():
            # first check ld_coeffs_bol vs ld_func_bol
            ld_func = str(self.get_value(qualifier='ld_func_bol', component=component, context='component', check_visible=False, **kwargs))
            ld_coeffs = np.asarray(self.get_value(qualifier='ld_coeffs_bol', component=component, context='component', check_visible=False, **kwargs))
            check = ld_coeffs_len(ld_func, ld_coeffs)
            if not check[0]:
                return check

            if ld_func != 'interp':
                check = libphoebe.ld_check(ld_func, ld_coeffs)
                if not check:
                    return False, 'ld_coeffs_bol={} not compatible for ld_func_bol=\'{}\'.'.format(ld_coeffs, ld_func)

            for dataset in self.datasets:
                if dataset=='_default' or self.get_dataset(dataset=dataset, kind='*dep').kind not in ['lc_dep', 'rv_dep']:
                    continue
                ld_func = str(self.get_value(qualifier='ld_func', dataset=dataset, component=component, context='dataset', **kwargs))
                ld_coeffs = np.asarray(self.get_value(qualifier='ld_coeffs', dataset=dataset, component=component, context='dataset', check_visible=False, **kwargs))
                if ld_coeffs is not None:
                    check = ld_coeffs_len(ld_func, ld_coeffs)
                    if not check[0]:
                        return check

                if ld_func != 'interp':
                    check = libphoebe.ld_check(ld_func, ld_coeffs)
                    if not check:
                        return False, 'ld_coeffs={} not compatible for ld_func=\'{}\'.'.format(ld_coeffs, ld_func)

                if ld_func=='interp':
                    for compute in kwargs.get('computes', self.computes):
                        atm = self.get_value(qualifier='atm', component=component, compute=compute, context='compute', **kwargs)
                        if atm != 'ck2004':
                            return False, "ld_func='interp' only supported by atm='ck2004'.  Either change atm@{} or ld_func@{}@{}".format(component, component, dataset)

        # mesh-consistency checks
        for compute in self.computes:
            mesh_methods = [p.get_value() for p in self.filter(qualifier='mesh_method', compute=compute, force_ps=True).to_list()]
            if 'wd' in mesh_methods:
                if len(set(mesh_methods)) > 1:
                    return False, "all (or none) components must use mesh_method='wd'."

        #### WARNINGS ONLY ####
        # let's check teff vs gravb_bol and irrad_frac_refl_bol
        for component in self.hierarchy.get_stars():
            teff = self.get_value(qualifier='teff', component=component, context='component', unit=u.K, **kwargs)
            gravb_bol = self.get_value(qualifier='gravb_bol', component=component, context='component', **kwargs)

            if teff >= 8000. and gravb_bol < 0.9:
                return None, "'{}' probably has a radiative atm (teff={:.0f}K>8000K), for which gravb_bol=1.00 might be a better approx than gravb_bol={:.2f}.".format(component, teff, gravb_bol)
            elif teff <= 6600. and gravb_bol >= 0.9:
                return None, "'{}' probably has a convective atm (teff={:.0f}K<6600K), for which gravb_bol=0.32 might be a better approx than gravb_bol={:.2f}.".format(component, teff, gravb_bol)
            elif gravb_bol < 0.32 or gravb_bol > 1.00:
                return None, "'{}' has intermittent temperature (6600K<teff={:.0f}K<8000K), gravb_bol might be better between 0.32-1.00 than gravb_bol={:.2f}.".format(component, teff, gravb_bol)

        for component in self.hierarchy.get_stars():
            teff = self.get_value(qualifier='teff', component=component, context='component', unit=u.K, **kwargs)
            irrad_frac_refl_bol = self.get_value(qualifier='irrad_frac_refl_bol', component=component, context='component', **kwargs)

            if teff >= 8000. and irrad_frac_refl_bol < 0.8:
                return None, "'{}' probably has a radiative atm (teff={:.0f}K>8000K), for which irrad_frac_refl_bol=1.00 might be a better approx than irrad_frac_refl_bol={:.2f}.".format(component, teff, irrad_frac_refl_bol)
            elif teff <= 6600. and irrad_frac_refl_bol >= 0.75:
                return None, "'{}' probably has a convective atm (teff={:.0f}K<6600K), for which irrad_frac_refl_bol=0.6 might be a better approx than irrad_frac_refl_bol={:.2f}.".format(component, teff, irrad_frac_refl_bol)
            elif irrad_frac_refl_bol < 0.6:
                return None, "'{}' has intermittent temperature (6600K<teff={:.0f}K<8000K), irrad_frac_refl_bol might be better between 0.6-1.00 than irrad_frac_refl_bol={:.2f}.".format(component, teff, irrad_frac_refl_bol)

        # TODO: add other checks
        # - make sure all ETV components are legal
        # - check for conflict between dynamics_method and mesh_method (?)

        # we've survived all tests
        return True, ''

Response: Checks to see if the system is expected to be computable.


Instruction:
Create a Python 3 function for
adding a new feature to a component in the system.

Response:
def add_feature(self, kind, component=None, **kwargs):
        """
        Add a new feature (spot, etc) to a component in the system.  If not
        provided, 'feature' (the name of the new feature) will be created
        for you and can be accessed by the 'feature' attribute of the returned
        ParameterSet

        >>> b.add_feature(feature.spot, component='mystar')

        or

        >>> b.add_feature('spot', 'mystar', colat=90)

        Available kinds include:
            * :func:`phoebe.parameters.feature.spot`

        :parameter kind: function to call that returns a
            ParameterSet or list of parameters.  This must either be
            a callable function that accepts nothing but default values,
            or the name of a function (as a string) that can be found in the
            :mod:`phoebe.parameters.feature` module (ie. 'spot')
        :type kind: str or callable
        :parameter str component: name of the component to attach the feature
        :parameter str feature: (optional) name of the newly-created feature
        :parameter **kwargs: default value for any of the newly-created
            parameters
        :return: :class:`phoebe.parameters.parameters.ParameterSet` of
            all parameters that have been added
        :raises NotImplementedError: if required constraint is not implemented
        """
        func = _get_add_func(_feature, kind)

        if kwargs.get('feature', False) is None:
            # then we want to apply the default below, so let's pop for now
            _ = kwargs.pop('feature')

        kwargs.setdefault('feature',
                          self._default_label(func.func_name,
                                              **{'context': 'feature',
                                                 'kind': func.func_name}))

        self._check_label(kwargs['feature'])

        if component is None:
            stars = self.hierarchy.get_meshables()
            if len(stars) == 1:
                component = stars[0]
            else:
                raise ValueError("must provide component")

        if component not in self.components:
            raise ValueError('component not recognized')

        component_kind = self.filter(component=component, context='component').kind
        if not _feature._component_allowed_for_feature(func.func_name, component_kind):
            raise ValueError("{} does not support component with kind {}".format(func.func_name, component_kind))

        params, constraints = func(**kwargs)

        metawargs = {'context': 'feature',
                     'component': component,
                     'feature': kwargs['feature'],
                     'kind': func.func_name}

        self._attach_params(params, **metawargs)

        redo_kwargs = deepcopy(kwargs)
        redo_kwargs['func'] = func.func_name
        self._add_history(redo_func='add_feature',
                          redo_kwargs=redo_kwargs,
                          undo_func='remove_feature',
                          undo_kwargs={'feature': kwargs['feature']})

        for constraint in constraints:
            self.add_constraint(*constraint)

        #return params
        # NOTE: we need to call get_ in order to make sure all metawargs are applied
        return self.get_feature(**metawargs)


Instruction:
Make a summary of the following Python 3 code
def get_feature(self, feature=None, **kwargs):
        if feature is not None:
            kwargs['feature'] = feature
        kwargs['context'] = 'feature'
        return self.filter(**kwargs)

Response: Filter in the proerty context


Instruction:
Can you create a Python 3 function that
removes a feature from the bundle.

Response:
def remove_feature(self, feature=None, **kwargs):
        """
        [NOT IMPLEMENTED]

        Remove a 'feature' from the bundle

        :raises NotImplementedError: because this isn't implemented yet
        """
        self._kwargs_checks(kwargs)

        # Let's avoid deleting ALL features from the matching contexts
        if feature is None and not len(kwargs.items()):
            raise ValueError("must provide some value to filter for features")

        kwargs['feature'] = feature

        # Let's avoid the possibility of deleting a single parameter
        kwargs['qualifier'] = None

        # Let's also avoid the possibility of accidentally deleting system
        # parameters, etc
        kwargs.setdefault('context', ['feature'])

        self.remove_parameters_all(**kwargs)

        self._add_history(redo_func='remove_feature',
                          redo_kwargs=kwargs,
                          undo_func=None,
                          undo_kwargs={})

        return


Instruction:
Make a summary of the following Python 3 code
def rename_feature(self, old_feature, new_feature):
        # TODO: raise error if old_feature not found?

        self._check_label(new_feature)
        self._rename_label('feature', old_feature, new_feature)

Response:
Change the label of a feature attached to the Bundle
           .


Instruction:
How would you explain what the following Python 3 function does
def add_spot(self, component=None, feature=None, **kwargs):
        if component is None:
            if len(self.hierarchy.get_stars())==1:
                component = self.hierarchy.get_stars()[0]
            else:
                raise ValueError("must provide component for spot")

        kwargs.setdefault('component', component)
        kwargs.setdefault('feature', feature)
        return self.add_feature('spot', **kwargs)

Response: Shortcut to add_feature but with kind = spot


Instruction:
Given the following Python 3 function, write the documentation
def remove_spot(self, feature=None, **kwargs):
        kwargs.setdefault('kind', 'spot')
        return self.remove_feature(feature, **kwargs)

Response: Shortcut to remove_feature but with kind = spot


Instruction:
Can you tell what is the following Python 3 function doing
def add_component(self, kind, **kwargs):

        func = _get_add_func(component, kind)

        if kwargs.get('component', False) is None:
            # then we want to apply the default below, so let's pop for now
            _ = kwargs.pop('component')

        kwargs.setdefault('component',
                          self._default_label(func.func_name,
                                              **{'context': 'component',
                                                 'kind': func.func_name}))

        if kwargs.pop('check_label', True):
            self._check_label(kwargs['component'])

        params, constraints = func(**kwargs)

        metawargs = {'context': 'component',
                     'component': kwargs['component'],
                     'kind': func.func_name}

        self._attach_params(params, **metawargs)

        redo_kwargs = deepcopy(kwargs)
        redo_kwargs['func'] = func.func_name
        self._add_history(redo_func='add_component',
                          redo_kwargs=redo_kwargs,
                          undo_func='remove_component',
                          undo_kwargs={'component': kwargs['component']})

        for constraint in constraints:
            self.add_constraint(*constraint)

        # since we've already processed (so that we can get the new qualifiers),
        # we'll only raise a warning
        self._kwargs_checks(kwargs, warning_only=True)

        # return params
        return self.get_component(**metawargs)

Response: Add a new component to the system.


Instruction:
Write a Python 3 script for
filtering in the component context

Response:
def get_component(self, component=None, **kwargs):
        """
        Filter in the 'component' context

        :parameter str component: name of the component (optional)
        :parameter **kwargs: any other tags to do the filter
            (except component or context)
        :return: :class:`phoebe.parameters.parameters.ParameterSet`
        """
        if component is not None:
            kwargs['component'] = component
        kwargs['context'] = 'component'
        return self.filter(**kwargs)


Instruction:
Given the following Python 3 function, write the documentation
def remove_component(self, component, **kwargs):
        # NOTE: run_checks will check if an entry is in the hierarchy but has no parameters
        kwargs['component'] = component
        # NOTE: we do not remove from 'model' by default
        kwargs['context'] = ['component', 'constraint', 'dataset', 'compute']
        self.remove_parameters_all(**kwargs)

Response: Removes a component from the bundle


Instruction:
Write a Python 3 script for
changing the label of a component attached to the Bundle .

Response:
def rename_component(self, old_component, new_component):
        """
        Change the label of a component attached to the Bundle

        :parameter str old_component: the current name of the component
            (must exist)
        :parameter str new_component: the desired new name of the component
            (must not exist)
        :return: None
        :raises ValueError: if the new_component is forbidden
        """
        # TODO: raise error if old_component not found?

        # even though _rename_tag will call _check_label again, we should
        # do it first so that we can raise any errors BEFORE we start messing
        # with the hierarchy
        self._check_label(new_component)
        # changing hierarchy must be called first since it needs to access
        # the kind of old_component
        if len([c for c in self.components if new_component in c]):
            logger.warning("hierarchy may not update correctly with new component")
        self.hierarchy.rename_component(old_component, new_component)

        self._rename_label('component', old_component, new_component)

        self._handle_dataset_selectparams()


Instruction:
Here you have a function in Python 3, explain what it does
def add_orbit(self, component=None, **kwargs):
        kwargs.setdefault('component', component)
        return self.add_component('orbit', **kwargs)

Response: Shortcut to add_component but with kind = orbit


Instruction:
Can you tell what is the following Python 3 function doing
def remove_orbit(self, component=None, **kwargs):
        kwargs.setdefault('kind', 'orbit')
        return self.remove_component(component, **kwargs)

Response: Shortcut to remove_component but with kind = orbit


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_star(self, component=None, **kwargs):
        kwargs.setdefault('kind', 'star')
        return self.get_component(component, **kwargs)

Response: Shortcut to get_component but with kind = star


Instruction:
Explain what the following Python 3 code does
def add_envelope(self, component=None, **kwargs):
        kwargs.setdefault('component', component)
        return self.add_component('envelope', **kwargs)

Response: Shortcut to add_envelope but with kind = envelope


Instruction:
Create a Python 3 function to
return the ephemeris of a given component.

Response:
def get_ephemeris(self, component=None, t0='t0_supconj', **kwargs):
        """
        Get the ephemeris of a component (star or orbit)

        :parameter str component: name of the component.  If not given,
            component will default to the top-most level of the current
            hierarchy
        :parameter t0: qualifier of the parameter to be used for t0
        :type t0: str
        :parameter **kwargs: any value passed through kwargs will override the
            ephemeris retrieved by component (ie period, t0, dpdt).
            Note: be careful about units - input values will not be converted.
        :return: dictionary containing period, t0 (t0_supconj if orbit),
            dpdt (as applicable)
        :rtype: dict
        """

        if component is None:
            component = self.hierarchy.get_top()

        if kwargs.get('shift', False):
            raise ValueError("support for phshift was removed as of 2.1.  Please pass t0 instead.")

        ret = {}

        ps = self.filter(component=component, context='component')

        if ps.kind in ['orbit']:
            ret['period'] = ps.get_value(qualifier='period', unit=u.d)
            if isinstance(t0, str):
                ret['t0'] = ps.get_value(qualifier=t0, unit=u.d)
            elif isinstance(t0, float) or isinstance(t0, int):
                ret['t0'] = t0
            else:
                raise ValueError("t0 must be string (qualifier) or float")
            ret['dpdt'] = ps.get_value(qualifier='dpdt', unit=u.d/u.d)
        elif ps.kind in ['star']:
            # TODO: consider renaming period to prot
            ret['period'] = ps.get_value(qualifier='period', unit=u.d)
        else:
            raise NotImplementedError

        for k,v in kwargs.items():
            ret[k] = v

        return ret


Instruction:
Can you create a Python 3 function that
converts a time to phases

Response:
def to_phase(self, time, component=None, t0='t0_supconj', **kwargs):
        """
        Get the phase(s) of a time(s) for a given ephemeris

        :parameter time: time to convert to phases (should be in same system
            as t0s)
        :type time: float, list, or array
        :parameter t0: qualifier of the parameter to be used for t0
        :type t0: str
        :parameter str component: component for which to get the ephemeris.
            If not given, component will default to the top-most level of the
            current hierarchy
        :parameter **kwargs: any value passed through kwargs will override the
            ephemeris retrieved by component (ie period, t0, dpdt).
            Note: be careful about units - input values will not be converted.
        :return: phase (float) or phases (array)
        """

        if kwargs.get('shift', False):
            raise ValueError("support for phshift was removed as of 2.1.  Please pass t0 instead.")

        ephem = self.get_ephemeris(component=component, t0=t0, **kwargs)

        if isinstance(time, list):
            time = np.array(time)
        elif isinstance(time, Parameter):
            time = time.get_value(u.d)
        elif isinstance(time, str):
            time = self.get_value(time, u.d)

        t0 = ephem.get('t0', 0.0)
        period = ephem.get('period', 1.0)
        dpdt = ephem.get('dpdt', 0.0)

        if dpdt != 0:
            phase = np.mod(1./dpdt * np.log(period + dpdt*(time-t0)), 1.0)
        else:
            phase = np.mod((time-t0)/period, 1.0)

        if isinstance(phase, float):
            if phase > 0.5:
                phase -= 1
        else:
            # then should be an array
            phase[phase > 0.5] -= 1

        return phase


Instruction:
Implement a Python 3 function for
converting the ephemeris time to a given phase.

Response:
def to_time(self, phase, component=None, t0='t0_supconj', **kwargs):
        """
        Get the time(s) of a phase(s) for a given ephemeris

        :parameter phase: phase to convert to times (should be in
            same system as t0s)
        :type phase: float, list, or array
    `   :parameter str component: component for which to get the ephemeris.
            If not given, component will default to the top-most level of the
            current hierarchy
        :parameter t0: qualifier of the parameter to be used for t0
        :type t0: str
        :parameter **kwargs: any value passed through kwargs will override the
            ephemeris retrieved by component (ie period, t0, dpdt).
            Note: be careful about units - input values will not be converted.
        :return: time (float) or times (array)
        """

        if kwargs.get('shift', False):
            raise ValueError("support for phshift was removed as of 2.1.  Please pass t0 instead.")

        ephem = self.get_ephemeris(component=component, t0=t0, **kwargs)

        if isinstance(phase, list):
            phase = np.array(phase)

        t0 = ephem.get('t0', 0.0)
        period = ephem.get('period', 1.0)
        dpdt = ephem.get('dpdt', 0.0)

        # if changing this, also see parameters.constraint.time_ephem
        if dpdt != 0:
            time = t0 + 1./dpdt*(np.exp(dpdt*(phase))-period)
        else:
            time = t0 + (phase)*period

        return time


Instruction:
Explain what the following Python 3 code does
def add_dataset(self, kind, component=None, **kwargs):

        sing_plural = {}
        sing_plural['time'] = 'times'
        sing_plural['flux'] = 'fluxes'
        sing_plural['sigma'] = 'sigmas'
        sing_plural['rv'] = 'rvs'

        func = _get_add_func(_dataset, kind.lower()
                             if isinstance(kind, str)
                             else kind)

        kwargs.setdefault('dataset',
                          self._default_label(func.func_name,
                                              **{'context': 'dataset',
                                                 'kind': func.func_name}))

        if kwargs.pop('check_label', True):
            self._check_label(kwargs['dataset'])

        kind = func.func_name

        # Let's remember if the user passed components or if they were automatically assigned
        user_provided_components = component or kwargs.get('components', False)

        if kind == 'lc':
            allowed_components = [None]
            default_components = allowed_components
        elif kind in ['rv', 'orb']:
            allowed_components = self.hierarchy.get_stars() # + self.hierarchy.get_orbits()
            default_components = self.hierarchy.get_stars()
            # TODO: how are we going to handle overcontacts dynamical vs flux-weighted
        elif kind in ['mesh']:
            # allowed_components = self.hierarchy.get_meshables()
            allowed_components = [None]
            # allowed_components = self.hierarchy.get_stars()
            # TODO: how will this work when changing hierarchy to add/remove the common envelope?
            default_components = allowed_components
        elif kind in ['etv']:
            hier = self.hierarchy
            stars = hier.get_stars()
            # only include components in which the sibling is also a star that
            # means that the companion in a triple cannot be timed, because how
            # do we know who it's eclipsing?
            allowed_components = [s for s in stars if hier.get_sibling_of(s) in stars]
            default_components = allowed_components
        elif kind in ['lp']:
            # TODO: need to think about what this should be for contacts...
            allowed_components = self.hierarchy.get_stars() + self.hierarchy.get_orbits()
            default_components = [self.hierarchy.get_top()]

        else:
            allowed_components = [None]
            default_components = [None]

        # Let's handle the case where the user accidentally sends components
        # instead of component
        if kwargs.get('components', None) and component is None:
            logger.warning("assuming you meant 'component' instead of 'components'")
            components = kwargs.pop('components')
        else:
            components = component

        if isinstance(components, str):
            components = [components]
        elif hasattr(components, '__iter__'):
            components = components
        elif components is None:
            components = default_components
        else:
            raise NotImplementedError

        # Let's handle the case where the user accidentally sends singular
        # instead of plural (since we used to have this)
        # TODO: use parameter._singular_to_plural?
        for singular, plural in sing_plural.items():
            if kwargs.get(singular, None) is not None and kwargs.get(plural, None) is None:
                logger.warning("assuming you meant '{}' instead of '{}'".format(plural, singular))
                kwargs[plural] = kwargs.pop(singular)

        if not np.all([component in allowed_components
                       for component in components]):
            raise ValueError("'{}' not a recognized/allowable component".format(component))

        obs_metawargs = {'context': 'dataset',
                         'kind': kind,
                         'dataset': kwargs['dataset']}

        if kind in ['lp']:
            # then times needs to be passed now to duplicate and tag the Parameters
            # correctly
            obs_kwargs = {'times': kwargs.pop('times', [])}
        else:
            obs_kwargs = {}

        obs_params, constraints = func(**obs_kwargs)
        self._attach_params(obs_params, **obs_metawargs)

        for constraint in constraints:
            # TODO: tricky thing here will be copying the constraints
            self.add_constraint(*constraint)

        dep_func = _get_add_func(_dataset, "{}_dep".format(kind))
        dep_metawargs = {'context': 'dataset',
                         'kind': '{}_dep'.format(kind),
                         'dataset': kwargs['dataset']}
        dep_params = dep_func()
        self._attach_params(dep_params, **dep_metawargs)

        # Now we need to apply any kwargs sent by the user.  There are a few
        # scenarios (and each kwargs could fall into different ones):
        # times = [0,1,2]
        #    in this case, we want to apply time across all of the components that
        #    are applicable for this dataset kind AND to _default so that any
        #    future components added to the system are copied appropriately
        # times = [0,1,2], components=['primary', 'secondary']
        #    in this case, we want to apply the value for time across components
        #    but time@_default should remain empty (it will not copy for components
        #    added in the future)
        # times = {'primary': [0,1], 'secondary': [0,1,2]}
        #    here, regardless of the components, we want to apply these to their
        #    individually requested parameters.  We won't touch _default unless
        #    its included in the dictionary

        # this needs to happen before kwargs get applied so that the default
        # values can be overridden by the supplied kwargs
        self._handle_pblum_defaults()
        self._handle_dataset_selectparams()

        for k, v in kwargs.items():
            if isinstance(v, dict):
                for component, value in v.items():
                    logger.debug("setting value of dataset parameter: qualifier={}, dataset={}, component={}, value={}".format(k, kwargs['dataset'], component, value))
                    try:
                        self.set_value_all(qualifier=k,
                                           dataset=kwargs['dataset'],
                                           component=component,
                                           value=value,
                                           check_visible=False,
                                           ignore_none=True)
                    except:
                        self.remove_dataset(dataset=kwargs['dataset'])
                        raise ValueError("could not set value for {}={}, dataset has not been added".format(k, value))

            elif k in ['dataset']:
                pass
            else:
                # for dataset kinds that include passband dependent AND
                # independent parameters, we need to carefully default on
                # what component to use when passing the defaults
                if kind in ['rv', 'lp'] and k in ['ld_func', 'ld_coeffs',
                                                  'passband', 'intens_weighting',
                                                  'profile_rest', 'profile_func', 'profile_sv']:
                    # passband-dependent (ie lc_dep) parameters do not have
                    # assigned components
                    components_ = None
                elif components == [None]:
                    components_ = None
                elif user_provided_components:
                    components_ = components
                else:
                    components_ = components+['_default']

                logger.debug("setting value of dataset parameter: qualifier={}, dataset={}, component={}, value={}".format(k, kwargs['dataset'], components_, v))
                try:
                    self.set_value_all(qualifier=k,
                                       dataset=kwargs['dataset'],
                                       component=components_,
                                       value=v,
                                       check_visible=False,
                                       ignore_none=True)
                except:
                    self.remove_dataset(dataset=kwargs['dataset'])
                    raise ValueError("could not set value for {}={}, dataset has not been added".format(k, v))

        redo_kwargs = deepcopy({k:v if not isinstance(v, nparray.ndarray) else v.to_json() for k,v in kwargs.items()})
        redo_kwargs['func'] = func.func_name
        self._add_history(redo_func='add_dataset',
                          redo_kwargs=redo_kwargs,
                          undo_func='remove_dataset',
                          undo_kwargs={'dataset': kwargs['dataset']})

        # since we've already processed (so that we can get the new qualifiers),
        # we'll only raise a warning
        self._kwargs_checks(kwargs, warning_only=True)

        return self.filter(dataset=kwargs['dataset'])

Response: Add a new dataset to the bundle.


Instruction:
How would you implement a function in Python 3 that
filters in the dataset context

Response:
def get_dataset(self, dataset=None, **kwargs):
        """
        Filter in the 'dataset' context

        :parameter str dataset: name of the dataset (optional)
        :parameter **kwargs: any other tags to do the filter
            (except dataset or context)
        :return: :class:`phoebe.parameters.parameters.ParameterSet`
        """
        if dataset is not None:
            kwargs['dataset'] = dataset

        kwargs['context'] = 'dataset'
        if 'kind' in kwargs.keys():
            # since we switched how dataset kinds are named, let's just
            # automatically handle switching to lowercase
            kwargs['kind'] = kwargs['kind'].lower()
        return self.filter(**kwargs)


Instruction:
Implement a function in Python 3 to
remove a dataset from the Bundle. This removes all matching Parameters from the dataset, model, and constraint contexts (by default if the context tag is not provided). You must provide some sort of filter or this will raise an Error (so that all Parameters are not accidentally removed). :parameter str dataset: name of the dataset :parameter **kwargs: any other tags to do the filter (except qualifier and dataset) :raises ValueError: if no filter is provided

Response:
def remove_dataset(self, dataset=None, **kwargs):
        """ Remove a dataset from the Bundle.

        This removes all matching Parameters from the dataset, model, and
        constraint contexts (by default if the context tag is not provided).

        You must provide some sort of filter or this will raise an Error (so
        that all Parameters are not accidentally removed).

        :parameter str dataset: name of the dataset
        :parameter **kwargs: any other tags to do the filter (except qualifier
            and dataset)
        :raises ValueError: if no filter is provided
        """

        self._kwargs_checks(kwargs)

        # Let's avoid deleting ALL parameters from the matching contexts
        if dataset is None and not len(kwargs.items()):
            raise ValueError("must provide some value to filter for datasets")

        # let's handle deps if kind was passed
        kind = kwargs.get('kind', None)

        if kind is not None:
            if isinstance(kind, str):
                kind = [kind]
            kind_deps = []
            for kind_i in kind:
                dep = '{}_dep'.format(kind_i)
                if dep not in kind:
                    kind_deps.append(dep)
            kind = kind + kind_deps
        kwargs['kind'] = kind

        if dataset is None:
            # then let's find the list of datasets that match the filter,
            # we'll then use dataset to do the removing.  This avoids leaving
            # pararameters behind that don't specifically match the filter
            # (ie if kind is passed as 'rv' we still want to remove parameters
            # with datasets that are RVs but belong to a different kind in
            # another context like compute)
            dataset = self.filter(**kwargs).datasets
            kwargs['kind'] = None

        kwargs['dataset'] = dataset
        # Let's avoid the possibility of deleting a single parameter
        kwargs['qualifier'] = None
        # Let's also avoid the possibility of accidentally deleting system
        # parameters, etc
        kwargs.setdefault('context', ['dataset', 'model', 'constraint', 'compute'])

        # ps = self.filter(**kwargs)
        # logger.info('removing {} parameters (this is not undoable)'.\
        #             format(len(ps)))

        # print "*** kwargs", kwargs, len(ps)
        self.remove_parameters_all(**kwargs)
        # not really sure why we need to call this twice, but it seems to do
        # the trick
        self.remove_parameters_all(**kwargs)

        self._handle_dataset_selectparams()

        # TODO: check to make sure that trying to undo this
        # will raise an error saying this is not undo-able
        self._add_history(redo_func='remove_dataset',
                          redo_kwargs={'dataset': dataset},
                          undo_func=None,
                          undo_kwargs={})

        return


Instruction:
Write a Python 3 script for
changing the label of a dataset attached to the Bundle

Response:
def rename_dataset(self, old_dataset, new_dataset):
        """
        Change the label of a dataset attached to the Bundle

        :parameter str old_dataset: the current name of the dataset
            (must exist)
        :parameter str new_dataset: the desired new name of the dataset
            (must not exist)
        :return: None
        :raises ValueError: if the new_dataset is forbidden
        """
        # TODO: raise error if old_component not found?

        self._check_label(new_dataset)
        self._rename_label('dataset', old_dataset, new_dataset)
        self._handle_dataset_selectparams()


Instruction:
Make a summary of the following Python 3 code
def enable_dataset(self, dataset=None, **kwargs):
        kwargs['context'] = 'compute'
        kwargs['dataset'] = dataset
        kwargs['qualifier'] = 'enabled'
        self.set_value_all(value=True, **kwargs)

        self._add_history(redo_func='enable_dataset',
                          redo_kwargs={'dataset': dataset},
                          undo_func='disable_dataset',
                          undo_kwargs={'dataset': dataset})

        return self.get_dataset(dataset=dataset)

Response:
Enable a 'dataset'.  Datasets that are enabled will be computed
        during :meth:`run_compute` and included in the cost function
        during :meth:`run_fitting`.

        If compute is not provided, the dataset will be enabled across all
        compute options.

        :parameter str dataset: name of the dataset
        :parameter **kwargs: any other tags to do the filter
            (except dataset or context)
        :return: :class:`phoebe.parameters.parameters.ParameterSet`
            of the enabled dataset


Instruction:
Make a summary of the following Python 3 code
def disable_dataset(self, dataset=None, **kwargs):
        kwargs['context'] = 'compute'
        kwargs['dataset'] = dataset
        kwargs['qualifier'] = 'enabled'
        self.set_value_all(value=False, **kwargs)

        self._add_history(redo_func='disable_dataset',
                          redo_kwargs={'dataset': dataset},
                          undo_func='enable_dataset',
                          undo_kwargs={'dataset': dataset})

        return self.get_dataset(dataset=dataset)

Response:
Disable a 'dataset'.  Datasets that are enabled will be computed
        during :meth:`run_compute` and included in the cost function
        during :meth:`run_fitting`.

        If compute is not provided, the dataset will be disabled across all
        compute options.

        :parameter str dataset: name of the dataset
        :parameter **kwargs: any other tags to do the filter
            (except dataset or context)
        :return: :class:`phoebe.parameters.parameters.ParameterSet`
            of the disabled dataset


Instruction:
Write a Python 3 script for
adding a constraint to the current object

Response:
def add_constraint(self, *args, **kwargs):
        """
        TODO: add documentation

        args can be string representation (length 1)
        func and strings to pass to function
        """
        # TODO: be smart enough to take kwargs (especially for undoing a
        # remove_constraint) for kind, value (expression),

        redo_kwargs = deepcopy(kwargs)

        if len(args) == 1 and \
                isinstance(args[0], str) and \
                not _get_add_func(_constraint, args[0],
                                  return_none_if_not_found=True):
            # then only the expression has been passed,
            # we just need to pass it on to constraints.custom

            func = constraint.custom
            func_args = args

        elif len(args) == 2 and \
                all([isinstance(arg, Parameter) or
                     isinstance(arg, ConstraintParameter) for arg in args]):
            # then we have 2 constraint expressions

            func = constraint.custom
            func_args = args

        elif len(args) == 0:
            # then everything is passed through kwargs
            if 'kind' in kwargs.keys():
                func = _get_add_func(_constraint, kwargs['kind'])
            elif 'func' in kwargs.keys():
                func = _get_add_func(_constraint, kwargs['func'])
            elif 'constraint_func' in kwargs.keys():
                func = _get_add_func(_constraint, kwargs['constraint_func'])
            else:
                func = constraint.custom

            func_args = []

            # constraint_param = ConstraintParameter(self, **kwargs)

        else:
            # then we've been passed the function in constraints and its
            # arguments

            func = _get_add_func(_constraint, args[0])
            func_args = args[1:]

        if 'solve_for' in kwargs.keys():
            # solve_for is a twig, we need to pass the parameter
            kwargs['solve_for'] = self.get_parameter(kwargs['solve_for'])

        lhs, rhs, constraint_kwargs = func(self, *func_args, **kwargs)
        # NOTE that any component parameters required have already been
        # created by this point

        constraint_param = ConstraintParameter(self,
                                               qualifier=lhs.qualifier,
                                               component=lhs.component,
                                               dataset=lhs.dataset,
                                               feature=lhs.feature,
                                               kind=lhs.kind,
                                               model=lhs.model,
                                               constraint_func=func.__name__,
                                               constraint_kwargs=constraint_kwargs,
                                               in_solar_units=func.__name__ not in constraint.list_of_constraints_requiring_si,
                                               value=rhs,
                                               default_unit=lhs.default_unit,
                                               description='expression that determines the constraint')

        newly_constrained_param = constraint_param.get_constrained_parameter()
        check_kwargs = {k:v for k,v in newly_constrained_param.meta.items() if k not in ['context', 'twig', 'uniquetwig']}
        check_kwargs['context'] = 'constraint'
        if len(self._bundle.filter(**check_kwargs)):
            raise ValueError("'{}' is already constrained".format(newly_constrained_param.twig))

        metawargs = {'context': 'constraint',
                     'kind': func.func_name}

        params = ParameterSet([constraint_param])
        constraint_param._update_bookkeeping()
        self._attach_params(params, **metawargs)

        redo_kwargs['func'] = func.func_name

        self._add_history(redo_func='add_constraint',
                          redo_kwargs=redo_kwargs,
                          undo_func='remove_constraint',
                          undo_kwargs={'uniqueid': constraint_param.uniqueid})

        # we should run it now to make sure everything is in-sync
        if conf.interactive_constraints:
            self.run_constraint(uniqueid=constraint_param.uniqueid, skip_kwargs_checks=True)
        else:
            self._delayed_constraints.append(constraint_param.uniqueid)

        return params


Instruction:
Write a Python 3 script for
returning a ParameterSet object with the constraint name

Response:
def get_constraint(self, twig=None, **kwargs):
        """
        Filter in the 'constraint' context

        :parameter str constraint: name of the constraint (optional)
        :parameter **kwargs: any other tags to do the filter
            (except constraint or context)
        :return: :class:`phoebe.parameters.parameters.ParameterSet`
        """
        if twig is not None:
            kwargs['twig'] = twig
        kwargs['context'] = 'constraint'
        return self.get(**kwargs)


Instruction:
How would you code a function in Python 3 to
remove a constraint from the bundle

Response:
def remove_constraint(self, twig=None, **kwargs):
        """
        Remove a 'constraint' from the bundle

        :parameter str twig: twig to filter for the constraint
        :parameter **kwargs: any other tags to do the filter
            (except twig or context)
        """
        # let's run delayed constraints first to ensure that we get the same
        # results in interactive and non-interactive modes as well as to make
        # sure we don't have delayed constraints for the constraint we're
        #  about to remove.  This could perhaps be optimized by searching
        #  for this/these constraints and only running/removing those, but
        #  probably isn't worth the savings.
        changed_params = self.run_delayed_constraints()

        kwargs['twig'] = twig
        redo_kwargs = deepcopy(kwargs)

        kwargs['context'] = 'constraint'

        # we'll get the constraint so that we can undo the bookkeeping
        # and also reproduce an undo command
        constraint = self.get_parameter(**kwargs)

        # undo parameter bookkeeping
        constraint._remove_bookkeeping()

        # and finally remove it
        self.remove_parameter(**kwargs)

        undo_kwargs = {k: v for k, v in constraint.to_dict().items()
                       if v is not None and
                       k not in ['uniqueid', 'uniquetwig', 'twig',
                                 'Class', 'context']}
        self._add_history(redo_func='remove_constraint',
                          redo_kwargs=redo_kwargs,
                          undo_func='add_constraint',
                          undo_kwargs=undo_kwargs)


Instruction:
Can you create a Python 3 function that
flips an existing constraint to solve for a different parameter

Response:
def flip_constraint(self, twig=None, solve_for=None, **kwargs):
        """
        Flip an existing constraint to solve for a different parameter

        :parameter str twig: twig to filter the constraint
        :parameter solve_for: twig or actual parameter object of the new
            parameter which this constraint should constraint (solve for).
        :type solve_for: str or :class:`phoebe.parameters.parameters.Parameter
        :parameter **kwargs: any other tags to do the filter
            (except twig or context)

        """
        self._kwargs_checks(kwargs, additional_allowed_keys=['check_nan'])

        kwargs['twig'] = twig
        redo_kwargs = deepcopy(kwargs)
        undo_kwargs = deepcopy(kwargs)

        changed_params = self.run_delayed_constraints()

        param = self.get_constraint(**kwargs)

        if kwargs.pop('check_nan', True) and np.any(np.isnan([p.get_value() for p in param.vars.to_list()])):
            raise ValueError("cannot flip constraint while the value of {} is nan".format([p.twig for p in param.vars.to_list() if np.isnan(p.get_value())]))

        if solve_for is None:
            return param
        if isinstance(solve_for, Parameter):
            solve_for = solve_for.uniquetwig

        redo_kwargs['solve_for'] = solve_for
        undo_kwargs['solve_for'] = param.constrained_parameter.uniquetwig

        logger.info("flipping constraint '{}' to solve for '{}'".format(param.uniquetwig, solve_for))
        param.flip_for(solve_for)

        result = self.run_constraint(uniqueid=param.uniqueid, skip_kwargs_checks=True)

        self._add_history(redo_func='flip_constraint',
                          redo_kwargs=redo_kwargs,
                          undo_func='flip_constraint',
                          undo_kwargs=undo_kwargs)

        return param


Instruction:
Here you have a function in Python 3, explain what it does
def run_constraint(self, twig=None, return_parameter=False, **kwargs):
        if not kwargs.get('skip_kwargs_checks', False):
            self._kwargs_checks(kwargs)

        kwargs['twig'] = twig
        kwargs['context'] = 'constraint'
        # kwargs['qualifier'] = 'expression'
        kwargs['check_visible'] = False
        kwargs['check_default'] = False
        # print "***", kwargs
        expression_param = self.get_parameter(**kwargs)

        kwargs = {}
        kwargs['twig'] = None
        # TODO: this might not be the case, we just know its not in constraint
        kwargs['qualifier'] = expression_param.qualifier
        kwargs['component'] = expression_param.component
        kwargs['dataset'] = expression_param.dataset
        kwargs['feature'] = expression_param.feature
        kwargs['context'] = []
        if kwargs['component'] is not None:
            kwargs['context'] += ['component']
        if kwargs['dataset'] is not None:
            kwargs['context'] += ['dataset']
        if kwargs['feature'] is not None:
            kwargs['context'] += ['feature']

        kwargs['check_visible'] = False
        kwargs['check_default'] = False
        constrained_param = self.get_parameter(**kwargs)

        result = expression_param.result

        constrained_param.set_value(result, force=True, run_constraints=True)

        logger.debug("setting '{}'={} from '{}' constraint".format(constrained_param.uniquetwig, result, expression_param.uniquetwig))

        if return_parameter:
            return constrained_param
        else:
            return result

Response: Run a given constraint now and set the value of the constrained parameter.


Instruction:
How would you implement a function in Python 3 that
computes the passband luminosities that will be applied to the system and then re - compute the pblums for the specified compute.

Response:
def compute_pblums(self, compute=None, **kwargs):
        """
        Compute the passband luminosities that will be applied to the system,
        following all coupling, etc, as well as all relevant compute options
        (ntriangles, distortion_method, etc).  The exposed passband luminosities
        (and any coupling) are computed at t0@system.

        This method is only for convenience and will be recomputed internally
        within run_compute.  Alternatively, you can create a mesh dataset
        and request any specific pblum to be exposed (per-time).

        :parameter str compute: label of the compute options (note required if
            only one is attached to the bundle)
        :parameter component: (optional) label of the component(s) requested
        :type component: str or list of strings
        :parameter dataset: (optional) label of the dataset(s) requested
        :type dataset: str or list of strings
        :parameter component: (optional) label of the component(s) requested
        :type component: str or list of strings
        :return: dictionary with keys <component>@<dataset> and computed pblums
            as values (as quantity objects, default units of W)

        """
        datasets = kwargs.pop('dataset', self.datasets)
        components = kwargs.pop('component', self.components)

        # don't allow things like model='mymodel', etc
        forbidden_keys = parameters._meta_fields_filter
        self._kwargs_checks(kwargs, additional_forbidden_keys=forbidden_keys)

        if compute is None:
            if len(self.computes)==1:
                compute = self.computes[0]
            else:
                raise ValueError("must provide compute")

        system = backends.PhoebeBackend()._create_system_and_compute_pblums(self, compute, **kwargs)

        pblums = {}
        for component, star in system.items():
            if component not in components:
                continue
            for dataset in star._pblum_scale.keys():
                if dataset not in datasets:
                    continue
                pblums["{}@{}".format(component, dataset)] = float(star.compute_luminosity(dataset)) * u.W

        return pblums


Instruction:
Can you generate the documentation for the following Python 3 function
def add_compute(self, kind=compute.phoebe, **kwargs):
        func = _get_add_func(_compute, kind)

        kwargs.setdefault('compute',
                          self._default_label(func.func_name,
                                              **{'context': 'compute',
                                                 'kind': func.func_name}))

        self._check_label(kwargs['compute'])

        params = func(**kwargs)
        # TODO: similar kwargs logic as in add_dataset (option to pass dict to
        # apply to different components this would be more complicated here if
        # allowing to also pass to different datasets

        metawargs = {'context': 'compute',
                     'kind': func.func_name,
                     'compute': kwargs['compute']}

        logger.info("adding {} '{}' compute to bundle".format(metawargs['kind'], metawargs['compute']))
        self._attach_params(params, **metawargs)

        redo_kwargs = deepcopy(kwargs)
        redo_kwargs['func'] = func.func_name
        self._add_history(redo_func='add_compute',
                          redo_kwargs=redo_kwargs,
                          undo_func='remove_compute',
                          undo_kwargs={'compute': kwargs['compute']})

        # since we've already processed (so that we can get the new qualifiers),
        # we'll only raise a warning
        self._kwargs_checks(kwargs, warning_only=True)

        return self.get_compute(**metawargs)

Response: Adds a set of compute options for a given backend to the bundle.


Instruction:
Can you write a function in Python 3 where it
filters in the compute context

Response:
def get_compute(self, compute=None, **kwargs):
        """
        Filter in the 'compute' context

        :parameter str compute: name of the compute options (optional)
        :parameter **kwargs: any other tags to do the filter
            (except compute or context)
        :return: :class:`phoebe.parameters.parameters.ParameterSet`
        """
        if compute is not None:
            kwargs['compute'] = compute
        kwargs['context'] = 'compute'
        return self.filter(**kwargs)


Instruction:
Given the following Python 3 function, write the documentation
def remove_compute(self, compute, **kwargs):
        kwargs['compute'] = compute
        kwargs['context'] = 'comute'
        self.remove_parameters_all(**kwargs)

Response: Remove a compute from the bundle


Instruction:
How would you code a function in Python 3 to
change the label of a compute attached to the Bundle

Response:
def rename_compute(self, old_compute, new_compute):
        """
        Change the label of a compute attached to the Bundle

        :parameter str old_compute: the current name of the compute options
            (must exist)
        :parameter str new_compute: the desired new name of the compute options
            (must not exist)
        :return: None
        :raises ValueError: if the new_compute is forbidden
        """
        # TODO: raise error if old_compute not found?

        self._check_label(new_compute)
        self._rename_label('compute', old_compute, new_compute)


Instruction:
Write a Python 3 function for
running a forward model of the system on the enabled dataset using a specified set of compute options. To attach and set custom values for compute options, including choosing which backend to use, see: * :meth:`add_compute` To define the dataset types and times at which the model should be computed see: * :meth:`add_dataset` To disable or enable existing datasets see: * :meth:`enable_dataset` * :meth:`disable_dataset` :parameter str compute: (optional) name of the compute options to use. If not provided or None, run_compute will use an existing set of attached compute options if only 1 exists. If more than 1 exist, then compute becomes a required argument. If no compute options exist, then this will use default options and create and attach a new set of compute options with a default label. :parameter str model: (optional) name of the resulting model. If not provided this will default to 'latest'. NOTE: existing models with the same name will be overwritten - including 'latest' :parameter bool datach: [EXPERIMENTAL] whether to detach from the computation run, or wait for computations to complete. If detach is True, see :meth:`get_model` and :meth:`phoebe.parameters.parameters.JobParameter` for details on how to check the job status and retrieve the results. Alternatively, you can provide the server location (host and port) as a string to detach and the bundle will temporarily enter client mode, submit the job to the server, and leave client mode. The resulting :meth:`phoebe.parameters.parameters.JobParameter` will then contain the necessary information to pull the results from the server at anytime in the future. :parameter list times: [EXPERIMENTAL] override the times at which to compute the model. NOTE: this only (temporarily) replaces the time array for datasets with times provided (ie empty time arrays are still ignored). So if you attach a rv to a single component, the model will still only compute for that single component. ALSO NOTE: this option is ignored if detach=True (at least for now). :parameter **kwargs: any values in the compute options to temporarily override for this single compute run (parameter values will revert after run_compute is finished) :return: :class:`phoebe.parameters.parameters.ParameterSet` of the newly-created model containing the synthetic data.

Response:
def run_compute(self, compute=None, model=None, detach=False,
                    times=None, **kwargs):
        """
        Run a forward model of the system on the enabled dataset using
        a specified set of compute options.

        To attach and set custom values for compute options, including choosing
        which backend to use, see:
            * :meth:`add_compute`

        To define the dataset types and times at which the model should be
        computed see:
            * :meth:`add_dataset`

        To disable or enable existing datasets see:
            * :meth:`enable_dataset`
            * :meth:`disable_dataset`

        :parameter str compute: (optional) name of the compute options to use.
            If not provided or None, run_compute will use an existing set of
            attached compute options if only 1 exists.  If more than 1 exist,
            then compute becomes a required argument.  If no compute options
            exist, then this will use default options and create and attach
            a new set of compute options with a default label.
        :parameter str model: (optional) name of the resulting model.  If not
            provided this will default to 'latest'.  NOTE: existing models
            with the same name will be overwritten - including 'latest'
        :parameter bool datach: [EXPERIMENTAL] whether to detach from the computation run,
            or wait for computations to complete.  If detach is True, see
            :meth:`get_model` and :meth:`phoebe.parameters.parameters.JobParameter`
            for details on how to check the job status and retrieve the results.
            Alternatively, you can provide the server location (host and port) as
            a string to detach and the bundle will temporarily enter client mode,
            submit the job to the server, and leave client mode.  The resulting
            :meth:`phoebe.parameters.parameters.JobParameter` will then contain
            the necessary information to pull the results from the server at anytime
            in the future.
        :parameter list times: [EXPERIMENTAL] override the times at which to compute the model.
            NOTE: this only (temporarily) replaces the time array for datasets
            with times provided (ie empty time arrays are still ignored).  So if
            you attach a rv to a single component, the model will still only
            compute for that single component.  ALSO NOTE: this option is ignored
            if detach=True (at least for now).
        :parameter **kwargs: any values in the compute options to temporarily
            override for this single compute run (parameter values will revert
            after run_compute is finished)
        :return: :class:`phoebe.parameters.parameters.ParameterSet` of the
            newly-created model containing the synthetic data.
        """
        if isinstance(detach, str):
            # then we want to temporarily go in to client mode
            self.as_client(server=detach)
            self.run_compute(compute=compute, model=model, time=time, **kwargs)
            self.as_client(False)
            return self.get_model(model)

        # protomesh and pbmesh were supported kwargs in 2.0.x but are no longer
        # so let's raise an error if they're passed here
        if 'protomesh' in kwargs.keys():
            raise ValueError("protomesh is no longer a valid option")
        if 'pbmesh' in kwargs.keys():
            raise ValueError("pbmesh is no longer a valid option")

        if model is None:
            model = 'latest'

        if model in self.models:
            logger.warning("overwriting model: {}".format(model))
            self.remove_model(model)

        self._check_label(model)

        if isinstance(times, float) or isinstance(times, int):
            times = [times]

        # handle case where compute is not provided
        if compute is None:
            computes = self.get_compute(**kwargs).computes
            if len(computes)==0:
                # NOTE: this doesn't take **kwargs since we want those to be
                # temporarily overriden as is the case when the compute options
                # are already attached
                self.add_compute()
                computes = self.get_compute().computes
                # now len(computes) should be 1 and will trigger the next
                # if statement

            if len(computes)==1:
                compute = computes[0]
            elif len(computes)>1:
                raise ValueError("must provide label of compute options since more than one are attached")

        # handle the ability to send multiple compute options/backends - here
        # we'll just always send a list of compute options
        if isinstance(compute, str):
            computes = [compute]
        else:
            computes = compute

        # if interactive mode was ever off, let's make sure all constraints
        # have been run before running system checks or computing the model
        changed_params = self.run_delayed_constraints()

        # any kwargs that were used just to filter for get_compute should  be
        # removed so that they aren't passed on to all future get_value(...
        # **kwargs) calls
        for k in parameters._meta_fields_filter:
            if k in kwargs.keys():
                dump = kwargs.pop(k)

        # we'll wait to here to run kwargs and system checks so that
        # add_compute is already called if necessary
        self._kwargs_checks(kwargs, ['skip_checks', 'jobid'])

        if not kwargs.get('skip_checks', False):
            passed, msg = self.run_checks(computes=computes, **kwargs)
            if passed is None:
                # then just raise a warning
                logger.warning(msg)
            if passed is False:
                # then raise an error
                raise ValueError("system failed to pass checks: {}".format(msg))

        # let's first make sure that there is no duplication of enabled datasets
        datasets = []
        # compute_ so we don't write over compute which we need if detach=True
        for compute_ in computes:
            # TODO: filter by value instead of if statement once implemented
            for enabled_param in self.filter(qualifier='enabled',
                                             compute=compute_,
                                             context='compute').to_list():
                if enabled_param.get_value():
                    item = (enabled_param.dataset, enabled_param.component)
                    if item in datasets:
                        raise ValueError("dataset {}@{} is enabled in multiple compute options".format(item[0], item[1]))
                    datasets.append(item)

        # now if we're supposed to detach we'll just prepare the job for submission
        # either in another subprocess or through some queuing system
        if detach and mpi.within_mpirun:
            logger.warning("cannot detach when within mpirun, ignoring")
            detach = False

        if (detach or mpi.enabled) and not mpi.within_mpirun:
            if detach:
                logger.warning("detach support is EXPERIMENTAL")

            if times is not None:
                # TODO: support overriding times with detached - issue here is
                # that it isn't necessarilly trivially to send this array
                # through the script.  May need to convert to list first to
                # avoid needing to import numpy?
                logger.warning("overriding time is not supported within detach - ignoring")

            # we'll track everything through the model name as well as
            # a random string, to avoid any conflicts
            jobid = kwargs.get('jobid', parameters._uniqueid())

            # we'll build a python script that can replicate this bundle as it
            # is now, run compute, and then save the resulting model
            script_fname = "_{}.py".format(jobid)
            f = open(script_fname, 'w')
            f.write("import os; os.environ['PHOEBE_ENABLE_PLOTTING'] = 'FALSE'; os.environ['PHOEBE_ENABLE_SYMPY'] = 'FALSE'; os.environ['PHOEBE_ENABLE_ONLINE_PASSBANDS'] = 'FALSE';\n")
            f.write("import phoebe; import json\n")
            # TODO: can we skip the history context?  And maybe even other models
            # or datasets (except times and only for run_compute but not run_fitting)
            f.write("bdict = json.loads(\"\"\"{}\"\"\")\n".format(json.dumps(self.to_json())))
            f.write("b = phoebe.Bundle(bdict)\n")
            # TODO: make sure this works with multiple computes
            compute_kwargs = kwargs.items()+[('compute', compute), ('model', model)]
            compute_kwargs_string = ','.join(["{}={}".format(k,"\'{}\'".format(v) if isinstance(v, str) else v) for k,v in compute_kwargs])
            f.write("model_ps = b.run_compute({})\n".format(compute_kwargs_string))
            f.write("model_ps.save('_{}.out', incl_uniqueid=True)\n".format(jobid))
            f.close()

            script_fname = os.path.abspath(script_fname)
            cmd = mpi.detach_cmd.format(script_fname)
            # TODO: would be nice to catch errors caused by the detached script...
            # but that would probably need to be the responsibility of the
            # jobparam to return a failed status and message
            subprocess.call(cmd, shell=True)

            # create model parameter and attach (and then return that instead of None)
            job_param = JobParameter(self,
                                     location=os.path.dirname(script_fname),
                                     status_method='exists',
                                     retrieve_method='local',
                                     uniqueid=jobid)

            metawargs = {'context': 'model', 'model': model}
            self._attach_params([job_param], **metawargs)

            if isinstance(detach, str):
                self.save(detach)

            if not detach:
                return job_param.attach()
            else:
                logger.info("detaching from run_compute.  Call get_model('{}').attach() to re-attach".format(model))

            # return self.get_model(model)
            return job_param

        for compute in computes:

            computeparams = self.get_compute(compute=compute)

            if not computeparams.kind:
                raise KeyError("could not recognize backend from compute: {}".format(compute))

            logger.info("running {} backend to create '{}' model".format(computeparams.kind, model))
            compute_class = getattr(backends, '{}Backend'.format(computeparams.kind.title()))
            # compute_func = getattr(backends, computeparams.kind)

            metawargs = {'compute': compute, 'model': model, 'context': 'model'}  # dataset, component, etc will be set by the compute_func

            params = compute_class().run(self, compute, times=times, **kwargs)

            # average over any exposure times before attaching parameters
            if computeparams.kind == 'phoebe':
                # TODO: we could eventually do this for all backends - we would
                # just need to copy the computeoption parameters into each backend's
                # compute PS, and include similar logic for oversampling that is
                # currently in backends._extract_info_from_bundle_by_time into
                # backends._extract_info_from_bundle_by_dataset.  We'd also
                # need to make sure that exptime is not being passed to any
                # alternate backend - and ALWAYS handle it here
                for dataset in params.datasets:
                    # not all dataset-types currently support exposure times.
                    # Once they do, this ugly if statement can be removed
                    if len(self.filter(dataset=dataset, qualifier='exptime')):
                        exptime = self.get_value(qualifier='exptime', dataset=dataset, context='dataset', unit=u.d)
                        if exptime > 0:
                            if self.get_value(qualifier='fti_method', dataset=dataset, compute=compute, context='compute', **kwargs)=='oversample':
                                times_ds = self.get_value(qualifier='times', dataset=dataset, context='dataset')
                                # exptime = self.get_value(qualifier='exptime', dataset=dataset, context='dataset', unit=u.d)
                                fti_oversample = self.get_value(qualifier='fti_oversample', dataset=dataset, compute=compute, context='compute', check_visible=False, **kwargs)
                                # NOTE: this is hardcoded for LCs which is the
                                # only dataset that currently supports oversampling,
                                # but this will need to be generalized if/when
                                # we expand that support to other dataset kinds
                                fluxes = np.zeros(times_ds.shape)

                                # the oversampled times and fluxes will be
                                # sorted according to times this may cause
                                # exposures to "overlap" each other, so we'll
                                # later need to determine which times (and
                                # therefore fluxes) belong to which datapoint
                                times_oversampled_sorted = params.get_value('times', dataset=dataset)
                                fluxes_oversampled = params.get_value('fluxes', dataset=dataset)

                                for i,t in enumerate(times_ds):
                                    # rebuild the unsorted oversampled times - see backends._extract_from_bundle_by_time
                                    # TODO: try to optimize this by having these indices returned by the backend itself
                                    times_oversampled_this = np.linspace(t-exptime/2., t+exptime/2., fti_oversample)
                                    sample_inds = np.searchsorted(times_oversampled_sorted, times_oversampled_this)

                                    fluxes[i] = np.mean(fluxes_oversampled[sample_inds])

                                params.set_value(qualifier='times', dataset=dataset, value=times_ds)
                                params.set_value(qualifier='fluxes', dataset=dataset, value=fluxes)

            self._attach_params(params, **metawargs)

        redo_kwargs = deepcopy(kwargs)
        redo_kwargs['compute'] = computes if len(computes)>1 else computes[0]
        redo_kwargs['model'] = model

        self._add_history(redo_func='run_compute',
                          redo_kwargs=redo_kwargs,
                          undo_func='remove_model',
                          undo_kwargs={'model': model})

        return self.get_model(model)


Instruction:
Can you tell what is the following Python 3 function doing
def get_model(self, model=None, **kwargs):
        if model is not None:
            kwargs['model'] = model
        kwargs['context'] = 'model'
        return self.filter(**kwargs)

Response: Filter in the model context


Instruction:
Explain what the following Python 3 code does
def remove_model(self, model, **kwargs):
        kwargs['model'] = model
        kwargs['context'] = 'model'
        self.remove_parameters_all(**kwargs)

Response: Remove a model from the bundle


Instruction:
How would you explain what the following Python 3 function does
def rename_model(self, old_model, new_model):
        # TODO: raise error if old_feature not found?

        self._check_label(new_model)
        self._rename_label('model', old_model, new_model)

Response:
Change the label of a model attached to the Bundle
           .


Instruction:
Can you write a function in Python 3 where it
adds a prior parameter to the current object.

Response:
def add_prior(self, twig=None, **kwargs):
        """
        [NOT IMPLEMENTED]

        :raises NotImplementedError: because it isn't
        """

        raise NotImplementedError

        param = self.get_parameter(twig=twig, **kwargs)
        # TODO: make sure param is a float parameter?

        func = _get_add_func(_distributions, 'prior')

        # TODO: send smart defaults for priors based on limits of parameter
        params = func(**kwargs)

        metawargs = {k: v for k, v in params.meta.items()
                     if k not in ['uniqueid', 'uniquetwig', 'twig']}
        metawargs['context'] = 'prior'

        logger.info("adding prior on '{}' parameter".format(param.uniquetwig))
        self._attach_params(params, **metawargs)

        redo_kwargs = deepcopy(kwargs)
        redo_kwargs['func'] = func.func_name
        self._add_history(redo_func='add_prior',
                          redo_kwargs=redo_kwargs,
                          undo_func='remove_prior',
                          undo_kwargs={'twig': param.uniquetwig})

        # return params
        return self.get_prior(**metawargs)


Instruction:
Explain what the following Python 3 code does
def get_prior(self, twig=None, **kwargs):
        raise NotImplementedError
        kwargs['context'] = 'prior'
        return self.filter(twig=twig, **kwargs)

Response: Returns a copy of the current object with the prior context.


Instruction:
Can you write a function in Python 3 where it
returns a new object with the given fitting.

Response:
def get_fitting(self, fitting=None, **kwargs):
        """
        [NOT IMPLEMENTED]

        :raises NotImplementedError: because it isn't
        """
        raise NotImplementedError
        if fitting is not None:
            kwargs['fitting'] = fitting
        kwargs['context'] = 'fitting'
        return self.filter(**kwargs)


Instruction:
Can you implement a function in Python 3 that
returns a new QuerySet with the posterior entries.

Response:
def get_posterior(self, twig=None, feedback=None, **kwargs):
        """
        [NOT IMPLEMENTED]

        :raises NotImplementedError: because it isn't
        """
        raise NotImplementedError
        kwargs['context'] = 'posterior'
        return self.filter(twig=twig, **kwargs)


Instruction:
Make a summary of the following Python 3 code
def get_feedback(self, feedback=None, **kwargs):
        raise NotImplementedError
        if feedback is not None:
            kwargs['feedback'] = feedback
        kwargs['context'] = 'feedback'
        return self.filter(**kwargs)

Response: Returns a new EntryCollection with feedback entries.


Instruction:
Create a Python 3 function to
convert a twig parameter to a unique ID.

Response:
def _twig_to_uniqueid(bundle, twig, **kwargs):
    """
    kwargs are passed on to filter
    """
    res = bundle.filter(twig=twig, force_ps=True, check_visible=False, check_default=False, **kwargs)
    # we force_ps instead of checking is_instance(res, ParameterSet) to avoid
    # having to import from parameters
    if len(res) == 1:
        #~ print "twighelpers._twig_to_uniqueid len(res): {}, res: {}".format(len(res), res)
        return res.to_list()[0].uniqueid
    else:
        raise ValueError("did not return a single unique match to a parameter for '{}'".format(twig))


Instruction:
Make a summary of the following Python 3 code
def update_user_label(self):
        self._user_label = _uniqueid_to_uniquetwig(self._bundle, self.unique_label)
        self._set_curly_label()

Response: Updates the user_label attribute of the current locale based on the least unique_twig from the bundle


Instruction:
How would you explain what the following Python 3 function does
def get_parameter(self):
        if not self.is_param:
            raise ValueError("this var does not point to a parameter")

        # this is quite expensive, so let's cache the parameter object so we only
        # have to filter on the first time this is called
        if self._parameter is None:
            self._parameter = self._bundle.get_parameter(uniqueid=self.unique_label, check_visible=False, check_default=False)

        return self._parameter

Response: get the parameter object for this var


Instruction:
Write a Python 3 function for
processing kwargs for AxDimension instances by stripping off the prefix of the prefix and removing off the appropriate direction

Response:
def _process_dimension_kwargs(direction, kwargs):
    """
    process kwargs for AxDimension instances by stripping off the prefix
    for the appropriate direction
    """
    acceptable_keys = ['unit', 'pad', 'lim', 'label']
    # if direction in ['s']:
        # acceptable_keys += ['mode']
    processed_kwargs = {}
    for k,v in kwargs.items():
        if k.startswith(direction):
            processed_key = k.lstrip(direction)
        else:
            processed_key = k

        if processed_key in acceptable_keys:
            processed_kwargs[processed_key] = v

    return processed_kwargs


Instruction:
Make a summary of the following Python 3 code
def calls_sorted(self):
        def _z(call):
            if isinstance(call.z.value, np.ndarray):
                return np.mean(call.z.value.flatten())
            elif isinstance(call.z.value, float) or isinstance(call.z.value, int):
                return call.z.value
            else:
                # put it at the back
                return -np.inf

        calls = self._calls
        zs = np.array([_z(c) for c in calls])
        sorted_inds = zs.argsort()
        # TODO: ugh, this is ugly.  Test to find the optimal way to sort
        # while still ending up with a list
        return _call.make_callgroup(np.array(calls)[sorted_inds].tolist())

Response:
Returns a list of all the calls in z
        sorted in z


Instruction:
Explain what the following Python 3 code does
def consistent_with_call(self, call):
        if len(self.calls) == 0:
            return True, ''

        msg = []

        if not _consistent_allow_none(call._axorder, self._axorder):
            msg.append('inconsistent axorder, {} != {}'.format(call.axorder, self.axorder))

        if not _consistent_allow_none(call._axpos, self._axpos):
            msg.append('inconsistent axpos, {} != {}'.format(call.axpos, self.axpos))

        if call._axorder == self._axorder and call._axorder is not None:
            # then despite other conflicts, attempt to put on same axes
            return True, ''

        if call._axpos == self._axpos and call._axpos is not None:
            # then despite other conflicts, attempt to put on same axes
            return True, ''

        # TODO: include s, c, fc, ec, etc and make these checks into loops
        if call.x.unit.physical_type != self.x.unit.physical_type:
            msg.append('inconsitent xunit, {} != {}'.format(call.x.unit, self.x.unit))
        if call.y.unit.physical_type != self.y.unit.physical_type:
            msg.append('inconsitent yunit, {} != {}'.format(call.y.unit, self.y.unit))
        if call.z.unit.physical_type != self.z.unit.physical_type:
            msg.append('inconsitent zunit, {} != {}'.format(call.z.unit, self.z.unit))
        if call.i.unit.physical_type != self.i.unit.physical_type:
            msg.append('inconsistent iunit, {} != {}'.format(call.i.unit, self.i.unit))
        if call.i.is_reference or self.i.is_reference:
            if call.i.reference != self.i.reference:
                msg.append('inconsistent i reference, {} != {}'.format(call.i.reference, self.i.reference))

        if not _consistent_allow_none(call.title, self.title):
            msg.append('inconsistent axes title, {} != {}'.format(call.title, self.title))

        # here we send the protected _label so that we get None instead of empty string
        if not _consistent_allow_none(call.x._label, self.x._label):
            msg.append('inconsitent xlabel, {} != {}'.format(call.x.label, self.x.label))
        if not _consistent_allow_none(call.y._label, self.y._label):
            msg.append('inconsitent ylabel, {} != {}'.format(call.y.label, self.y.label))
        if not _consistent_allow_none(call.z._label, self.z._label):
            msg.append('inconsitent zlabel, {} != {}'.format(call.z.label, self.z.label))

        if len(msg):
            return False, ', '.join(msg)
        else:
            return True, ''

Response: check to see if a new call would be consistent with this Axes instance


Instruction:
Make a summary of the following Python 3 code
def lim(self, lim):
        if lim is None:
            self._lim = lim
            return

        typeerror_msg = "lim must be of type tuple, float, None, or in ['fixed', 'symmetric', 'frame', 'sliding']"

        if isinstance(lim, str):
            if lim in ['fixed', 'symmetric', 'frame', 'sliding']:
                self._lim = lim
                return
            else:
                raise ValueError(typeerror_msg)

        if isinstance(lim, int):
            lim = float(lim)

        if isinstance(lim, float):
            if lim <= 0.0:
                raise ValueError("lim cannot be <= 0")
            self._lim = lim
            return

        if not isinstance(lim, tuple):
            try:
                lim = tuple(lim)
            except:
                raise TypeError(typeerror_msg)

        if not len(lim)==2:
            raise ValueError('lim must have length 2')

        for l in lim:
            if not (isinstance(l, float) or isinstance(l, int) or l is None):
                raise ValueError("each item in limit must be of type float, int, or None")

        self._lim = lim

Response: set the limit of the available log entries


Instruction:
Write a Python 3 function for
getting the value at a give value of i

Response:
def get_value(self, i, indeps=None):
        """
        access the interpolated value at a give value of i (independent-variable)

        if indeps is not passed, then the entire range of indeps over all calls is assumed
        """
        if self.value is None:
            return None

        if i is None:
            return np.median(self.value)

        if indeps is None:
            indeps_all_calls = list(set(np.concatenate([common.tolist(call.i.get_value(unit=self.axes.i.unit)) for call in self.axes.calls])))
            indeps = np.linspace(np.nanmin(indeps_all_calls),
                                 np.nanmax(indeps_all_calls),
                                 len(self.value))

        if len(indeps) != len(self.value):
            raise ValueError("indeps and value must have same length")

        return np.interp(i, indeps, self.value)


Instruction:
Can you write a function in Python 3 where it
generates a new system parameter set for all the parameters in the order they appear.

Response:
def system(**kwargs):
    """
    Generally, this will automatically be added to a newly initialized
    :class:`phoebe.frontend.bundle.Bundle`

    :parameter **kwargs: defaults for the values of any of the parameters
    :return: a :class:`phoebe.parameters.parameters.ParameterSet` of all newly
        created :class:`phoebe.parameters.parameters.Parameter`s
    """
    params = []

    params += [FloatParameter(qualifier='t0', value=kwargs.get('t0', 0.0), default_unit=u.d, description='Time at which all values are provided')]

    # TODO: re-enable these once they're incorporated into orbits (dynamics) correctly.
    params += [FloatParameter(qualifier='ra', value=kwargs.get('ra', 0.0), default_unit=u.deg, description='Right ascension')]
    params += [FloatParameter(qualifier='dec', value=kwargs.get('dec', 0.0), default_unit=u.deg, description='Declination')]
    params += [StringParameter(qualifier='epoch', value=kwargs.get('epoch', 'J2000'), description='Epoch of coordinates')]
    #params += [FloatParameter(qualifier='pmra', value=kwargs.get('pmra', 0.0), default_unit=u.mas/u.yr, description='Proper motion in right ascension')]
    #params += [FloatParameter(qualifier='pmdec', value=kwargs.get('pmdec', 0.0), default_unit=u.mas/u.yr, description='Proper motion in declination')]

    params += [FloatParameter(qualifier='distance', value=kwargs.get('distance', 1.0), default_unit=u.m, description='Distance to the system')]
    params += [FloatParameter(qualifier='vgamma', value=kwargs.get('vgamma', 0.0), default_unit=u.km/u.s, description='Systemic velocity (in the direction of positive RV or negative vz)')]

    return ParameterSet(params)


Instruction:
Can you generate the documentation for the following Python 3 function
def create_teams(obj, user, access):
    for field_name, access_types in access.items():
        id_field = "{}_id".format(field_name)
        # Check that the team is associated with the object via a FK...
        if hasattr(obj, id_field) and getattr(obj, id_field) is None:
            # ...and there is no existing related team.
            # TODO - the team name needs to be able to create a unique
            # slug that's < 50 characters long.
            # TODO - this is just a workaround:
            next_pk = next(iter(instance.pk for instance in obj.__class__.objects.order_by("-pk")), 0) + 1  # this is a thing a beauty. ;-)
            team_name = u"{} for {} {}".format(
                field_name, obj._meta.model_name, next_pk)
            new_team = Team(
                name=team_name,
                member_access=access_types[0],
                manager_access=access_types[1],
                creator=user)
            new_team.save()
            setattr(obj, field_name, new_team)
    return obj

Response: Create new teams associated with the object.


Instruction:
Given the following Python 3 function, write the documentation
def _to_component(obj, allow_hierarchy=True):

    def _to_str(obj):
        return "{}:{}".format(obj.kind, obj.component)

    if isinstance(obj, str):
        # TODO: check to see if valid?, use allow_hierarchy
        # TODO: when passed labels this is going to give the wrong thing, but that might be fixable in the HierarchyParameter set_value check
        #~ raise NotImplementedError # need to get object from bundle and pass to _to_str
        return obj
    elif isinstance(obj, ParameterSet):
        # TODO: be smarter about this and don't assume only 1 will be returned
        if 'repr' in obj.to_flat_dict().keys():
            return obj.get_value(qualifier='repr')

        else:
            # make sure we only have things in the 'component' context
            obj = obj.filter(context='component')
            return _to_str(obj)

    elif isinstance(obj, Parameter):
        if obj.qualifier == 'repr':
            return obj.get_value()
        else:
            return _to_str(obj)

    else:
        raise NotImplementedError("could not parse {}".format(obj))

Response: Convert an object to a string or ParameterSet or a nested hierarchy.


Instruction:
Can you generate the documentation for the following Python 3 function
def binaryorbit(orbit, comp1, comp2, envelope=None):

    if envelope:
        return '{}({}, {}, {})'.format(_to_component(orbit, False), _to_component(comp1), _to_component(comp2), _to_component(envelope, False))
    else:
        return '{}({}, {})'.format(_to_component(orbit, False), _to_component(comp1), _to_component(comp2))

Response: Builds a string representation of a binary hierarchy containing a 2 components orbit.


Instruction:
Can you generate the documentation for the following Python 3 function
def nekmin(omega_in,q,x0=0.5,z0=0.5):

    '''Computes the position of the neck (minimal radius) in an contact_binary star1'''

    def Omega_xz(q,x,z):
        return 1./np.sqrt(x**2+z**2)+q/np.sqrt((1-x)**2+z**2)+(q+1)*x**2/2.-q*x

    def Omega_xy(q,x,y):
        return 1./np.sqrt(x**2+y**2)+q/np.sqrt((1-x)**2+y**2)+(q+1)*(x**2+y**2)/2.-q*x

    def dOmegadx_z(q,x,z):
        return -x/(x**2+z**2)**(3./2)+q*(1-x)/((1-x)**2+z**2)**(3./2.)+(q+1)*x-q

    def dOmegadx_y(q,x,y):
        return -x/(x**2+y**2)**(3./2)+q*(1-x)/((1-x)**2+y**2)**(3./2.)+(q+1)*x-q

    def dOmegadz(q,x,z):
        return -z/(x**2+z**2)**(3./2)-q*z/((1-x)**2+z**2)**(3./2.)

    def dOmegady(q,x,y):
        return -y/(x**2+y**2)**(3./2)-q*y/((1-x)**2+y**2)**(3./2.)+(q+1)*y

    def d2Omegadx2_z(q,x,z):
        return (2*x**2-z**2)/(x**2+z**2)**(5./2)+q*(2*(1-x)**2-z**2)/((1-x)**2+z**2)**(5./2)+(q+1)

    def d2Omegadx2_y(q,x,y):
        return (2*x**2-y**2)/(x**2+y**2)**(5./2)+q*(2*(1-x)**2-y**2)/((1-x)**2+y**2)**(5./2)+(q+1)

    def d2Omegadxdz(q,x,z):
        return 3*x*z/(x**2+z**2)**(5./2)-3*q*x*(1-x)/((1-x)**2+z**2)**(5./2)

    def d2Omegadxdy(q,x,y):
        return 3*x*y/(x**2+y**2)**(5./2)-3*q*x*(1-x)/((1-x)**2+y**2)**(5./2)

    xz,z = x0,z0
    dxz, dz = 1.,1.

    # find solution in xz plane
    while abs(dxz)>1e-8 and abs(dz)>1e-8:

        delz = 1.
        z=0.05
        while abs(delz) > 0.000001:
            delom = omega_in - Omega_xz(q,xz,z)
            delz = delom/dOmegadz(q,xz,z)
            z = abs(z+delz)

        DN = np.array([[dOmegadx_z(q,xz,z),dOmegadz(q,xz,z)],[d2Omegadx2_z(q,xz,z),d2Omegadxdz(q,xz,z)]])
        EN = np.array([omega_in-Omega_xz(q,xz,z),(-1)*dOmegadx_z(q,xz,z)])

        a,b,c,d = DN[0][0],DN[0][1],DN[1][0],DN[1][1]

        if (a*d-b*c)!=0.:
            DNINV = 1./(a*d-b*c)*np.array([[d,(-1)*b],[(-1)*c,d]])
            #DNINV = inv(DN)

            dd = np.dot(DNINV,EN)
            dxz,dz = dd[0],dd[1]
            xz=xz+dxz
            z=z+dz
        else:
            xz = xz+0.5
            z = z+0.5
            dxz = 1.
            dz = 1.

    return xz,z

Response: Computes the position of the neck in an contact_binary star1