Instruction:
Can you generate a brief explanation for the following Python 3 code
def observe(self, dataset, kind, components=None, distance=1.0, l3=0.0, **kwargs):

        meshes = self.meshes
        if kind=='lp':
            def sv(p, p0, w):
                # Subsidiary variable:
                return (p0-p)/(w/2)

            def lorentzian(sv):
                return 1-1./(1+sv**2)

            def gaussian(sv):
                return 1-np.exp(-np.log(2)*sv**2)

            profile_func = kwargs.get('profile_func')
            profile_rest = kwargs.get('profile_rest')
            profile_sv = kwargs.get('profile_sv')
            wavelengths = kwargs.get('wavelengths')
            if profile_func == 'gaussian':
                func = gaussian
            elif profile_func == 'lorentzian':
                func = lorentzian
            else:
                raise NotImplementedError("profile_func='{}' not supported".format(profile_func))

            visibilities = meshes.get_column_flat('visibilities', components)

            abs_intensities = meshes.get_column_flat('abs_intensities:{}'.format(dataset), components)
            # mus here will be from the tnormals of the triangle and will not
            # be weighted by the visibility of the triangle
            mus = meshes.get_column_flat('mus', components)
            areas = meshes.get_column_flat('areas_si', components)
            ldint = meshes.get_column_flat('ldint:{}'.format(dataset), components)

            rvs = (meshes.get_column_flat("rvs:{}".format(dataset), components)*u.solRad/u.d).to(u.m/u.s).value
            dls = rvs*profile_rest/c.c.si.value

            line = func(sv(wavelengths, profile_rest, profile_sv))
            lines = np.array([np.interp(wavelengths, wavelengths+dl, line) for dl in dls])
            if not np.any(visibilities):
                avg_line = np.full_like(wavelengths, np.nan)
            else:
                avg_line = np.average(lines, axis=0, weights=abs_intensities*areas*mus*ldint*visibilities)

            return {'flux_densities': avg_line}

        elif kind=='rv':
            visibilities = meshes.get_column_flat('visibilities', components)

            if np.all(visibilities==0):
                # then no triangles are visible, so we should return nan
                return {'rv': np.nan}

            rvs = meshes.get_column_flat("rvs:{}".format(dataset), components)
            abs_intensities = meshes.get_column_flat('abs_intensities:{}'.format(dataset), components)
            # mus here will be from the tnormals of the triangle and will not
            # be weighted by the visibility of the triangle
            mus = meshes.get_column_flat('mus', components)
            areas = meshes.get_column_flat('areas_si', components)
            ldint = meshes.get_column_flat('ldint:{}'.format(dataset), components)
            # NOTE: don't need ptfarea because its a float (same for all
            # elements, regardless of component)

            # NOTE: the intensities are already projected but are per unit area
            # so we need to multiply by the /projected/ area of each triangle (thus the extra mu)
            return {'rv': np.average(rvs, weights=abs_intensities*areas*mus*ldint*visibilities)}

        elif kind=='lc':
            visibilities = meshes.get_column_flat('visibilities')

            if np.all(visibilities==0):
                # then no triangles are visible, so we should return nan -
                # probably shouldn't ever happen for lcs
                return {'flux': np.nan}

            intensities = meshes.get_column_flat("intensities:{}".format(dataset), components)
            mus = meshes.get_column_flat('mus', components)
            areas = meshes.get_column_flat('areas_si', components)
            ldint = meshes.get_column_flat('ldint:{}'.format(dataset), components)

            # assume that all bodies are using the same passband and therefore
            # will have the same ptfarea.  If this assumption is ever a problem -
            # then we will need to build a flat column based on the component
            # of each element so that ptfarea is an array with the same shape
            # as those above
            if isinstance(self.bodies[0], Envelope):
                # for envelopes, we'll make the same assumption and just grab
                # that value stored in the first "half"
                ptfarea = self.bodies[0]._halves[0].get_ptfarea(dataset)
            else:
                ptfarea = self.bodies[0].get_ptfarea(dataset)

            # intens_proj is the intensity in the direction of the observer per unit surface area of the triangle
            # areas is the area of each triangle
            # areas*mus is the area of each triangle projected in the direction of the observer
            # visibilities is 0 for hidden, 0.5 for partial, 1.0 for visible
            # areas*mus*visibilities is the visibile projected area of each triangle (ie half the area for a partially-visible triangle)
            # so, intens_proj*areas*mus*visibilities is the intensity in the direction of the observer per the observed projected area of that triangle
            # and the sum of these values is the observed flux

            # note that the intensities are already projected but are per unit area
            # so we need to multiply by the /projected/ area of each triangle (thus the extra mu)

            return {'flux': np.sum(intensities*areas*mus*visibilities)*ptfarea/(distance**2)+l3}

        else:
            raise NotImplementedError("observe for dataset with kind '{}' not implemented".format(kind))

Response: This method returns a dictionary of observable values for a given set of components.


Instruction:
Can you write a function in Python 3 where it
returns the maximum r of the instantaneous nucleus of the species.

Response:
def instantaneous_maxr(self):
        """
        Recall the maximum r (triangle furthest from the center of the star) of
        this star at the given time

        :return: maximum r
        :rtype: float
        """
        logger.debug("{}.instantaneous_maxr".format(self.component))

        if 'maxr' not in self.inst_vals.keys():
            logger.debug("{}.instantaneous_maxr COMPUTING".format(self.component))

            self.inst_vals['maxr'] = max(self.mesh.rs.centers*self._scale)

        return self.inst_vals['maxr']


Instruction:
Make a summary of the following Python 3 code
def _get_mass_by_index(self, index):
        if hasattr(index, '__iter__'):
            return sum([self.masses[i] for i in index])
        else:
            return self.masses[index]

Response: returns the mass by index


Instruction:
Can you implement a function in Python 3 that
gets coordinates by index

Response:
def _get_coords_by_index(self, coords_array, index):
        """
        where index can either by an integer or a list of integers (returns some of masses)
        coords_array should be a single array (xs, ys, or zs)
        """
        if hasattr(index, '__iter__'):
            # then we want the center-of-mass coordinates
            # TODO: clean this up
            return np.average([_value(coords_array[i]) for i in index],
                              weights=[self._get_mass_by_index(i) for i in index])
        else:
            return coords_array[index]


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_standard_mesh(self, scaled=True):
        # TODO: allow this to take etheta and retreive a mesh at that true anomaly
        theta = 0.0
        protomesh = self._standard_meshes[theta] #.copy() # if theta in self._standard_meshes.keys() else self.mesh.copy()

        if scaled:
            # TODO: be careful about self._scale... we may want self._instantaneous_scale
            return mesh.ScaledProtoMesh.from_proto(protomesh, self._scale)
        else:
            return protomesh.copy()

Response: Returns a copy of the standard mesh.


Instruction:
Given the following Python 3 function, write the documentation
def reset_time(self, time, true_anom, elongan, eincl):
        self.true_anom = true_anom
        self.elongan = elongan
        self.eincl = eincl
        self.time = time
        self.populated_at_time = []

        self.reset()

        return

Response: reset the time of the current instance


Instruction:
How would you code a function in Python 3 to
update the position of the star into its orbit

Response:
def update_position(self, time,
                        xs, ys, zs, vxs, vys, vzs,
                        ethetas, elongans, eincls,
                        ds=None, Fs=None,
                        ignore_effects=False,
                        component_com_x=None,
                        **kwargs):
        """
        Update the position of the star into its orbit

        :parameter float time: the current time
        :parameter list xs: a list/array of x-positions of ALL COMPONENTS in the :class:`System`
        :parameter list ys: a list/array of y-positions of ALL COMPONENTS in the :class:`System`
        :parameter list zs: a list/array of z-positions of ALL COMPONENTS in the :class:`System`
        :parameter list vxs: a list/array of x-velocities of ALL COMPONENTS in the :class:`System`
        :parameter list vys: a list/array of y-velocities of ALL COMPONENTS in the :class:`System`
        :parameter list vzs: a list/array of z-velocities of ALL COMPONENTS in the :class:`System`
        :parameter list ethetas: a list/array of euler-thetas of ALL COMPONENTS in the :class:`System`
        :parameter list elongans: a list/array of euler-longans of ALL COMPONENTS in the :class:`System`
        :parameter list eincls: a list/array of euler-incls of ALL COMPONENTS in the :class:`System`
        :parameter list ds: (optional) a list/array of instantaneous distances of ALL COMPONENTS in the :class:`System`
        :parameter list Fs: (optional) a list/array of instantaneous syncpars of ALL COMPONENTS in the :class:`System`
        """

        self.reset_time(time, ethetas[self.ind_self], elongans[self.ind_self], eincls[self.ind_self])

        #-- Get current position/euler information
        # TODO: get rid of this ugly _value stuff
        pos = (_value(xs[self.ind_self]), _value(ys[self.ind_self]), _value(zs[self.ind_self]))
        vel = (_value(vxs[self.ind_self_vel]), _value(vys[self.ind_self_vel]), _value(vzs[self.ind_self_vel]))
        euler = (_value(ethetas[self.ind_self]), _value(elongans[self.ind_self]), _value(eincls[self.ind_self]))
        euler_vel = (_value(ethetas[self.ind_self_vel]), _value(elongans[self.ind_self_vel]), _value(eincls[self.ind_self_vel]))

        # TODO: eventually pass etheta to has_standard_mesh
        # TODO: implement reprojection as an option based on a nearby standard?
        if self.needs_remesh or not self.has_standard_mesh():
            logger.debug("{}.update_position: remeshing at t={}".format(self.component, time))
            # track whether we did the remesh or not, so we know if we should
            # compute local quantities if not otherwise necessary
            did_remesh = True

            # TODO: allow time dependence on d and F from dynamics
            # d = _value(ds[self.ind_self])
            # F = _value(Fs[self.ind_self])

            new_mesh_dict, scale = self._build_mesh(mesh_method=self.mesh_method)
            if self.mesh_method != 'wd':
                new_mesh_dict = self._offset_mesh(new_mesh_dict)

                # We only need the gradients where we'll compute local
                # quantities which, for a marching mesh, is at the vertices.
                new_mesh_dict['normgrads'] = new_mesh_dict.pop('vnormgrads', np.array([]))

            # And lastly, let's fill the velocities column - with zeros
            # at each of the vertices
            new_mesh_dict['velocities'] = np.zeros(new_mesh_dict['vertices'].shape if self.mesh_method != 'wd' else new_mesh_dict['centers'].shape)

            new_mesh_dict['tareas'] = np.array([])

            # TODO: need to be very careful about self.sma vs self._scale - maybe need to make a self._instantaneous_scale???
            # self._scale = scale

            if not self.has_standard_mesh():
                # then we only computed this because we didn't already have a
                # standard_mesh... so let's save this for future use
                # TODO: eventually pass etheta to save_as_standard_mesh
                protomesh = mesh.ProtoMesh(**new_mesh_dict)
                self.save_as_standard_mesh(protomesh)

            # Here we'll build a scaledprotomesh directly from the newly
            # marched mesh
            # NOTE that we're using scale from the new
            # mesh rather than self._scale since the instantaneous separation
            # has likely changed since periastron
            scaledprotomesh = mesh.ScaledProtoMesh(scale=scale, **new_mesh_dict)

        else:
            logger.debug("{}.update_position: accessing standard mesh at t={}".format(self.component, self.time))
            # track whether we did the remesh or not, so we know if we should
            # compute local quantities if not otherwise necessary
            did_remesh = False

            # We still need to go through scaledprotomesh instead of directly
            # to mesh since features may want to process the body-centric
            # coordinates before placing in orbit

            # TODO: eventually pass etheta to get_standard_mesh
            scaledprotomesh = self.get_standard_mesh(scaled=True)
            # TODO: can we avoid an extra copy here?

        if not ignore_effects and len(self.features):
            logger.debug("{}.update_position: processing features at t={}".format(self.component, self.time))
            # First allow features to edit the coords_for_computations (pvertices).
            # Changes here WILL affect future computations for logg, teff,
            # intensities, etc.  Note that these WILL NOT affect the
            # coords_for_observations automatically - those should probably be
            # perturbed as well, unless there is a good reason not to.
            for feature in self.features:
                # NOTE: these are ALWAYS done on the protomesh
                coords_for_observations = feature.process_coords_for_computations(scaledprotomesh.coords_for_computations, s=self.polar_direction_xyz, t=self.time)
                if scaledprotomesh._compute_at_vertices:
                    scaledprotomesh.update_columns(pvertices=coords_for_observations)

                else:
                    scaledprotomesh.update_columns(centers=coords_for_observations)
                    raise NotImplementedError("areas are not updated for changed mesh")

            for feature in self.features:
                coords_for_observations = feature.process_coords_for_observations(scaledprotomesh.coords_for_computations, scaledprotomesh.coords_for_observations, s=self.polar_direction_xyz, t=self.time)
                if scaledprotomesh._compute_at_vertices:
                    scaledprotomesh.update_columns(vertices=coords_for_observations)

                    # TODO [DONE?]: centers either need to be supported or we need to report
                    # vertices in the frontend as x, y, z instead of centers

                    updated_props = libphoebe.mesh_properties(scaledprotomesh.vertices,
                                                              scaledprotomesh.triangles,
                                                              tnormals=True,
                                                              areas=True)

                    scaledprotomesh.update_columns(**updated_props)

                else:
                    scaledprotomesh.update_columns(centers=coords_for_observations)
                    raise NotImplementedError("areas are not updated for changed mesh")

        # TODO NOW [OPTIMIZE]: get rid of the deepcopy here - but without it the
        # mesh velocities build-up and do terrible things.  It may be possible
        # to just clear the velocities in get_standard_mesh()?
        logger.debug("{}.update_position: placing in orbit, Mesh.from_scaledproto at t={}".format(self.component, self.time))
        self._mesh = mesh.Mesh.from_scaledproto(scaledprotomesh.copy(),
                                                pos, vel, euler, euler_vel,
                                                self.polar_direction_xyz*self.freq_rot*self._scale,
                                                component_com_x)

        # Lastly, we'll recompute physical quantities (not observables) if
        # needed for this time-step.
        # TODO [DONE?]: make sure features smartly trigger needs_recompute_instantaneous
        # TODO: get rid of the or True here... the problem is that we're saving the standard mesh before filling local quantities
        if self.needs_recompute_instantaneous or did_remesh:
            logger.debug("{}.update_position: calling compute_local_quantities at t={}".format(self.component, self.time))
            self.compute_local_quantities(xs, ys, zs, ignore_effects)

        return


Instruction:
Write a Python 3 function that can
populate the internal data structures for the specified dataset.

Response:
def populate_observable(self, time, kind, dataset, **kwargs):
        """
        TODO: add documentation
        """

        if kind in ['mesh', 'orb']:
            return

        if time==self.time and dataset in self.populated_at_time and 'pblum' not in kind:
            # then we've already computed the needed columns

            # TODO: handle the case of intensities already computed by
            # /different/ dataset (ie RVs computed first and filling intensities
            # and then lc requesting intensities with SAME passband/atm)
            return

        new_mesh_cols = getattr(self, '_populate_{}'.format(kind.lower()))(dataset, **kwargs)

        for key, col in new_mesh_cols.items():

            self.mesh.update_columns_dict({'{}:{}'.format(key, dataset): col})

        self.populated_at_time.append(dataset)


Instruction:
Implement a Python 3 function for
building a star from a bundle.

Response:
def from_bundle(cls, b, component, compute=None,
                    mesh_init_phi=0.0, datasets=[], **kwargs):
        """
        Build a star from the :class:`phoebe.frontend.bundle.Bundle` and its
        hierarchy.

        Usually it makes more sense to call :meth:`System.from_bundle` directly.

        :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
        :parameter str component: label of the component in the bundle
        :parameter str compute: name of the computeoptions in the bundle
        :parameter list datasets: list of names of datasets
        :parameter **kwargs: temporary overrides for computeoptions
        :return: an instantiated :class:`Star` object
        """
        # TODO [DONE?]: handle overriding options from kwargs
        # TODO [DONE?]: do we need dynamics method???

        hier = b.hierarchy

        if not len(hier.get_value()):
            raise NotImplementedError("Star meshing requires a hierarchy to exist")

        label_self = component
        label_sibling = hier.get_stars_of_sibling_of(component)
        label_orbit = hier.get_parent_of(component)
        starrefs  = hier.get_stars()

        ind_self = starrefs.index(label_self)
        # for the sibling, we may need to handle a list of stars (ie in the case of a hierarchical triple)
        ind_sibling = starrefs.index(label_sibling) if isinstance(label_sibling, str) else [starrefs.index(l) for l in label_sibling]
        comp_no = ['primary', 'secondary'].index(hier.get_primary_or_secondary(component))+1

        self_ps = b.filter(component=component, context='component', check_visible=False)
        requiv = self_ps.get_value('requiv', unit=u.solRad)

        masses = [b.get_value('mass', component=star, context='component', unit=u.solMass) for star in starrefs]
        if b.hierarchy.get_parent_of(component) is not None:
            sma = b.get_value('sma', component=label_orbit, context='component', unit=u.solRad)
            ecc = b.get_value('ecc', component=label_orbit, context='component')
            is_single = False
        else:
            # single star case
            sma = 1.0
            ecc = 0.0
            is_single = True

        incl = b.get_value('incl', component=label_orbit, context='component', unit=u.rad)
        long_an = b.get_value('long_an', component=label_orbit, context='component', unit=u.rad)

        # NOTE: these may not be used when not visible for contact systems, so
        # Star_roche_envelope_half should ignore and override with
        # aligned/synchronous
        incl_star = self_ps.get_value('incl', unit=u.rad, check_visible=False)
        long_an_star = self_ps.get_value('long_an', unit=u.rad, check_visible=False)
        polar_direction_uvw = mesh.spin_in_system(incl_star, long_an_star)
        # freq_rot for contacts will be provided by that subclass as 2*pi/P_orb since they're always synchronous
        freq_rot = self_ps.get_value('freq', unit=u.rad/u.d)

        t0 = b.get_value('t0', context='system', unit=u.d)

        teff = b.get_value('teff', component=component, context='component', unit=u.K)
        gravb_bol= b.get_value('gravb_bol', component=component, context='component')

        abun = b.get_value('abun', component=component, context='component', check_visible=False)
        irrad_frac_refl = b.get_value('irrad_frac_refl_bol', component=component, context='component')

        try:
            rv_grav_override = kwargs.pop('rv_grav', None)
            do_rv_grav = b.get_value('rv_grav', component=component, compute=compute, check_visible=False, rv_grav=rv_grav_override) if compute is not None else False
        except ValueError:
            # rv_grav may not have been copied to this component if no rvs are attached
            do_rv_grav = False

        mesh_method_override = kwargs.pop('mesh_method', None)
        mesh_method = b.get_value('mesh_method', component=component, compute=compute, mesh_method=mesh_method_override) if compute is not None else 'marching'

        if mesh_method == 'marching':
            ntriangles_override = kwargs.pop('ntriangle', None)
            kwargs['ntriangles'] = b.get_value('ntriangles', component=component, compute=compute, ntriangles=ntriangles_override) if compute is not None else 1000
            distortion_method_override = kwargs.pop('distortion_method', None)
            kwargs['distortion_method'] = b.get_value('distortion_method', component=component, compute=compute, distortion_method=distortion_method_override) if compute is not None else 'roche'
        elif mesh_method == 'wd':
            gridsize_override = kwargs.pop('gridsize', None)
            kwargs['gridsize'] = b.get_value('gridsize', component=component, compute=compute, gridsize=gridsize_override) if compute is not None else 30
        else:
            raise NotImplementedError

        features = []
        for feature in b.filter(component=component).features:
            feature_ps = b.filter(feature=feature, component=component)
            feature_cls = globals()[feature_ps.kind.title()]
            features.append(feature_cls.from_bundle(b, feature))

        if conf.devel:
            mesh_offset_override = kwargs.pop('mesh_offset', None)
            do_mesh_offset = b.get_value('mesh_offset', compute=compute, mesh_offset=mesh_offset_override)
        else:
            do_mesh_offset = True

        datasets_intens = [ds for ds in b.filter(kind=['lc', 'rv', 'lp'], context='dataset').datasets if ds != '_default']
        datasets_lp = [ds for ds in b.filter(kind='lp', context='dataset').datasets if ds != '_default']
        atm_override = kwargs.pop('atm', None)
        atm = b.get_value('atm', compute=compute, component=component, atm=atm_override) if compute is not None else 'blackbody'
        passband_override = kwargs.pop('passband', None)
        passband = {ds: b.get_value('passband', dataset=ds, passband=passband_override) for ds in datasets_intens}
        intens_weighting_override = kwargs.pop('intens_weighting', None)
        intens_weighting = {ds: b.get_value('intens_weighting', dataset=ds, intens_weighting=intens_weighting_override) for ds in datasets_intens}
        ld_func_override = kwargs.pop('ld_func', None)
        ld_func = {ds: b.get_value('ld_func', dataset=ds, component=component, ld_func=ld_func_override) for ds in datasets_intens}
        ld_coeffs_override = kwargs.pop('ld_coeffs', None)
        ld_coeffs = {ds: b.get_value('ld_coeffs', dataset=ds, component=component, check_visible=False, ld_coeffs=ld_coeffs_override) for ds in datasets_intens}
        ld_func_bol_override = kwargs.pop('ld_func_bol', None)
        ld_func['bol'] = b.get_value('ld_func_bol', component=component, context='component', check_visible=False, ld_func_bol=ld_func_bol_override)
        ld_coeffs_bol_override = kwargs.pop('ld_coeffs_bol', None)
        ld_coeffs['bol'] = b.get_value('ld_coeffs_bol', component=component, context='component', check_visible=False, ld_coeffs_bol=ld_coeffs_bol_override)
        profile_rest_override = kwargs.pop('profile_rest', None)
        lp_profile_rest = {ds: b.get_value('profile_rest', dataset=ds, unit=u.nm, profile_rest=profile_rest_override) for ds in datasets_lp}

        # we'll pass kwargs on here so they can be overridden by the classmethod
        # of any subclass and then intercepted again by the __init__ by the
        # same subclass.  Note: kwargs also hold meshing kwargs which are used
        # by Star.__init__
        return cls(component, comp_no, ind_self, ind_sibling,
                   masses, ecc,
                   incl, long_an, t0,
                   do_mesh_offset,
                   mesh_init_phi,

                   atm,
                   datasets,
                   passband,
                   intens_weighting,
                   ld_func,
                   ld_coeffs,
                   lp_profile_rest,
                   requiv,
                   sma,
                   polar_direction_uvw,
                   freq_rot,
                   teff,
                   gravb_bol,
                   abun,
                   irrad_frac_refl,
                   mesh_method,
                   is_single,
                   do_rv_grav,
                   features,
                   **kwargs
                   )


Instruction:
How would you code a function in Python 3 to
get current polar direction in Roche ( xyz coordinates

Response:
def polar_direction_xyz(self):
        """
        get current polar direction in Roche (xyz) coordinates
        """
        return mesh.spin_in_roche(self.polar_direction_uvw,
                                  self.true_anom, self.elongan, self.eincl).astype(float)


Instruction:
Can you tell what is the following Python 3 function doing
def get_target_volume(self, etheta=0.0, scaled=False):
        # TODO: make this a function of d instead of etheta?
        logger.debug("determining target volume at t={}, theta={}".format(self.time, etheta))

        # TODO: eventually this could allow us to "break" volume conservation
        # and have volume be a function of d, with some scaling factor provided
        # by the user as a parameter.  Until then, we'll assume volume is
        # conserved which means the volume should always be the same
        volume = 4./3 * np.pi * self.requiv**3

        if not scaled:
            return volume / self._scale**3
        else:
            return volume

Response: get the target volume of the object


Instruction:
Can you tell what is the following Python 3 function doing
def north_pole_uvw(self):
        # TODO: is this rpole scaling true for all distortion_methods??
        rpole = self.instantaneous_rpole*self.sma
        return self.polar_direction_uvw*rpole+self.mesh._pos

Response: location of the north pole in the global system frame


Instruction:
Here you have a function in Python 3, explain what it does
def _fill_loggs(self, mesh=None, ignore_effects=False):
        logger.debug("{}._fill_loggs".format(self.component))

        if mesh is None:
            mesh = self.mesh

        loggs = np.log10(mesh.normgrads.for_computations * g_rel_to_abs(self.masses[self.ind_self], self.sma))

        if not ignore_effects:
            for feature in self.features:
                if feature.proto_coords:
                    loggs = feature.process_loggs(loggs, mesh.roche_coords_for_computations, s=self.polar_direction_xyz, t=self.time)
                else:
                    loggs = feature.process_loggs(loggs, mesh.coords_for_computations, s=self.polar_direction_xyz, t=self.time)

        mesh.update_columns(loggs=loggs)

        if not self.needs_recompute_instantaneous:
            logger.debug("{}._fill_loggs: copying loggs to standard mesh".format(self.component))
            theta = 0.0
            self._standard_meshes[theta].update_columns(loggs=loggs)

Response: Fill the loggs of the current instance with the loggs of the current instance.


Instruction:
Implement a Python 3 function for
filling the gravbs of the current object with the current gravbs of the current object.

Response:
def _fill_gravs(self, mesh=None, **kwargs):
        """
        TODO: add documentation

        requires _fill_loggs to have been called
        """
        logger.debug("{}._fill_gravs".format(self.component))

        if mesh is None:
            mesh = self.mesh

        # TODO: rename 'gravs' to 'gdcs' (gravity darkening corrections)

        gravs = ((mesh.normgrads.for_computations * g_rel_to_abs(self.masses[self.ind_self], self.sma))/self.instantaneous_gpole)**self.gravb_bol

        mesh.update_columns(gravs=gravs)

        if not self.needs_recompute_instantaneous:
            logger.debug("{}._fill_gravs: copying gravs to standard mesh".format(self.component))
            theta = 0.0
            self._standard_meshes[theta].update_columns(gravs=gravs)


Instruction:
Explain what the following Python 3 code does
def _fill_teffs(self, mesh=None, ignore_effects=False, **kwargs):
        logger.debug("{}._fill_teffs".format(self.component))

        if mesh is None:
            mesh = self.mesh

        # Now we can compute the local temperatures.
        # see PHOEBE Legacy scientific reference eq 5.23
        teffs = self.instantaneous_tpole*mesh.gravs.for_computations**0.25

        if not ignore_effects:
            for feature in self.features:
                if feature.proto_coords:
                    teffs = feature.process_teffs(teffs, mesh.roche_coords_for_computations, s=self.polar_direction_xyz, t=self.time)
                else:
                    teffs = feature.process_teffs(teffs, mesh.coords_for_computations, s=self.polar_direction_xyz, t=self.time)

        mesh.update_columns(teffs=teffs)

        if not self.needs_recompute_instantaneous:
            logger.debug("{}._fill_teffs: copying teffs to standard mesh".format(self.component))
            theta = 0.0
            self._standard_meshes[theta].update_columns(teffs=teffs)

Response: r Fills the local temperatures of the given mesh with the local temperatures of the given instance of the class.


Instruction:
Make a summary of the following Python 3 code
def _fill_abuns(self, mesh=None, abun=0.0):
        logger.debug("{}._fill_abuns".format(self.component))

        if mesh is None:
            mesh = self.mesh

        # TODO: support from frontend

        mesh.update_columns(abuns=abun)

        if not self.needs_recompute_instantaneous:
            logger.debug("{}._fill_abuns: copying abuns to standard mesh".format(self.component))
            theta = 0.0
            self._standard_meshes[theta].update_columns(abuns=abun)

Response: Fill in the internal columns of the internal mesh.


Instruction:
How would you explain what the following Python 3 function does
def _fill_albedos(self, mesh=None, irrad_frac_refl=0.0):
        logger.debug("{}._fill_albedos".format(self.component))

        if mesh is None:
            mesh = self.mesh

        mesh.update_columns(irrad_frac_refl=irrad_frac_refl)

        if not self.needs_recompute_instantaneous:
            logger.debug("{}._fill_albedos: copying albedos to standard mesh".format(self.component))
            theta = 0.0
            self._standard_meshes[theta].update_columns(irrad_frac_refl=irrad_frac_refl)

Response: Fill in the albedos of the current instance of the class.


Instruction:
Can you tell what is the following Python 3 function doing
def compute_pblum_scale(self, dataset, pblum, **kwargs):
        logger.debug("{}.compute_pblum_scale(dataset={}, pblum={})".format(self.component, dataset, pblum))

        abs_luminosity = self.compute_luminosity(dataset, **kwargs)

        # We now want to remember the scale for all intensities such that the
        # luminosity in relative units gives the provided pblum
        pblum_scale = pblum / abs_luminosity

        self.set_pblum_scale(dataset, pblum_scale)

Response: Compute the pblum scale for all intensities in this dataset.


Instruction:
Can you write a function in Python 3 where it
populates columns necessary for an LP dataset

Response:
def _populate_lp(self, dataset, **kwargs):
        """
        Populate columns necessary for an LP dataset

        This should not be called directly, but rather via :meth:`Body.populate_observable`
        or :meth:`System.populate_observables`
        """
        logger.debug("{}._populate_lp(dataset={})".format(self.component, dataset))

        profile_rest = kwargs.get('profile_rest', self.lp_profile_rest.get(dataset))

        rv_cols = self._populate_rv(dataset, **kwargs)

        cols = rv_cols
        # rvs = (rv_cols['rvs']*u.solRad/u.d).to(u.m/u.s).value
        # cols['dls'] = rv_cols['rvs']*profile_rest/c.c.si.value

        return cols


Instruction:
Implement a Python 3 function for
populating the columns necessary for an RV dataset

Response:
def _populate_rv(self, dataset, **kwargs):
        """
        Populate columns necessary for an RV dataset

        This should not be called directly, but rather via :meth:`Body.populate_observable`
        or :meth:`System.populate_observables`
        """
        logger.debug("{}._populate_rv(dataset={})".format(self.component, dataset))

        # We need to fill all the flux-related columns so that we can weigh each
        # triangle's rv by its flux in the requested passband.
        lc_cols = self._populate_lc(dataset, **kwargs)

        # rv per element is just the z-component of the velocity vectory.  Note
        # the change in sign from our right-handed system to rv conventions.
        # These will be weighted by the fluxes when integrating

        rvs = -1*self.mesh.velocities.for_computations[:,2]

        # Gravitational redshift
        if self.do_rv_grav:
            rv_grav = c.G*(self.mass*u.solMass)/(self.instantaneous_rpole*u.solRad)/c.c
            # rvs are in solRad/d internally
            rv_grav = rv_grav.to('solRad/d').value

            rvs += rv_grav

        cols = lc_cols
        cols['rvs'] = rvs
        return cols


Instruction:
Write a Python 3 script to
populate the columns necessary for an LC dataset.

Response:
def _populate_lc(self, dataset, **kwargs):
        """
        Populate columns necessary for an LC dataset

        This should not be called directly, but rather via :meth:`Body.populate_observable`
        or :meth:`System.populate_observables`

        :raises NotImplementedError: if lc_method is not supported
        """
        logger.debug("{}._populate_lc(dataset={})".format(self.component, dataset))

        lc_method = kwargs.get('lc_method', 'numerical')  # TODO: make sure this is actually passed

        passband = kwargs.get('passband', self.passband.get(dataset, None))
        intens_weighting = kwargs.get('intens_weighting', self.intens_weighting.get(dataset, None))
        ld_func = kwargs.get('ld_func', self.ld_func.get(dataset, None))
        ld_coeffs = kwargs.get('ld_coeffs', self.ld_coeffs.get(dataset, None)) if ld_func != 'interp' else None
        atm = kwargs.get('atm', self.atm)
        boosting_method = kwargs.get('boosting_method', self.boosting_method)

        pblum = kwargs.get('pblum', 4*np.pi)

        if lc_method=='numerical':

            pb = passbands.get_passband(passband)

            if intens_weighting=='photon':
                ptfarea = pb.ptf_photon_area/pb.h/pb.c
            else:
                ptfarea = pb.ptf_area

            self.set_ptfarea(dataset, ptfarea)

            ldint = pb.ldint(Teff=self.mesh.teffs.for_computations,
                             logg=self.mesh.loggs.for_computations,
                             abun=self.mesh.abuns.for_computations,
                             atm=atm,
                             ld_func=ld_func,
                             ld_coeffs=ld_coeffs,
                             photon_weighted=intens_weighting=='photon')

            # abs_normal_intensities are the normal emergent passband intensities:
            abs_normal_intensities = pb.Inorm(Teff=self.mesh.teffs.for_computations,
                                              logg=self.mesh.loggs.for_computations,
                                              abun=self.mesh.abuns.for_computations,
                                              atm=atm,
                                              ldint=ldint,
                                              photon_weighted=intens_weighting=='photon')

            # abs_intensities are the projected (limb-darkened) passband intensities
            # TODO: why do we need to use abs(mus) here?
            abs_intensities = pb.Imu(Teff=self.mesh.teffs.for_computations,
                                     logg=self.mesh.loggs.for_computations,
                                     abun=self.mesh.abuns.for_computations,
                                     mu=abs(self.mesh.mus_for_computations),
                                     atm=atm,
                                     ldint=ldint,
                                     ld_func=ld_func,
                                     ld_coeffs=ld_coeffs,
                                     photon_weighted=intens_weighting=='photon')

            # Beaming/boosting
            if boosting_method == 'none':
                boost_factors = 1.0
            elif boosting_method == 'linear':
                bindex = pb.bindex(Teff=self.mesh.teffs.for_computations,
                                   logg=self.mesh.loggs.for_computations,
                                   abun=self.mesh.abuns.for_computations,
                                   mu=abs(self.mesh.mus_for_computations),
                                   atm=atm,
                                   photon_weighted=intens_weighting=='photon')

                boost_factors = 1.0 + bindex * self.mesh.velocities.for_computations[:,2]/37241.94167601236
            else:
                raise NotImplementedError("boosting_method='{}' not supported".format(self.boosting_method))

            # boosting is aspect dependent so we don't need to correct the
            # normal intensities
            abs_intensities *= boost_factors

            # Handle pblum - distance and l3 scaling happens when integrating (in observe)
            # we need to scale each triangle so that the summed normal_intensities over the
            # entire star is equivalent to pblum / 4pi
            normal_intensities = abs_normal_intensities * self.get_pblum_scale(dataset)
            intensities = abs_intensities * self.get_pblum_scale(dataset)

        elif lc_method=='analytical':
            raise NotImplementedError("analytical fluxes not yet supported")
            # TODO: this probably needs to be moved into observe or backends.phoebe
            # (assuming it doesn't result in per-triangle quantities)

        else:
            raise NotImplementedError("lc_method '{}' not recognized".format(lc_method))

        # TODO: do we really need to store all of these if store_mesh==False?
        # Can we optimize by only returning the essentials if we know we don't need them?
        return {'abs_normal_intensities': abs_normal_intensities,
                'normal_intensities': normal_intensities,
                'abs_intensities': abs_intensities,
                'intensities': intensities,
                'ldint': ldint,
                'boost_factors': boost_factors}


Instruction:
Given the following Python 3 function, write the documentation
def needs_remesh(self):
        # TODO: may be able to get away with removing the features check and just doing for pulsations, etc?
        # TODO: what about dpdt, deccdt, dincldt, etc?
        return len(self.features) > 0 or self.is_misaligned or self.ecc != 0 or self.dynamics_method != 'keplerian'

Response: Returns True if the star needs to be re - meshed.


Instruction:
Make a summary of the following Python 3 code
def _build_mesh(self, mesh_method, **kwargs):

        # need the sma to scale between Roche and real units
        sma = kwargs.get('sma', self.sma)  # Rsol (same units as coordinates)

        mesh_args = self.instantaneous_mesh_args

        if mesh_method == 'marching':
            # TODO: do this during mesh initialization only and then keep delta fixed in time??
            ntriangles = kwargs.get('ntriangles', self.ntriangles)

            # we need the surface area of the lobe to estimate the correct value
            # to pass for delta to marching.  We will later need the volume to
            # expose its value
            logger.debug("libphoebe.roche_area_volume{}".format(mesh_args))
            av = libphoebe.roche_area_volume(*mesh_args,
                                             choice=2,
                                             larea=True,
                                             lvolume=True)

            delta = _estimate_delta(ntriangles, av['larea'])

            logger.debug("libphoebe.roche_marching_mesh{}".format(mesh_args))
            new_mesh = libphoebe.roche_marching_mesh(*mesh_args,
                                                     delta=delta,
                                                     choice=2,
                                                     full=True,
                                                     max_triangles=ntriangles*2,
                                                     vertices=True,
                                                     triangles=True,
                                                     centers=True,
                                                     vnormals=True,
                                                     tnormals=True,
                                                     cnormals=False,
                                                     vnormgrads=True,
                                                     cnormgrads=False,
                                                     areas=True,
                                                     volume=False,
                                                     init_phi=self.mesh_init_phi)

            # In addition to the values exposed by the mesh itself, let's report
            # the volume and surface area of the lobe.  The lobe area is used
            # if mesh_offseting is required, and the volume is optionally exposed
            # to the user.
            new_mesh['volume'] = av['lvolume']  # * sma**3
            new_mesh['area'] = av['larea']      # * sma**2

            scale = sma

        elif mesh_method == 'wd':
            N = int(kwargs.get('gridsize', self.gridsize))

            # unpack mesh_args
            q, F, d, Phi = mesh_args

            the_grid = mesh_wd.discretize_wd_style(N, q, F, d, Phi)
            new_mesh = mesh.wd_grid_to_mesh_dict(the_grid, q, F, d)
            scale = sma

        else:
            raise NotImplementedError("mesh_method '{}' is not supported".format(mesh_method))

        return new_mesh, scale

Response: This function builds the mesh for a specific class of class


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _build_mesh(self, mesh_method, **kwargs):

        # if we don't provide instantaneous masses or smas, then assume they are
        # not time dependent - in which case they were already stored in the init
        sma = kwargs.get('sma', self.sma)  # Rsol (same units as coordinates)

        mesh_args = self.instantaneous_mesh_args

        if mesh_method == 'marching':
            ntriangles = kwargs.get('ntriangles', self.ntriangles)

            av = libphoebe.sphere_area_volume(*mesh_args,
                                              larea=True,
                                              lvolume=True)

            delta = _estimate_delta(ntriangles, av['larea'])

            new_mesh = libphoebe.sphere_marching_mesh(*mesh_args,
                                                      delta=delta,
                                                      full=True,
                                                      max_triangles=ntriangles*2,
                                                      vertices=True,
                                                      triangles=True,
                                                      centers=True,
                                                      vnormals=True,
                                                      tnormals=True,
                                                      cnormals=False,
                                                      vnormgrads=True,
                                                      cnormgrads=False,
                                                      areas=True,
                                                      volume=True,
                                                      init_phi=self.mesh_init_phi)

            # In addition to the values exposed by the mesh itself, let's report
            # the volume and surface area of the lobe.  The lobe area is used
            # if mesh_offseting is required, and the volume is optionally exposed
            # to the user.
            new_mesh['volume'] = av['lvolume']
            new_mesh['area'] = av['larea']

            scale = sma

        else:
            raise NotImplementedError("mesh_method '{}' is not supported".format(mesh_method))

        return new_mesh, scale

Response: Builds a mesh from the given parameters.


Instruction:
Can you write a function in Python 3 where it
populates the internal data structures of the observed data structures.

Response:
def populate_observable(self, time, kind, dataset, **kwargs):
        """
        TODO: add documentation
        """

        for half in self._halves:
            half.populate_observable(time, kind, dataset, **kwargs)


Instruction:
Implement a Python 3 function for
initializing a Spot feature from the bundle.

Response:
def from_bundle(cls, b, feature):
        """
        Initialize a Spot feature from the bundle.
        """

        feature_ps = b.get_feature(feature)

        colat = feature_ps.get_value('colat', unit=u.rad)
        longitude = feature_ps.get_value('long', unit=u.rad)

        if len(b.hierarchy.get_stars())>=2:
            star_ps = b.get_component(feature_ps.component)
            orbit_ps = b.get_component(b.hierarchy.get_parent_of(feature_ps.component))
            syncpar = star_ps.get_value('syncpar')
            period = orbit_ps.get_value('period')
            dlongdt = (syncpar - 1) / period * 2 * np.pi
        else:
            star_ps = b.get_component(feature_ps.component)
            dlongdt = star_ps.get_value('freq', unit=u.rad/u.d)
            longitude = np.pi/2

        radius = feature_ps.get_value('radius', unit=u.rad)
        relteff = feature_ps.get_value('relteff', unit=u.dimensionless_unscaled)

        t0 = b.get_value('t0', context='system', unit=u.d)

        return cls(colat, longitude, dlongdt, radius, relteff, t0)


Instruction:
Implement a function in Python 3 to
return the basis vectors in roche coordinates

Response:
def pointing_vector(self, s, time):
        """
        s is the spin vector in roche coordinates
        time is the current time
        """
        t = time - self._t0
        longitude = self._longitude + self._dlongdt * t

        # define the basis vectors in the spin (primed) coordinates in terms of
        # the Roche coordinates.
        # ez' = s
        # ex' =  (ex - s(s.ex)) /|i - s(s.ex)|
        # ey' = s x ex'
        ex = np.array([1., 0., 0.])
        ezp = s
        exp = (ex - s*np.dot(s,ex))
        eyp = np.cross(s, exp)

        return np.sin(self._colat)*np.cos(longitude)*exp +\
                  np.sin(self._colat)*np.sin(longitude)*eyp +\
                  np.cos(self._colat)*ezp


Instruction:
Make a summary of the following Python 3 code
def process_teffs(self, teffs, coords, s=np.array([0., 0., 1.]), t=None):
        if t is None:
            # then assume at t0
            t = self._t0

        pointing_vector = self.pointing_vector(s,t)
        logger.debug("spot.process_teffs at t={} with pointing_vector={} and radius={}".format(t, pointing_vector, self._radius))

        cos_alpha_coords = np.dot(coords, pointing_vector) / np.linalg.norm(coords, axis=1)
        cos_alpha_spot = np.cos(self._radius)

        filter_ = cos_alpha_coords > cos_alpha_spot
        teffs[filter_] = teffs[filter_] * self._relteff

        return teffs

Response: This function takes a set of teffs and a set of coordinates and returns a set of teffs that are within the spot and applies the relteff factor to those teffs.


Instruction:
Create a Python 3 function for
initializing a Pulsation feature from a bundle.

Response:
def from_bundle(cls, b, feature):
        """
        Initialize a Pulsation feature from the bundle.
        """

        feature_ps = b.get_feature(feature)
        freq = feature_ps.get_value('freq', unit=u.d**-1)
        radamp = feature_ps.get_value('radamp', unit=u.dimensionless_unscaled)
        l = feature_ps.get_value('l', unit=u.dimensionless_unscaled)
        m = feature_ps.get_value('m', unit=u.dimensionless_unscaled)
        teffext = feature_ps.get_value('teffext')

        GM = c.G.to('solRad3 / (solMass d2)').value*b.get_value(qualifier='mass', component=feature_ps.component, context='component', unit=u.solMass)
        R = b.get_value(qualifier='rpole', component=feature_ps.component, section='component', unit=u.solRad)

        tanamp = GM/R**3/freq**2

        return cls(radamp, freq, l, m, tanamp, teffext)


Instruction:
Given the following Python 3 function, write the documentation
def project_onto_potential(r, pot_name, *args):

    pot = globals()[pot_name]
    dpdx = globals()['d%sdx'%(pot_name)]
    dpdy = globals()['d%sdy'%(pot_name)]
    dpdz = globals()['d%sdz'%(pot_name)]
    dpdr = globals()['d%sdr'%(pot_name)]

    n_iter = 0

    rmag, rmag0 = np.sqrt((r*r).sum()), 0
    lam, nu = r[0]/rmag, r[2]/rmag
    dc = np.array((lam, np.sqrt(1-lam*lam-nu*nu), nu)) # direction cosines -- must not change during reprojection
    D, q, F, p0 = args

    while np.abs(rmag-rmag0) > 1e-12 and n_iter < 100:
        rmag0 = rmag
        rmag = rmag0 - pot(rmag0*dc, *args)/dpdr(rmag0*dc, *args[:-1])
        n_iter += 1
    if n_iter == 100:
        logger.warning('projection did not converge')

    r = rmag*dc

    return MeshVertex(r, dpdx, dpdy, dpdz, *args[:-1])

Response: project a mesh onto a potential


Instruction:
Can you tell what is the following Python 3 function doing
def open(cls, filename):
        filename = os.path.expanduser(filename)
        logger.debug("importing from {}".format(filename))
        f = open(filename, 'r')
        data = json.load(f, object_pairs_hook=parse_json)
        f.close()
        b = cls(data)

        version = b.get_value('phoebe_version')
        phoebe_version_import = StrictVersion(version if version != 'devel' else '2.1.2')
        phoebe_version_this = StrictVersion(__version__ if __version__ != 'devel' else '2.1.2')

        logger.debug("importing from PHOEBE v {} into v {}".format(phoebe_version_import, phoebe_version_this))

        # update the entry in the PS, so if this is saved again it will have the new version
        b.set_value('phoebe_version', __version__)

        if phoebe_version_import == phoebe_version_this:
            return b
        elif phoebe_version_import > phoebe_version_this:
            warning = "importing from a newer version ({}) of PHOEBE, this may or may not work, consider updating".format(phoebe_version_import)
            print("WARNING: {}".format(warning))
            logger.warning(warning)
            return b

        if phoebe_version_import < StrictVersion("2.1.2"):
            b._import_before_v211 = True
            warning = "Importing from an older version ({}) of PHOEBE which did not support constraints in solar units.  All constraints will remain in SI, but calling set_hierarchy will likely fail.".format(phoebe_version_import)
            print("WARNING: {}".format(warning))
            logger.warning(warning)

        if phoebe_version_import < StrictVersion("2.1.0"):
            logger.warning("importing from an older version ({}) of PHOEBE into version {}".format(phoebe_version_import, phoebe_version_this))

            def _ps_dict(ps):
                return {p.qualifier: p.get_quantity() if hasattr(p, 'get_quantity') else p.get_value() for p in ps.to_list()}

            # rpole -> requiv: https://github.com/phoebe-project/phoebe2/pull/300
            dict_stars = {}
            for star in b.hierarchy.get_stars():
                ps_star = b.filter(context='component', component=star)
                dict_stars[star] = _ps_dict(ps_star)

                # TODO: actually do the translation
                rpole = dict_stars[star].pop('rpole', 1.0*u.solRad).to(u.solRad).value
                # PHOEBE 2.0 didn't have syncpar for contacts
                if len(b.filter('syncpar', component=star)):
                    F = b.get_value('syncpar', component=star, context='component')
                else:
                    F = 1.0
                parent_orbit = b.hierarchy.get_parent_of(star)
                component = b.hierarchy.get_primary_or_secondary(star, return_ind=True)
                sma = b.get_value('sma', component=parent_orbit, context='component', unit=u.solRad)
                q = b.get_value('q', component=parent_orbit, context='component')
                d = 1 - b.get_value('ecc', component=parent_orbit)

                logger.info("roche.rpole_to_requiv_aligned(rpole={}, sma={}, q={}, F={}, d={}, component={})".format(rpole, sma, q, F, d, component))
                dict_stars[star]['requiv'] = roche.rpole_to_requiv_aligned(rpole, sma, q, F, d, component=component)

                b.remove_component(star)

            for star, dict_star in dict_stars.items():
                logger.info("attempting to update component='{}' to new version requirements".format(star))
                b.add_component('star', component=star, check_label=False, **dict_star)

            dict_envs = {}
            for env in b.hierarchy.get_envelopes():
                ps_env = b.filter(context='component', component=env)
                dict_envs[env] = _ps_dict(ps_env)
                b.remove_component(env)

            for env, dict_env in dict_envs.items():
                logger.info("attempting to update component='{}' to new version requirements".format(env))
                b.add_component('envelope', component=env, check_label=False, **dict_env)

                # TODO: this probably will fail once more than one contacts are
                # supported, but will never need that for 2.0->2.1 since
                # multiples aren't supported (yet) call b.set_hierarchy() to

                # reset all hieararchy-dependent constraints (including
                # pot<->requiv)
                b.set_hierarchy()

                primary = b.hierarchy.get_stars()[0]
                b.flip_constraint('pot', component=env, solve_for='requiv@{}'.format(primary), check_nan=False)
                b.set_value('pot', component=env, context='component', value=dict_env['pot'])
                b.flip_constraint('requiv', component=primary, solve_for='pot', check_nan=False)

            # reset all hieararchy-dependent constraints
            b.set_hierarchy()

            # mesh datasets: https://github.com/phoebe-project/phoebe2/pull/261, https://github.com/phoebe-project/phoebe2/pull/300
            for dataset in b.filter(context='dataset', kind='mesh').datasets:
                logger.info("attempting to update mesh dataset='{}' to new version requirements".format(dataset))
                ps_mesh = b.filter(context='dataset', kind='mesh', dataset=dataset)
                dict_mesh = _ps_dict(ps_mesh)
                # NOTE: we will not remove (or update) the dataset from any existing models
                b.remove_dataset(dataset, context=['dataset', 'constraint', 'compute'])
                if len(b.filter(dataset=dataset, context='model')):
                    logger.warning("existing model for dataset='{}' models={} will not be removed, but likely will not work with new plotting updates".format(dataset, b.filter(dataset=dataset, context='model').models))

                b.add_dataset('mesh', dataset=dataset, check_label=False, **dict_mesh)

            # vgamma definition: https://github.com/phoebe-project/phoebe2/issues/234
            logger.info("updating vgamma to new version requirements")
            b.set_value('vgamma', -1*b.get_value('vgamma'))

            # remove phshift parameter: https://github.com/phoebe-project/phoebe2/commit/1fa3a4e1c0f8d80502101e1b1e750f5fb14115cb
            logger.info("removing any phshift parameters for new version requirements")
            b.remove_parameters_all(qualifier='phshift')

            # colon -> long: https://github.com/phoebe-project/phoebe2/issues/211
            logger.info("removing any colon parameters for new version requirements")
            b.remove_parameters_all(qualifier='colon')

            # make sure constraints are updated according to conf.interactive_constraints
            b.run_delayed_constraints()

        return b

Response: Open a new bundle from a JSON - formatted PHOEBE 2 file. This is a constructor so should be called as : class:`Bundle` object.


Instruction:
Write a Python 3 script to
load a new bundle from a phoebe server.

Response:
def from_server(cls, bundleid, server='http://localhost:5555',
                    as_client=True):
        """Load a new bundle from a server.

        [NOT IMPLEMENTED]

        Load a bundle from a phoebe server.  This is a constructor so should be
        called as:

        >>> b = Bundle.from_server('asdf', as_client=False)

        :parameter str bundleid: the identifier given to the bundle by the
            server
        :parameter str server: the host (and port) of the server
        :parameter bool as_client: whether to attach in client mode
            (default: True)
        """
        if not conf.devel:
            raise NotImplementedError("'from_server' not officially supported for this release.  Enable developer mode to test.")

        # TODO: run test message on server, if localhost and fails, attempt to
        # launch?
        url = "{}/{}/json".format(server, bundleid)
        logger.info("downloading bundle from {}".format(url))
        r = requests.get(url, timeout=5)
        rjson = r.json()

        b = cls(rjson['data'])

        if as_client:
            b.as_client(as_client, server=server,
                        bundleid=rjson['meta']['bundleid'])

            logger.warning("This bundle is in client mode, meaning all\
            computations will be handled by the server at {}.  To disable\
            client mode, call as_client(False) or in the future pass\
            as_client=False to from_server".format(server))

        return b


Instruction:
Explain what the following Python 3 code does
def from_legacy(cls, filename, add_compute_legacy=True, add_compute_phoebe=True):
        logger.warning("importing from legacy is experimental until official 1.0 release")
        filename = os.path.expanduser(filename)
        return io.load_legacy(filename, add_compute_legacy, add_compute_phoebe)

Response: Load a bundle from a PHOEBE 1. 0 Legacy file.


Instruction:
How would you code a function in Python 3 to
load a bundle with a default triple system.

Response:
def default_triple(cls, inner_as_primary=True, inner_as_overcontact=False,
                       starA='starA', starB='starB', starC='starC',
                       inner='inner', outer='outer',
                       contact_envelope='contact_envelope'):
        """Load a bundle with a default triple system.

        Set inner_as_primary based on what hierarchical configuration you want.

        inner_as_primary = True:

        starA - starB -- starC

        inner_as_primary = False:

        starC -- starA - starB

        This is a constructor, so should be called as:

        >>> b = Bundle.default_triple_primary()

        :parameter bool inner_as_primary: whether the inner-binary should be
            the primary component of the outer-orbit
        :return: instantiated :class:`Bundle` object
        """
        if not conf.devel:
            raise NotImplementedError("'default_triple' not officially supported for this release.  Enable developer mode to test.")

        b = cls()
        b.add_star(component=starA)
        b.add_star(component=starB)
        b.add_star(component=starC)
        b.add_orbit(component=inner, period=1)
        b.add_orbit(component=outer, period=10)

        if inner_as_overcontact:
            b.add_envelope(component=contact_envelope)
            inner_hier = _hierarchy.binaryorbit(b[inner],
                                           b[starA],
                                           b[starB],
                                           b[contact_envelope])
        else:
            inner_hier = _hierarchy.binaryorbit(b[inner], b[starA], b[starB])

        if inner_as_primary:
            hierstring = _hierarchy.binaryorbit(b[outer], inner_hier, b[starC])
        else:
            hierstring = _hierarchy.binaryorbit(b[outer], b[starC], inner_hier)
        b.set_hierarchy(hierstring)

        b.add_constraint(constraint.keplers_third_law_hierarchical,
                         outer, inner)

        # TODO: does this constraint need to be rebuilt when things change?
        # (ie in set_hierarchy)

        b.add_compute()

        return b


Instruction:
Write a Python 3 script for
saving the bundle to a JSON - formatted ASCII file.

Response:
def save(self, filename, clear_history=True, incl_uniqueid=False,
             compact=False):
        """Save the bundle to a JSON-formatted ASCII file.

        :parameter str filename: relative or full path to the file
        :parameter bool clear_history: whether to clear history log
            items before saving (default: True)
        :parameter bool incl_uniqueid: whether to including uniqueids in the
            file (only needed if its necessary to maintain the uniqueids when
            reloading)
        :parameter bool compact: whether to use compact file-formatting (maybe
            be quicker to save/load, but not as easily readable)
        :return: the filename
        """
        if clear_history:
            # TODO: let's not actually clear history,
            # but rather skip the context when saving
            self.remove_history()

        # TODO: add option for clear_models, clear_feedback
        # NOTE: PS.save will handle os.path.expanduser
        return super(Bundle, self).save(filename, incl_uniqueid=incl_uniqueid,
                                        compact=compact)


Instruction:
Create a Python 3 function for
exporting the current object to a legacy file.

Response:
def export_legacy(self, filename):
        """
        TODO: add docs
        """
        logger.warning("exporting to legacy is experimental until official 1.0 release")
        filename = os.path.expanduser(filename)
        return io.pass_to_legacy(self, filename)


Instruction:
How would you explain what the following Python 3 function does
def _on_socket_push_updates(self, resp):
        # TODO: check to make sure resp['meta']['bundleid']==bundleid ?
        # TODO: handle added parameters
        # TODO: handle removed (isDeleted) parameters

        for item in resp['data']:
            if item['id'] in self.uniqueids:
                # then we're updating something in the parameter (or deleting)
                param = self.get_parameter(uniqueid=item['id'])
                for attr, value in item['attributes'].items():
                    if hasattr(param, "_{}".format(attr)):
                        logger.info("updates from server: setting {}@{}={}".
                                    format(attr, param.twig, value))
                        setattr(param, "_{}".format(attr), value)
            else:
                self._attach_param_from_server(item)

Response: Handle incoming socket push updates from server


Instruction:
How would you code a function in Python 3 to
attach a parameter to the bundle based on the item.

Response:
def _attach_param_from_server(self, item):
        """
        [NOT IMPLEMENTED]
        """
        if isinstance(item, list):
            for itemi in item:
                self._attach_param_from_server(itemi)
        else:
            # then we need to add a new parameter
            d = item['attributes']
            d['uniqueid'] = item['id']
            param = parameters.parameter_from_json(d, bundle=self)

            metawargs = {}
            self._attach_params([param], **metawargs)


Instruction:
Can you generate the documentation for the following Python 3 function
def as_client(self, as_client=True, server='http://localhost:5555',
                  bundleid=None):
        """
        [NOT IMPLEMENTED]
        """
        if as_client:
            if not _can_client:
                raise ImportError("dependencies to support client mode not met - see docs")

            server_running = self._test_server(server=server,
                                               start_if_fail=True)
            if not server_running:
                raise ValueError("server {} is not running".format(server))

            server_split = server.split(':')
            host = ':'.join(server_split[:-1])
            port = int(float(server_split[-1] if len(server_split) else 8000))
            self._socketio = SocketIO(host, port, BaseNamespace)
            self._socketio.on('connect', self._on_socket_connect)
            self._socketio.on('disconnect', self._on_socket_disconnect)

            self._socketio.on('push updates', self._on_socket_push_updates)

            if not bundleid:
                upload_url = "{}/upload".format(server)
                logger.info("uploading bundle to server {}".format(upload_url))
                data = json.dumps(self.to_json(incl_uniqueid=True))
                r = requests.post(upload_url, data=data, timeout=5)
                bundleid = r.json()['meta']['bundleid']

            self._socketio.emit('subscribe bundle', {'bundleid': bundleid})

            self._bundleid = bundleid

            self._is_client = server
            logger.info("connected as client to server at {}:{}".
                        format(host, port))

        else:
            logger.warning("This bundle is now permanently detached from the instance\
                on the server and will not receive future updates.  To start a client\
                in sync with the version on the server or other clients currently \
                subscribed, you must instantiate a new bundle with Bundle.from_server.")

            if hasattr(self, '_socketIO') and self._socketIO is not None:
                self._socketio.emit('unsubscribe bundle', {'bundleid': bundleid})
                self._socketIO.disconnect()
                self._socketIO = None

            self._bundleid = None
            self._is_client = False

Response: Subscribe to the server and set as_client flag.


Instruction:
Implement a Python 3 function for
updating the bundle with the latest entries from the client.

Response:
def client_update(self):
        """
        [NOT IMPLEMENTED]
        """
        if not self.is_client:
            raise ValueError("Bundle is not in client mode, cannot update")

        logger.info("updating client...")
        # wait briefly to pickup any missed messages, which should then fire
        # the corresponding callbacks and update the bundle
        self._socketio.wait(seconds=1)
        self._last_client_update = datetime.now()


Instruction:
Can you generate the documentation for the following Python 3 function
def _default_label(self, base, context, **kwargs):

        kwargs['context'] = context
        params = len(getattr(self.filter(check_visible=False,**kwargs), '{}s'.format(context)))

        return "{}{:02d}".format(base, params+1)

Response: This function returns a default label given a base label and a context and keyword arguments


Instruction:
Explain what the following Python 3 code does
def get_setting(self, twig=None, **kwargs):
        if twig is not None:
            kwargs['twig'] = twig
        kwargs['context'] = 'setting'
        return self.filter_or_get(**kwargs)

Response: Filter in the setting context


Instruction:
Create a Python 3 function for
adding a new log to the history

Response:
def _add_history(self, redo_func, redo_kwargs, undo_func, undo_kwargs,
                     **kwargs):
        """
        Add a new log (undo/redoable) to this history context

        :parameter str redo_func: function to redo the action, must be a
            method of :class:`Bundle`
        :parameter dict redo_kwargs: kwargs to pass to the redo_func.  Each
            item must be serializable (float or str, not objects)
        :parameter str undo_func: function to undo the action, must be a
            method of :class:`Bundle`
        :parameter dict undo_kwargs: kwargs to pass to the undo_func.  Each
            item must be serializable (float or str, not objects)
        :parameter str history: label of the history parameter
        :raises ValueError: if the label for this history item is forbidden or
            already exists
        """
        if not self.history_enabled:
            return

        param = HistoryParameter(self, redo_func, redo_kwargs,
                                 undo_func, undo_kwargs)

        metawargs = {'context': 'history',
                     'history': kwargs.get('history', self._default_label('hist', **{'context': 'history'}))}

        self._check_label(metawargs['history'])

        self._attach_params([param], **metawargs)


Instruction:
Explain what the following Python 3 code does
def get_history(self, i=None):
        ps = self.filter(context='history')
        # if not len(ps):
        #    raise ValueError("no history recorded")

        if i is not None:
            return ps.to_list()[i]
        else:
            return ps

Response: Get a history item by index.


Instruction:
Make a summary of the following Python 3 code
def remove_history(self, i=None):
        if i is None:
            self.remove_parameters_all(context='history')
        else:
            param = self.get_history(i=i)
            self.remove_parameter(uniqueid=param.uniqueid)

Response: Removes a history item from the bundle by index.


Instruction:
Given the following Python 3 function, write the documentation
def undo(self, i=-1):

        _history_enabled = self.history_enabled
        param = self.get_history(i)
        self.disable_history()
        param.undo()
        # TODO: do we really want to remove this?  then what's the point of redo?
        self.remove_parameter(uniqueid=param.uniqueid)
        if _history_enabled:
            self.enable_history()

Response: Undo an item in the history logs


Instruction:
Write a Python 3 script to
set the hierarchy of the current system.

Response:
def set_hierarchy(self, *args, **kwargs):
        """
        Set the hierarchy of the system.

        See tutorial on building a system.

        TODO: provide documentation
        args can be
        - string representation (preferably passed through hierarchy already)
        - func and strings/PSs/params to pass to function
        """

        if self._import_before_v211:
            raise ValueError("This bundle was created before constraints in solar units were supported and therefore cannot call set_hierarchy.  Either downgrade PHOEBE or re-create this system from scratch if you need to change the hierarchy.")

        # need to run any constraints since some may be deleted and rebuilt
        changed_params = self.run_delayed_constraints()

        _old_param = self.get_hierarchy()

        if len(args) == 1 and isinstance(args[0], str):
            repr_ = args[0]
            kind = None

        elif len(args) == 0:
            if 'value' in kwargs.keys():
                repr_ = kwargs['value']
                kind = None
            else:
                repr_ = self.get_hierarchy().get_value()
                kind = None

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

            repr_ = func(*func_args)

            kind = func.func_name

        hier_param = HierarchyParameter(value=repr_,
                                        description='Hierarchy representation')

        self.remove_parameters_all(qualifier='hierarchy', context='system')

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

        # cache hierarchy param so we don't need to do a filter everytime we
        # want to access it in is_visible, etc
        self._hierarchy_param = hier_param

        self._handle_pblum_defaults()
        # self._handle_dataset_selectparams()

        # Handle inter-PS constraints
        starrefs = hier_param.get_stars()

        # user_interactive_constraints = conf.interactive_constraints
        # conf.interactive_constraints_off()

        for component in self.hierarchy.get_envelopes():
            # we need two of the three [comp_env] + self.hierarchy.get_siblings_of(comp_env) to have constraints
            logger.debug('re-creating requiv constraints')
            existing_requiv_constraints = self.filter(constraint_func='requiv_to_pot', component=[component]+self.hierarchy.get_siblings_of(component))
            if len(existing_requiv_constraints) == 2:
                # do we need to rebuild these?
                continue
            elif len(existing_requiv_constraints)==0:
                for component_requiv in self.hierarchy.get_siblings_of(component):
                    pot_parameter = self.get_parameter(qualifier='pot', component=self.hierarchy.get_envelope_of(component_requiv), context='component')
                    requiv_parameter = self.get_parameter(qualifier='requiv', component=component_requiv, context='component')
                    if len(pot_parameter.constrained_by):
                        solve_for = requiv_parameter.uniquetwig
                    else:
                        solve_for = pot_parameter.uniquetwig

                    self.add_constraint(constraint.requiv_to_pot, component_requiv,
                                        constraint=self._default_label('requiv_to_pot', context='constraint'),
                                        solve_for=solve_for)
            else:
                raise NotImplementedError("expected 0 or 2 existing requiv_to_pot constraints")

            logger.debug('re-creating fillout_factor (contact) constraint for {}'.format(component))
            if len(self.filter(context='constraint',
                               constraint_func='fillout_factor',
                               component=component)):
                constraint_param = self.get_constraint(constraint_func='fillout_factor',
                                                       component=component)
                self.remove_constraint(constraint_func='fillout_factor',
                                       component=component)
                self.add_constraint(constraint.fillout_factor, component,
                                    solve_for=constraint_param.constrained_parameter.uniquetwig,
                                    constraint=constraint_param.constraint)
            else:
                self.add_constraint(constraint.fillout_factor, component,
                                    constraint=self._default_label('fillout_factor', context='constraint'))

            logger.debug('re-creating pot_min (contact) constraint for {}'.format(component))
            if len(self.filter(context='constraint',
                               constraint_func='potential_contact_min',
                               component=component)):
                constraint_param = self.get_constraint(constraint_func='potential_contact_min',
                                                       component=component)
                self.remove_constraint(constraint_func='potential_contact_min',
                                       component=component)
                self.add_constraint(constraint.potential_contact_min, component,
                                    solve_for=constraint_param.constrained_parameter.uniquetwig,
                                    constraint=constraint_param.constraint)
            else:
                self.add_constraint(constraint.potential_contact_min, component,
                                    constraint=self._default_label('pot_min', context='constraint'))

            logger.debug('re-creating pot_max (contact) constraint for {}'.format(component))
            if len(self.filter(context='constraint',
                               constraint_func='potential_contact_max',
                               component=component)):
                constraint_param = self.get_constraint(constraint_func='potential_contact_max',
                                                       component=component)
                self.remove_constraint(constraint_func='potential_contact_max',
                                       component=component)
                self.add_constraint(constraint.potential_contact_max, component,
                                    solve_for=constraint_param.constrained_parameter.uniquetwig,
                                    constraint=constraint_param.constraint)
            else:
                self.add_constraint(constraint.potential_contact_max, component,
                                    constraint=self._default_label('pot_max', context='constraint'))

        for component in self.hierarchy.get_stars():
            if len(starrefs)==1:
                pass
                # we'll do the potential constraint either way
            else:
                logger.debug('re-creating mass constraint for {}'.format(component))
                # TODO: will this cause problems if the constraint has been flipped?
                if len(self.filter(context='constraint',
                                   constraint_func='mass',
                                component=component)):
                    constraint_param = self.get_constraint(constraint_func='mass',
                                                           component=component)
                    self.remove_constraint(constraint_func='mass',
                                           component=component)
                    self.add_constraint(constraint.mass, component,
                                        solve_for=constraint_param.constrained_parameter.uniquetwig,
                                        constraint=constraint_param.constraint)
                else:
                    self.add_constraint(constraint.mass, component,
                                        constraint=self._default_label('mass', context='constraint'))

                logger.debug('re-creating comp_sma constraint for {}'.format(component))
                # TODO: will this cause problems if the constraint has been flipped?
                if len(self.filter(context='constraint',
                                   constraint_func='comp_sma',
                                   component=component)):
                    constraint_param = self.get_constraint(constraint_func='comp_sma',
                                                           component=component)
                    self.remove_constraint(constraint_func='comp_sma',
                                           component=component)
                    self.add_constraint(constraint.comp_sma, component,
                                        solve_for=constraint_param.constrained_parameter.uniquetwig,
                                        constraint=constraint_param.constraint)
                else:
                    self.add_constraint(constraint.comp_sma, component,
                                        constraint=self._default_label('comp_sma', context='constraint'))

                logger.debug('re-creating rotation_period constraint for {}'.format(component))
                # TODO: will this cause problems if the constraint has been flipped?
                if len(self.filter(context='constraint',
                                   constraint_func='rotation_period',
                                   component=component)):
                    constraint_param = self.get_constraint(constraint_func='rotation_period',
                                                           component=component)
                    self.remove_constraint(constraint_func='rotation_period',
                                           component=component)
                    self.add_constraint(constraint.rotation_period, component,
                                        solve_for=constraint_param.constrained_parameter.uniquetwig,
                                        constraint=constraint_param.constraint)
                else:
                    self.add_constraint(constraint.rotation_period, component,
                                        constraint=self._default_label('rotation_period', context='constraint'))

                if self.hierarchy.is_contact_binary(component):
                    # then we're in a contact binary and need to create pot<->requiv constraints
                    # NOTE: pot_min and pot_max are handled above at the envelope level
                    logger.debug('re-creating requiv_detached_max (contact) constraint for {}'.format(component))
                    if len(self.filter(context='constraint',
                                       constraint_func='requiv_detached_max',
                                       component=component)):
                        # then we're changing from detached to contact so should remove the detached constraint first
                        self.remove_constraint(constraint_func='requiv_detached_max', component=component)

                    logger.debug('re-creating requiv_contact_max (contact) constraint for {}'.format(component))
                    if len(self.filter(context='constraint',
                                       constraint_func='requiv_contact_max',
                                       component=component)):
                        constraint_param = self.get_constraint(constraint_func='requiv_contact_max',
                                                               component=component)
                        self.remove_constraint(constraint_func='requiv_contact_max',
                                               component=component)
                        self.add_constraint(constraint.requiv_contact_max, component,
                                            solve_for=constraint_param.constrained_parameter.uniquetwig,
                                            constraint=constraint_param.constraint)
                    else:
                        self.add_constraint(constraint.requiv_contact_max, component,
                                            constraint=self._default_label('requiv_max', context='constraint'))

                    logger.debug('re-creating requiv_contact_min (contact) constraint for {}'.format(component))
                    if len(self.filter(context='constraint',
                                       constraint_func='requiv_contact_min',
                                       component=component)):
                        constraint_param = self.get_constraint(constraint_func='requiv_contact_min',
                                                               component=component)
                        self.remove_constraint(constraint_func='requiv_contact_min',
                                               component=component)
                        self.add_constraint(constraint.requiv_contact_min, component,
                                            solve_for=constraint_param.constrained_parameter.uniquetwig,
                                            constraint=constraint_param.constraint)
                    else:
                        self.add_constraint(constraint.requiv_contact_min, component,
                                            constraint=self._default_label('requiv_min', context='constraint'))

                else:
                    # then we're in a detached/semi-detached system
                    # let's make sure we remove any requiv_to_pot constraints
                    if len(self.filter(context='constraint',
                                       constraint_func='requiv_to_pot',
                                       component=component)):
                        self.remove_constraint(constraint_func='requiv_to_pot', component=component)

                    logger.debug('re-creating requiv_max (detached) constraint for {}'.format(component))
                    if len(self.filter(context='constraint',
                                       constraint_func='requiv_contact_max',
                                       component=component)):
                        # then we're changing from contact to detached so should remove the detached constraint first
                        self.remove_constraint(constraint_func='requiv_contact_max', component=component)

                    logger.debug('re-creating requiv_detached_max (detached) constraint for {}'.format(component))
                    if len(self.filter(context='constraint',
                                       constraint_func='requiv_detached_max',
                                       component=component)):
                        constraint_param = self.get_constraint(constraint_func='requiv_detached_max',
                                                               component=component)
                        self.remove_constraint(constraint_func='requiv_detached_max',
                                               component=component)
                        self.add_constraint(constraint.requiv_detached_max, component,
                                            solve_for=constraint_param.constrained_parameter.uniquetwig,
                                            constraint=constraint_param.constraint)
                    else:
                        self.add_constraint(constraint.requiv_detached_max, component,
                                            constraint=self._default_label('requiv_max', context='constraint'))

                    logger.debug('re-creating pitch constraint for {}'.format(component))
                    # TODO: will this cause problems if the constraint has been flipped?
                    # TODO: what if the user disabled/removed this constraint?
                    if len(self.filter(context='constraint',
                                       constraint_func='pitch',
                                       component=component)):
                        constraint_param = self.get_constraint(constraint_func='pitch',
                                                               component=component)
                        self.remove_constraint(constraint_func='pitch',
                                               component=component)
                        self.add_constraint(constraint.pitch, component,
                                            solve_for=constraint_param.constrained_parameter.uniquetwig,
                                            constraint=constraint_param.constraint)
                    else:
                        self.add_constraint(constraint.pitch, component,
                                            constraint=self._default_label('pitch', context='constraint'))

                    logger.debug('re-creating yaw constraint for {}'.format(component))
                    # TODO: will this cause problems if the constraint has been flipped?
                    # TODO: what if the user disabled/removed this constraint?
                    if len(self.filter(context='constraint',
                                       constraint_func='yaw',
                                    component=component)):
                        constraint_param = self.get_constraint(constraint_func='yaw',
                                                               component=component)
                        self.remove_constraint(constraint_func='yaw',
                                               component=component)
                        self.add_constraint(constraint.yaw, component,
                                            solve_for=constraint_param.constrained_parameter.uniquetwig,
                                            constraint=constraint_param.constraint)
                    else:
                        self.add_constraint(constraint.yaw, component,
                                            constraint=self._default_label('yaw', context='constraint'))

        # if user_interactive_constraints:
            # conf.interactive_constraints_on()
            # self.run_delayed_constraints()

        redo_kwargs = {k: v for k, v in hier_param.to_dict().items()
                       if v not in [None, ''] and
                       k not in ['uniqueid', 'uniquetwig', 'twig',
                                 'Class', 'context', 'qualifier',
                                 'description']}
        if _old_param is None:
            # this will fake the undo-ability to raise an error saying it
            # cannot be undone
            undo_kwargs = {'uniqueid': None}
        else:
            undo_kwargs = {k: v for k, v in _old_param.to_dict().items()
                           if v not in [None, ''] and
                           k not in ['uniqueid', 'uniquetwig', 'twig',
                                     'Class', 'context', 'qualifier',
                                     'description']}
        self._add_history(redo_func='set_hierarchy',
                          redo_kwargs=redo_kwargs,
                          undo_func='set_hierarchy',
                          undo_kwargs=undo_kwargs)

        return


Instruction:
Implement a Python 3 function for
returning a new ParameterSet with only the system tags in the current context

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

        :parameter str twig: twig to use for filtering
        :parameter **kwargs: any other tags to do the filter
            (except twig or context)

        :return: :class:`phoebe.parameters.parameters.Parameter` or
            :class:`phoebe.parameters.parameters.ParameterSet`
        """
        if twig is not None:
            kwargs['twig'] = twig
        kwargs['context'] = 'system'
        return self.filter(**kwargs)