Instruction:
Make a summary of the following Python 3 code
def compute_frac_areas(new_mesh,xmin):

    '''Computes fractional areas belonging to each triangle vertex that are a result
    of the intersection with the neck plane and assigns them to each vertex per triangle.'''

    def intersection(point1,point2,xmin):
        ''' point1 = (x1,y1,z1), point2 = (x2,y2,z2
        parameters for matrices: a1=(z2-z1)/(x2-x1), b1=0, c1=-1, d1=z1-(z2-z1)/(x2-x1)*x1
                                 a2= , b2=(z2-z1)/(y2-y1), c2=-1, d2=z1-(z2-z1)/(y2-y1)*y1
                                 a3=1, b3=0, c3=0, d3=-xmin'''

        a1 = (point2[2]-point1[2])/(point2[0]-point1[0])
        b1 = 0.
        c1 = -1.
        d1 = point1[2] - point1[0]*(point2[2]-point1[2])/(point2[0]-point1[0])

        b2 = (point2[2]-point1[2])/(point2[1]-point1[1])
        a2 = 0.
        c1 = -1.
        d1 = point1[2] - point1[1]*(point2[2]-point1[2])/(point2[1]-point1[1])

        a3, b3, c3, d3 = 1., 0., 0., (-1)*xmin

        R_c = np.array([[a1,b1,c1],[a2,b2,c2],[a3,b3,c3]])
        R_d = np.array([[a1,b1,c1,d1],[a2,b2,c2,d2],[a3,b3,c3,d3]])

        # condition for one-point intersection
        if np.linalg.matrix_rank(R_c)==3 and np.linalg.matrix_rank(R_d)==3:
            # build the arrays whose determinants are used to compute the intersection coords
            x_arr = np.array([[d1,b1,c1],[d2,b2,c2],[d3,b3,c3]])
            y_arr = np.array([[a1,d1,c1],[a2,d2,c2],[a3,d3,c3]])
            z_arr = np.array([[a1,b1,d1],[a2,b2,d2],[a3,b3,d3]])

            x = np.linalg.det(x_arr)/np.linalg.det(R_c)
            y = np.linalg.det(y_arr)/np.linalg.det(R_c)
            z = np.linalg.det(z_arr)/np.linalg.det(R_c)

        # next we need to check whether the point is actually on the line section that makes the triangle
        x_low,x_up = min(point1[0],point2[0]),max(point1[0],point2[0])
        y_low,y_up = min(point1[1],point2[1]),max(point1[1],point2[1])
        z_low,z_up = min(point1[2],point2[2]),max(point1[2],point2[2])

        if x>x_low and x<x_up and y>y_low and y<y_up and z>z_low and z<z_up:
            return np.array(x,y,z)
        else:
            return None

    '''Used only in the Envelope class, computes triangle fractional areas
    based on the intersection with the neck plane and assigns them to each vertex
    to be used as weights in triangle temperature averaging'''

    # only works for marching now
    frac_areas = np.zeros((len(new_mesh['triangles']),3))
    frac_areas[(new_mesh['env_comp3']==0)|(new_mesh['env_comp3']==1)] = 1.

    triangles_neck = new_mesh['triangles'][(new_mesh['env_comp3']!=0)&(new_mesh['env_comp3']!=1)]

    for i in range(len(triangles_neck)):

        # take the vertex indices of each triangle and pull the vertices
        # new_mesh already has the env_comp and env_comp3 columns
        vind = triangles_neck[i]
        v1,v2,v3 = new_mesh['vertices'][vind[0]],new_mesh['vertices'][vind[1]],new_mesh['vertices'][vind[2]]
        env1,env2,env3 = new_mesh['env_comp'][vind[0]],new_mesh['env_comp'][vind[1]],new_mesh['env_comp'][vind[2]]

        # take lines formed by vertices on opposite sides of neck (different env_comp)
        # be smart about this, now it's just so it's there

        if (env1==0 and env2==0 and env3==1) or (env1==1 and env2==1 and env3==0):
            line1,line2=[v1,v3],[v2,v3]
            triangle1,triangle2,triangle3 = [v1,v2,0],[v2,0,0],[v3,0,0]
        if (env1==0 and env2==1 and env3==1) or (env1==1 and env2==0 and env3==0):
            line1,line2=[v1,v2],[v1,v3]
            triangle1,triangle2,triangle3 = [v2,v3,0],[v3,0,0],[v1,0,0]
        if (env1==0 and env2==1 and env3==0) or (env1==1 and env2==0 and env3==1):
            line1,line2=[v1,v2],[v2,v3]
            triangle1,triangle2,triangle3 = [v1,v3,0],[v3,0,0],[v2,0,0]

        # compute the points of intersection
        if line1!=None and line2!=None:
            o1 = intersection(line1[0],line1[1],xmin)
            o2 = intersection(line2[0],line2[1],xmin)

            # create the new triangles whose areas need to be computed
            # triangle1 is the one containing the two vertices of the original
            # triangle3 is the top one that is on the other side
            triangle1[2] = o1
            triangle2[1] = o1
            triangle2[2] = o2
            triangle3[1] = o1
            triangle3[2] = o2

            triangle0 = [v1,v2,v3]

            # compute the areas
            area0,area1,area2,area3 = 0.,0.,0.,0.
            for triangle,area in zip([triangle0,triangle1,triangle2,triangle3],[area0,area1,area2,area3]):
                a = np.sqrt((triangle[0][0]-triangle[1][0])**2+(triangle[0][1]-triangle[1][1])**2+(triangle[0][2]-triangle[1][2])**2)
                b = np.sqrt((triangle[0][0]-triangle[2][0])**2+(triangle[0][1]-triangle[2][1])**2+(triangle[0][2]-triangle[2][2])**2)
                c = np.sqrt((triangle[2][0]-triangle[1][0])**2+(triangle[2][1]-triangle[1][1])**2+(triangle[2][2]-triangle[1][2])**2)
                s = (a+b+c)/2.

                area = np.sqrt(s*(s-a)*(s-b)*(s-c))

            # assign fractional areas to vertices based on where they are with respect to the intersection
            # the top one gets its own fractional area, the two bottom ones get half of the remaining

            if (env1==0 and env2==0 and env3==1) or (env1==1 and env2==1 and env3==0):
				frac_areas[i]=[0.5*(area1+area2)/area0,0.5*(area1+area2)/area0,area3/area0]
            if (env1==0 and env2==1 and env3==1) or (env1==1 and env2==0 and env3==0):
                frac_areas[i]=[area1/area0,0.5*(area2+area3)/area0,0.5*(area2+area3)/area0]
            if (env1==0 and env2==1 and env3==0) or (env1==1 and env2==0 and env3==1):
                frac_areas[i]=[0.5*(area1+area3)/area0,area2/area0,0.5*(area1+area3)/area0]

Response:
Computes the fractional areas belonging to each triangle that are a result
    of the intersection with the neck plane and assigns them to each vertex per triangle.


Instruction:
Given the following Python 3 function, write the documentation
def orbit(component, **kwargs):
    params = []

    #~ params += [ObjrefParameter(value=component)]
    params += [FloatParameter(qualifier='period', timederiv='dpdt', value=kwargs.get('period', 1.0), default_unit=u.d, limits=(0.0,None), description='Orbital period')]
    params += [FloatParameter(qualifier='freq', value=kwargs.get('freq', 2*np.pi/3.0), default_unit=u.rad/u.d, description='Orbital frequency')]
    params += [FloatParameter(qualifier='dpdt', value=kwargs.get('dpdt', 0.0), default_unit=u.s/u.yr, description='Period change')]
    params += [FloatParameter(qualifier='per0', timederiv='dperdt', value=kwargs.get('per0', 0.0), default_unit=u.deg, description='Argument of periastron')]
    params += [FloatParameter(qualifier='dperdt', value=kwargs.get('dperdt', 0.0), default_unit=u.deg/u.yr, description='Periastron change')]
    params += [FloatParameter(qualifier='ecc', timederiv='deccdt', value=kwargs.get('ecc', 0.0), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='Eccentricity')]
    if conf.devel:
        params += [FloatParameter(qualifier='deccdt', value=kwargs.get('deccdt', 0.0), default_unit=u.dimensionless_unscaled/u.d, description='Eccentricity change')]
    params += [FloatParameter(qualifier='t0_perpass', value=kwargs.get('t0_perpass', 0.0), default_unit=u.d, description='Zeropoint date at periastron passage of the primary component')]  # TODO: d vs JD
    params += [FloatParameter(qualifier='t0_supconj', value=kwargs.get('t0_supconj', 0.0), default_unit=u.d, description='Zeropoint date at superior conjunction of the primary component')]  # TODO: d vs JD
    params += [FloatParameter(qualifier='t0_ref', value=kwargs.get('t0_ref', 0.0), default_unit=u.d, description='Zeropoint date at reference point for the primary component')]
    params += [FloatParameter(qualifier='mean_anom', value=kwargs.get('mean_anom', 0.0), default_unit=u.deg, description='Mean anomaly')]
    #params += [FloatParameter(qualifier='ph_perpass', value=kwargs.get('ph_perpass', 0.0), default_unit=u.cycle, description='Phase at periastron passage')]
    #params += [FloatParameter(qualifier='ph_supconj', value=kwargs.get('ph_supconj', 0.0), default_unit=u.cycle, description='Phase at superior conjunction')]
    #params += [FloatParameter(qualifier='ph_infconj', value=kwargs.get('ph_infconj', 0.0), default_unit=u.cycle, description='Phase at inferior conjunction')]
    #params += [FloatParameter(qualifier='t0_ph0', value=kwargs.get('t0_ph0', 0.0), default_unit=u.d, description='Zeropoint to anchor at phase=0.0')] # TODO: d vs JD
    # NOTE: the limits on inclination are from 0-180 so that the definition of superior conjunction doesn't flip
    params += [FloatParameter(qualifier='incl', timederiv='dincldt', value=kwargs.get('incl', 90.0), limits=(0.0, 180.0), default_unit=u.deg, description='Orbital inclination angle')]
    # params += [FloatParameter(qualifier='dincldt', value=kwargs.get('dincldt', 0.0), default_unit=u.deg/u.yr, description="Inclination change")]
    params += [FloatParameter(qualifier='q', value=kwargs.get('q', 1.0), default_unit=u.dimensionless_unscaled, limits=(0.0,None), description='Mass ratio')]
    params += [FloatParameter(qualifier='sma', value=kwargs.get('sma', 5.3), default_unit=u.solRad, limits=(0.0,None), description='Semi major axis of the orbit')]
    params += [FloatParameter(qualifier='long_an', value=kwargs.get('long_an', 0.0), default_unit=u.deg, description='Longitude of the ascending node')]

    constraints = []
    constraints += [(constraint.asini, component)]
    constraints += [(constraint.t0_perpass_supconj, component)]
    constraints += [(constraint.t0_ref_supconj, component)]
    constraints += [(constraint.mean_anom, component)]
    #constraints += [(constraint.ph_perpass, component)]
    #constraints += [(constraint.ph_supconj, component)]
    #constraints += [(constraint.ph_infconj, component)]
    constraints += [(constraint.ecosw, component)]
    constraints += [(constraint.esinw, component)]
    constraints += [(constraint.freq, component)]

    return ParameterSet(params), constraints

Response: Creates parameters for a new orbit.


Instruction:
Explain what the following Python 3 code does
def star(component, **kwargs):

    params = []

    #~ params += [ObjrefParameter(value=component)]
    params += [FloatParameter(qualifier='requiv', value=kwargs.get('requiv', 1.0), default_unit=u.solRad, limits=(0.0,None), description='Equivalent radius')]
    params += [FloatParameter(qualifier='requiv_max', value=kwargs.get('requiv_max', 10.0), default_unit=u.solRad, limits=(0.0, None), description='Critical (maximum) value of the equivalent radius for the given morphology')]
    params += [FloatParameter(qualifier='requiv_min', visible_if='hierarchy.is_contact_binary:True', value=kwargs.get('requiv_min', 0.1), default_unit=u.solRad, limits=(0.0, None), description='Critical (minimum) value of the equivalent radius for the given morphology')]
    params += [FloatParameter(qualifier='teff', value=kwargs.get('teff', 6000.), default_unit=u.K, limits=(0.0,None), description='Mean effective temperature')]
    params += [FloatParameter(qualifier='abun', visible_if='hierarchy.is_contact_binary:False', value=kwargs.get('abun', 0.), default_unit=u.dimensionless_unscaled, description='Metallicity')]   # TODO: correct units??? check if log or not? (logabun = 0)

    params += [FloatParameter(qualifier='syncpar', visible_if='hierarchy.is_binary:True', value=kwargs.get('syncpar', 1.0), default_unit=u.dimensionless_unscaled, limits=(0.0,None), description='Synchronicity parameter')]
    params += [FloatParameter(qualifier='period', value=kwargs.get('period', 1.0), default_unit=u.d, limits=(0.0,None), description='Rotation period')]
    params += [FloatParameter(qualifier='freq', value=kwargs.get('freq', 2*np.pi), default_unit=u.rad/u.d, limits=(0.0,None), description='Rotation frequency')]

    params += [FloatParameter(qualifier='pitch', value=kwargs.get('pitch', 0), default_unit=u.deg, description='Pitch of the stellar rotation axis wrt the orbital rotation axis')]
    params += [FloatParameter(qualifier='yaw', value=kwargs.get('yaw', 0), default_unit=u.deg, description='Yaw of the stellar rotation axis wrt the orbital rotation axis')]

    params += [FloatParameter(qualifier='incl', value=kwargs.get('incl', 90), default_unit=u.deg, description='Inclination of the stellar rotation axis')]
    params += [FloatParameter(qualifier='long_an', value=kwargs.get('long_an', 0.0), default_unit=u.deg, description='Longitude of the ascending node (ie. equator) of the star')]

    # params += [FloatParameter(qualifier='vsini', value=kwargs.get('vsini', 1), default_unit=u.km/u.s, description='Projected maximum rotational velocity')]

    # params += [ChoiceParameter(qualifier='gravblaw_bol', value=kwargs.get('gravblaw_bol', 'zeipel'), choices=['zeipel', 'espinosa', 'claret'], description='Gravity brightening law')]

    # params += [FloatParameter(qualifier='gravb_bol', visible_if='hierarchy.is_contact_binary:False', value=kwargs.get('gravb_bol', 0.32), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='Bolometric gravity brightening')]
    params += [FloatParameter(qualifier='gravb_bol', value=kwargs.get('gravb_bol', 0.32), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='Bolometric gravity brightening')]

    # also see constraint below
    params += [FloatParameter(qualifier='irrad_frac_refl_bol', value=kwargs.get('irrad_frac_refl_bol', 0.6), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='ratio of incident bolometric light that is used for reflection (heating without redistribution)')]
    params += [FloatParameter(qualifier='irrad_frac_lost_bol', value=kwargs.get('irrad_frac_lost_bol', 1.0), default_unit=u.dimensionless_unscaled, limits=(0.0, 1.0), description='ratio of incident bolometric light that is lost/ignored')]

    # TODO: allow for 'interp' as choice, make default, and set visible_if for ld_coeffs_bol (see ld_coeffs in dataset.py)
    params += [ChoiceParameter(qualifier='ld_func_bol', value=kwargs.get('ld_func_bol', 'logarithmic'), choices=_ld_func_choices_no_interp, description='Bolometric limb darkening model')]
    params += [FloatArrayParameter(qualifier='ld_coeffs_bol', value=kwargs.get('ld_coeffs_bol', [0.5, 0.5]), default_unit=u.dimensionless_unscaled, description='Bolometric limb darkening coefficients')]

    params += [FloatParameter(qualifier='mass', value=kwargs.get('mass', 1.0), default_unit=u.solMass, description='Mass')]

    # TODO: add others or move to a bol_dep (in which case create the bol_dep now)?

    constraints = []
    # constraints handled by set_hierarchy:
    # - requiv_detached_max
    # - mass
    # - comp_sma
    # - rotation_period
    # - pitch
    # - yaw

    constraints += [(constraint.freq, component)]
    constraints += [(constraint.irrad_frac, component)]

    return ParameterSet(params), constraints

Response: Creates a parameter set for a new component in the order they appear in the order they appear.


Instruction:
Implement a Python 3 function for
creating a parameter set that can be used to create a common envelope for the given component.

Response:
def envelope(component, **kwargs):
    """
    Create parameters for an envelope (usually will be attached to two stars solRad
        that they can share a common-envelope)

    Generally, this will be used as an input to the kind argument in
    :meth:`phoebe.frontend.bundle.Bundle.add_component`

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

    params += [FloatParameter(qualifier='abun', value=kwargs.get('abun', 0.), default_unit=u.dimensionless_unscaled, description='Metallicity')]   # TODO: correct units??? check if log or not? (logabun = 0)
    # params += [FloatParameter(qualifier='gravb_bol', value=kwargs.get('gravb_bol', 0.32), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='Bolometric gravity brightening')]

    # params += [FloatParameter(qualifier='frac_refl_bol', value=kwargs.get('frac_refl_bol', 0.0), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='ratio of incident bolometric light that is used for reflection (heating without redistribution)')]
    # params += [FloatParameter(qualifier='frac_heat_bol', value=kwargs.get('frac_heat_bol', 0.0), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='ratio of incident bolometric light that is used for heating')]
    # params += [FloatParameter(qualifier='frac_scatt_bol', value=kwargs.get('frac_scatt_bol', 0.0), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='ratio of bolometric incident light that is scattered')]
    # params += [FloatParameter(qualifier='frac_lost_bol', value=kwargs.get('frac_lost_bol', 1.0), default_unit=u.dimensionless_unscaled, limits=(0.0, 1.0), description='ratio of incident bolometric light that is lost/ignored')]

    params += [FloatParameter(qualifier='fillout_factor', value=kwargs.get('fillout_factor', 0.5), default_unit=u.dimensionless_unscaled, limits=(0.0,1.0), description='Fillout-factor of the envelope')]
    params += [FloatParameter(qualifier='pot', value=kwargs.get('pot', 3.5), default_unit=u.dimensionless_unscaled, limits=(0.0,None), description='Potential of the envelope (from the primary component\s reference)')]
    params += [FloatParameter(qualifier='pot_min', value=kwargs.get('pot_min', 3.5), default_unit=u.dimensionless_unscaled, limits=(0.0,None), description='Critical (minimum) value of the potential to remain a contact')]
    params += [FloatParameter(qualifier='pot_max', value=kwargs.get('pot_max', 3.5), default_unit=u.dimensionless_unscaled, limits=(0.0,None), description='Critical (maximum) value of the potential to remain a contact')]
    # params += [FloatParameter(qualifier='intens_coeff1', value=kwargs.get('intens_coeff1', 1.0), default_unit=u.dimensionless_unscaled, description='')]
    # params += [FloatParameter(qualifier='intens_coeff2', value=kwargs.get('intens_coeff2', 1.0), default_unit=u.dimensionless_unscaled, description='')]
    # params += [FloatParameter(qualifier='intens_coeff3', value=kwargs.get('intens_coeff3', 1.0), default_unit=u.dimensionless_unscaled, description='')]
    # params += [FloatParameter(qualifier='intens_coeff4', value=kwargs.get('intens_coeff4', 1.0), default_unit=u.dimensionless_unscaled, description='')]
    # params += [FloatParameter(qualifier='intens_coeff5', value=kwargs.get('intens_coeff5', 1.0), default_unit=u.dimensionless_unscaled, description='')]

    # params += [ChoiceParameter(qualifier='ld_func_bol', value=kwargs.get('ld_func_bol', 'logarithmic'), choices=_ld_func_choices_no_interp, description='Bolometric limb darkening model')]
    # params += [FloatArrayParameter(qualifier='ld_coeffs_bol', value=kwargs.get('ld_coeffs_bol', [0.5, 0.5]), default_unit=u.dimensionless_unscaled, description='Bolometric limb darkening coefficients')]

    constraints = []

    # constraints handled by set hierarchy:
    # potential_contact_min/max
    # requiv_contact_min/max

    return ParameterSet(params), constraints


Instruction:
Explain what the following Python 3 code does
def create_pixeltypegrid(grid_pars, grid_data):

    uniques = [np.unique(column, return_inverse=True) for column in grid_pars]
    #[0] are the unique values, [1] the indices for these to recreate the original array

    # we need to copy the values of the unique axes explicitly into new arrays
    # otherwise we can get issues with the interpolator
    axis_values = []
    for uniques_ in uniques:
        this_axes = np.zeros(len(uniques_[0]))
        this_axes[:] = uniques_[0]
        axis_values.append(this_axes)
    #axis_values = [uniques_[0] for uniques_ in uniques]
    #axis_values = [np.require(uniques_[0],requirements=['A','O','W','F']) for uniques_ in uniques]

    unique_val_indices = [uniques_[1] for uniques_ in uniques]

    data_dim = np.shape(grid_data)[0]

    par_dims   = [len(uv[0]) for uv in uniques]

    par_dims.append(data_dim)
    pixelgrid = np.ones(par_dims)

    # We put np.inf as default value. If we get an inf, that means we tried to access
    # a region of the pixelgrid that is not populated by the data table
    pixelgrid[pixelgrid==1] = np.inf

    # now populate the multiDgrid
    indices = [uv[1] for uv in uniques]
    pixelgrid[indices] = grid_data.T
    return tuple(axis_values), pixelgrid

Response: Create pixelgrid and array of axis values for the current set of parameters and data.


Instruction:
Write a Python 3 script to
interpolate in a grid prepared by create_pixeltypegrid.

Response:
def interpolate(p, axis_values, pixelgrid, order=1, mode='constant', cval=0.0):
    """
    Interpolates in a grid prepared by create_pixeltypegrid().

    p is an array of parameter arrays

    @param p: Npar x Ninterpolate array
    @type p: array
    @return: Ndata x Ninterpolate array
    @rtype: array
    """
    # convert requested parameter combination into a coordinate
    p_ = np.array([np.searchsorted(av_,val) for av_, val in zip(axis_values,p)])
    lowervals_stepsize = np.array([[av_[p__-1], av_[p__]-av_[p__-1]] \
                         for av_, p__ in zip(axis_values,p_)])
    p_coord = (p-lowervals_stepsize[:,0])/lowervals_stepsize[:,1] + p_-1

    # interpolate
    if order > 1:
        prefilter = False
    else:
        prefilter = False

    return [ndimage.map_coordinates(pixelgrid[...,i],p_coord, order=order,
                                    prefilter=prefilter, mode=mode, cval=cval) \
                for i in range(np.shape(pixelgrid)[-1])]


Instruction:
Here you have a function in Python 3, explain what it does
def cinterpolate(p, axis_values, pixelgrid):
    res = libphoebe.interp(p, axis_values, pixelgrid)
    return res

Response: Interpolates in a grid prepared by create_pixeltypegrid.


Instruction:
Given the following Python 3 function, write the documentation
def logger(*args, **kwargs):
    if mpi.within_mpirun and mpi.myrank == 0:
        # tell the workers to invoke the same logger
        mpi.comm.bcast({'worker_command': 'logger', 'args': args, 'kwargs': kwargs}, root=0)

    return _utils.get_basic_logger(*args, **kwargs)

Response: shortcut to utils. get_basic_logger


Instruction:
Implement a function in Python 3 to
return a basic logger for the given level and file.

Response:
def get_basic_logger(clevel='WARNING',flevel='DEBUG',
                     style="default",filename=None,filemode='w'):
    """
    Return a basic logger via a log file and/or terminal.

    Example 1: log only to the console, accepting levels "INFO" and above

    >>> logger = utils.get_basic_logger()

    Example 2: log only to the console, accepting levels "DEBUG" and above

    >>> logger = utils.get_basic_logger(clevel='DEBUG')

    Example 3: log only to a file, accepting levels "DEBUG" and above

    >>> logger = utils.get_basic_logger(clevel=None,filename='mylog.log')

    Example 4: log only to a file, accepting levels "INFO" and above

    >>> logger = utils.get_basic_logger(clevel=None,flevel='INFO',filename='mylog.log')

    Example 5: log to the terminal (INFO and above) and file (DEBUG and above)

    >>> logger = utils.get_basic_logger(filename='mylog.log')

    The different logging styles are:

    C{style='default'}::

        Wed, 13 Feb 2013 08:47 root INFO     Some information

    C{style='grandpa'}::

        # INFO    Some information

    C{style='minimal'}::

        Some information

    @param style: logger style
    @type style: str, one of 'default','grandpa','minimal'
    """
    name = ""
    #-- define formats
    if style=='default':
        format  = '%(asctime)s %(name)-12s %(levelname)-7s %(message)s'
        datefmt = '%a, %d %b %Y %H:%M'
    elif style=='grandpa':
        format  = '# %(levelname)-7s %(message)s'
        datefmt = '%a, %d %b %Y %H:%M'
    elif style=='minimal':
        format = ''
        datefmt = '%a, %d %b %Y %H:%M'

    if style=='trace':
        formatter = MyFormatter()
    else:
        formatter = logging.Formatter(fmt=format,datefmt=datefmt)

    if clevel: clevel = logging.__dict__[clevel.upper()]
    if flevel: flevel = logging.__dict__[flevel.upper()]

    #-- set up basic configuration.
    #   The basicConfig sets up one default logger. If you give a filename, it's
    #   a FileHandler, otherwise a StreamHandler.
    #-- If we want console and filename, first set up a basic FileHandler, then
    #   add terminal StreamHandler
    if filename is not None:
        if flevel is None:
            level = clevel
        else:
            level = flevel
        logging.basicConfig(level=level,
                            format=format,datefmt=datefmt,
                            filename=filename,filemode=filemode)
        fh = logging.FileHandler(filename)
        fh.setLevel(flevel)
        fh.setFormatter(formatter)
        logging.getLogger(name).addHandler(fh)
    if filename is not None and clevel:
        # define a Handler which writes INFO messages or higher to the sys.stderr
        ch = logging.StreamHandler()
        ch.setLevel(clevel)
        # tell the handler to use this format
        ch.setFormatter(formatter)
        logging.getLogger(name).addHandler(ch)
    #-- If we only want a console:
    else:
        logging.basicConfig(level=clevel,format=format,datefmt=datefmt,
                            filename=filename,filemode=filemode)
    #-- fix filename logging
    if filename is not None:
        logging.getLogger(name).handlers[0].level = flevel
    return logging.getLogger(name)


Instruction:
Can you tell what is the following Python 3 function doing
def parse_json(pairs):
    new_pairs = []
    for key, value in pairs:
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        if isinstance(key, unicode):
            key = key.encode('utf-8')
        new_pairs.append((key, value))
    return dict(new_pairs)

Response: parse_json returns a dict of key - value pairs


Instruction:
Here you have a function in Python 3, explain what it does
def direction(self, direction):
        if not isinstance(direction, str):
            raise TypeError("direction must be of type str")

        accepted_values = ['i', 'x', 'y', 'z', 's', 'c']
        if direction not in accepted_values:
            raise ValueError("must be one of: {}".format(accepted_values))

        self._direction = direction

Response: set the direction of the log entry


Instruction:
Can you generate a brief explanation for the following Python 3 code
def interpolate_at_i(self, i, unit=None):
        if isinstance(self.call.i._value, float):
            if self.call.i._value==i:
                return self._to_unit(self._value, unit)
            else:
                return None

        # we can't call i._value here because that may point to a string, and
        # we want this to resolve the array
        i_value = self.call.i.get_value(linebreak=False, sort_by_indep=False)
        if len(i_value) != len(self._value):
            raise ValueError("length mismatch with independent-variable")

        sort_inds = i_value.argsort()
        indep_value = i_value[sort_inds]
        this_value = self._value[sort_inds]
        return self._to_unit(np.interp(i, indep_value, this_value, left=np.nan, right=np.nan), unit)

Response: interpolate the value at a give value of i


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _sort_by_indep(self, func='get_value', i=None, iunit=None, unit=None,
                       uncover=None, trail=None, linebreak=None,
                       sort_by_indep=None):

        """
        must be called before (or within) _do_linebreak
        """

        if sort_by_indep is None:
            # TODO: add property of the call?
            sort_by_indep = True

        indep_array = self.call.i.get_value(i=i,
                                            unit=iunit,
                                            uncover=uncover,
                                            trail=trail,
                                            linebreak=False,
                                            sort_by_indep=False)

        this_array = getattr(self, func)(i=i,
                                         unit=unit,
                                         uncover=uncover,
                                         trail=trail,
                                         linebreak=False,
                                         sort_by_indep=False)

        if not (isinstance(indep_array, np.ndarray) and len(indep_array)==len(this_array)):
            sort_by_indep = False

        if sort_by_indep:
            # TODO: it might be nice to buffer this at the call level, so making
            # multiple get_value calls doesn't have to recompute the sort-order
            sort_inds = indep_array.argsort()
            return this_array[sort_inds]
        else:
            return this_array

Response: Internal method to sort the array of the items in the log entry by indep.


Instruction:
Explain what the following Python 3 code does
def get_value(self, i=None, unit=None,
                  uncover=None, trail=None,
                  linebreak=None, sort_by_indep=None,
                  attr='_value'):
        """
        access the value for a given value of i (independent-variable) depending
        on which effects (i.e. uncover) are enabled.

        If uncover, trail, or linebreak are None (default), then the value from
        the parent Call will be used.
        """

        value = getattr(self, attr)  # could be self._value or self._error
        if value is None:
            return None

        if uncover is None:
            uncover = self.call.uncover

        if trail is None:
            trail = self.call.trail

        if linebreak is None:
            linebreak = self.call.linebreak

        if sort_by_indep is None:
            # TODO: make this a property of the call?
            sort_by_indep = True

        if isinstance(value, str) or isinstance(value, float):
            if i is None:
                return self._to_unit(value, unit)
            elif isinstance(self.call.i.value, float):
                # then we still want to "select" based on the value of i
                if self._filter_at_i(i):
                    return value
                else:
                    return None
            else:
                # then we should show either way.  For example - a color or
                # axhline even with i given won't change in i
                return self._to_unit(value, unit)

        # from here on we're assuming the value is an array, so let's just check
        # to be sure
        if not isinstance(value, np.ndarray):
            raise NotImplementedError("value/error must be a numpy array")

        if linebreak is not False:
            return self._do_linebreak(func='get{}'.format(attr),
                                      i=i,
                                      unit=unit,
                                      uncover=uncover,
                                      trail=trail,
                                      linebreak=linebreak,
                                      sort_by_indep=sort_by_indep)

        if sort_by_indep is not False:
            # if we've made it here, linebreak should already be False (if
            # linebreak was True, then we'd be within _do_linebreak and those
            # get_value calls pass linebreak=False)
            return self._sort_by_indep(func='get{}'.format(attr),
                                       i=i,
                                       unit=unit,
                                       uncover=uncover,
                                       trail=trail,
                                       linebreak=False,
                                       sort_by_indep=sort_by_indep)

        # from here on, linebreak==False and sort_by_indep==False (if either
        # were True, then we're within those functions and asking for the original
        # array)
        if i is None:
            if len(value.shape)==1:
                return self._to_unit(value, unit)
            else:
                if isinstance(self.call, Plot):
                    return self._to_unit(value.T, unit)
                else:
                    return self._to_unit(value, unit)

        # filter the data as necessary
        filter_ = self._filter_at_i(i, uncover=uncover, trail=trail)

        if isinstance(self.call.i.value, float):
            if filter_:
                return self._to_unit(value, unit)
            else:
                return None

        if len(value.shape)==1:
            # then we're dealing with a flat 1D array
            if attr == '_value':
                if trail is not False:
                    trail_i = self._get_trail_min(i)
                    first_point = self.interpolate_at_i(trail_i)

                if uncover:
                    last_point = self.interpolate_at_i(i)
            else:
                first_point = np.nan
                last_point = np.nan

            if uncover and trail is not False:
                concat = (np.array([first_point]),
                          value[filter_],
                          np.array([last_point]))
            elif uncover:
                concat = (value[filter_],
                          np.array([last_point]))

            elif trail:
                concat = (np.array([first_point]),
                          value[filter_])
            else:
                return self._to_unit(value[filter_], unit)

            return self._to_unit(np.concatenate(concat), unit)

        else:
            # then we need to "select" based on the indep and the value
            if isinstance(self.call, Plot):
                return self._to_unit(value[filter_].T, unit)
            else:
                return self._to_unit(value[filter_], unit)

Response: get the value of a given attribute of a given i


Instruction:
Here you have a function in Python 3, explain what it does
def _set_value(self, value):
        if value is None:
            self._value = value
            return

        # handle casting to acceptable types
        if isinstance(value, list) or isinstance(value, tuple):
            value = np.array(value)
        if isinstance(value, int):
            value = float(value)
        if isinstance(value, u.Quantity):
            if self.unit == u.dimensionless_unscaled:
                # then take the unit from quantity and apply it
                self.unit = value.unit
                value = value.value
            else:
                # then convert to the requested unit
                value = value.to(self.unit).value

        # handle setting based on type
        if isinstance(value, np.ndarray):
            # if len(value.shape) != 1:
                # raise ValueError("value must be a flat array")

            self._value = value
        elif isinstance(value, float):
            # TODO: do we want to cast to np.array([value])??
            # this will most likely be used for axhline/axvline
            self._value = value
        # elif isinstance(value, str):
            # TODO: then need to pull from the bundle??? Or will this happen
            # at a higher level
        elif self.direction=='c' and isinstance(value, str):
            self._value = common.coloralias.map(value)
        else:
            raise TypeError("value must be of type array (or similar)")

Response: set the value of the attribute


Instruction:
Given the following Python 3 function, write the documentation
def get_error(self, i=None, unit=None,
                  uncover=None, trail=None,
                  linebreak=None, sort_by_indep=None):
        """
        access the error for a given value of i (independent-variable) depending
        on which effects (i.e. uncover) are enabled.
        """
        return self.get_value(i=i, unit=unit,
                              uncover=uncover, trail=trail,
                              linebreak=linebreak, sort_by_indep=sort_by_indep,
                              attr='_error')

Response: get the error for a given value of i


Instruction:
Can you implement a function in Python 3 that
sets the error of the current object

Response:
def error(self, error):
        """
        set the error
        """
        # TODO: check length with value?
        # TODO: type checks (similar to value)
        if self.direction not in ['x', 'y', 'z'] and error is not None:
            raise ValueError("error only accepted for x, y, z dimensions")

        if isinstance(error, u.Quantity):
            error = error.to(self.unit).value

        self._error = error


Instruction:
Write a Python 3 script for
setting the label of the object

Response:
def label(self, label):
        """
        set the label
        """
        if self.direction in ['i'] and label is not None:
            raise ValueError("label not accepted for indep dimension")

        if label is None:
            self._label = label
            return

        if not isinstance(label, str):
            try:
                label = str(label)
            except:
                raise TypeError("label must be of type str")

        self._label = label


Instruction:
Write a Python 3 script to
set the value of the value

Response:
def value(self, value):
        """
        set the value
        """
        # for the indep direction we also allow a string which points to one
        # of the other available dimensions
        # TODO: support c, fc, ec?
        if isinstance(value, common.basestring) and value in ['x', 'y', 'z']:
            # we'll cast just to get rid of any python2 unicodes
            self._value  = str(value)
            dimension = value
            self._unit = getattr(self.call, dimension).unit
            return

        # NOTE: cannot do super on setter directly, see this python
        # bug: https://bugs.python.org/issue14965 and discussion:
        # https://mail.python.org/pipermail/python-dev/2010-April/099672.html
        super(CallDimensionI, self)._set_value(value)


Instruction:
How would you explain what the following Python 3 function does
def rotfreq_to_omega(rotfreq, scale=c.R_sun.si.value, solar_units=False):
    if solar_units:
        omega = rotfreq / (2*np.pi) / np.sqrt(c.GM_sun.to(u.solRad**3/u.d**2).value/scale**3)
    else:
        # then SI units
        omega = rotfreq / (2*np.pi) / np.sqrt(c.GM_sun.value/scale**3)

    # print "*** rotstar.rotfreq_to_omega", rotfreq, scale, solar_units, omega

    return omega

Response: Convert a rotation frequency to an omega value.


Instruction:
Can you generate the documentation for the following Python 3 function
def _ensure_tuple(item):
    if isinstance(item, tuple):
        return item
    elif isinstance(item, list):
        return tuple(item)
    elif isinstance(item, np.ndarray):
        return tuple(item.tolist())
    else:
        raise NotImplementedError

Response: Ensure that the passed item is a tuple. If it is not then return the item itself.


Instruction:
Can you write a function in Python 3 where it
parses parameters in the bundle and call :func:`dynamics`. See :func:`dynamics` for more detailed information. NOTE: you must either provide compute (the label) OR all relevant options as kwargs (ltte, stepsize, gr, integrator) Args: b: (Bundle) the bundle with a set hierarchy times: (list or array) times at which to run the dynamics stepsize: (float, optional) stepsize for the integration [default: 0.01] orbiterror: (float, optional) orbiterror for the integration [default: 1e-16] ltte: (bool, default False) whether to account for light travel time effects. gr: (bool, default False) whether to account for general relativity effects. Returns: t, xs, ys, zs, vxs, vys, vzs. t is a numpy array of all times, the remaining are a list of numpy arrays (a numpy array per star - in order given by b.hierarchy.get_stars()) for the cartesian positions and velocities of each star at those same times.

Response:
def dynamics_from_bundle(b, times, compute=None, return_roche_euler=False, use_kepcart=False, **kwargs):
    """
    Parse parameters in the bundle and call :func:`dynamics`.

    See :func:`dynamics` for more detailed information.

    NOTE: you must either provide compute (the label) OR all relevant options
    as kwargs (ltte, stepsize, gr, integrator)

    Args:
        b: (Bundle) the bundle with a set hierarchy
        times: (list or array) times at which to run the dynamics
        stepsize: (float, optional) stepsize for the integration
            [default: 0.01]
        orbiterror: (float, optional) orbiterror for the integration
            [default: 1e-16]
        ltte: (bool, default False) whether to account for light travel time effects.
        gr: (bool, default False) whether to account for general relativity effects.

    Returns:
        t, xs, ys, zs, vxs, vys, vzs.  t is a numpy array of all times,
        the remaining are a list of numpy arrays (a numpy array per
        star - in order given by b.hierarchy.get_stars()) for the cartesian
        positions and velocities of each star at those same times.

    """

    b.run_delayed_constraints()

    hier = b.hierarchy

    computeps = b.get_compute(compute, check_visible=False, force_ps=True)
    stepsize = computeps.get_value('stepsize', check_visible=False, **kwargs)
    ltte = computeps.get_value('ltte', check_visible=False, **kwargs)
    gr = computeps.get_value('gr', check_visible=False, **kwargs)
    integrator = computeps.get_value('integrator', check_visible=False, **kwargs)

    starrefs = hier.get_stars()
    orbitrefs = hier.get_orbits() if use_kepcart else [hier.get_parent_of(star) for star in starrefs]

    def mean_anom(t0, t0_perpass, period):
        # TODO: somehow make this into a constraint where t0 and mean anom
        # are both in the compute options if dynamic_method==nbody
        # (one is constrained from the other and the orbit.... nvm, this gets ugly)
        return 2 * np.pi * (t0 - t0_perpass) / period

    masses = [b.get_value('mass', u.solMass, component=component, context='component') * c.G.to('AU3 / (Msun d2)').value for component in starrefs]  # GM
    smas = [b.get_value('sma', u.AU, component=component, context='component') for component in orbitrefs]
    eccs = [b.get_value('ecc', component=component, context='component') for component in orbitrefs]
    incls = [b.get_value('incl', u.rad, component=component, context='component') for component in orbitrefs]
    per0s = [b.get_value('per0', u.rad, component=component, context='component') for component in orbitrefs]
    long_ans = [b.get_value('long_an', u.rad, component=component, context='component') for component in orbitrefs]
    t0_perpasses = [b.get_value('t0_perpass', u.d, component=component, context='component') for component in orbitrefs]
    periods = [b.get_value('period', u.d, component=component, context='component') for component in orbitrefs]

    if return_roche_euler:
        # rotperiods are only needed to compute instantaneous syncpars
        rotperiods = [b.get_value('period', u.d, component=component, context='component') for component in starrefs]
    else:
        rotperiods = None

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

    # mean_anoms = [mean_anom(t0, t0_perpass, period) for t0_perpass, period in zip(t0_perpasses, periods)]
    mean_anoms = [b.get_value('mean_anom', u.rad, component=component, context='component') for component in orbitrefs]

    return dynamics(times, masses, smas, eccs, incls, per0s, long_ans, \
                    mean_anoms, rotperiods, t0, vgamma, stepsize, ltte, gr,
                    integrator, use_kepcart=use_kepcart, return_roche_euler=return_roche_euler)


Instruction:
Given the following Python 3 function, write the documentation
def dynamics_from_bundle_bs(b, times, compute=None, return_roche_euler=False, **kwargs):

    stepsize = 0.01
    orbiterror = 1e-16
    computeps = b.get_compute(compute, check_visible=False, force_ps=True)
    ltte = computeps.get_value('ltte', check_visible=False, **kwargs)

    hier = b.hierarchy

    starrefs = hier.get_stars()
    orbitrefs = hier.get_orbits()

    def mean_anom(t0, t0_perpass, period):
        # TODO: somehow make this into a constraint where t0 and mean anom
        # are both in the compute options if dynamic_method==nbody
        # (one is constrained from the other and the orbit.... nvm, this gets ugly)
        return 2 * np.pi * (t0 - t0_perpass) / period

    masses = [b.get_value('mass', u.solMass, component=component, context='component') * c.G.to('AU3 / (Msun d2)').value for component in starrefs]  # GM
    smas = [b.get_value('sma', u.AU, component=component, context='component') for component in orbitrefs]
    eccs = [b.get_value('ecc', component=component, context='component') for component in orbitrefs]
    incls = [b.get_value('incl', u.rad, component=component, context='component') for component in orbitrefs]
    per0s = [b.get_value('per0', u.rad, component=component, context='component') for component in orbitrefs]
    long_ans = [b.get_value('long_an', u.rad, component=component, context='component') for component in orbitrefs]
    t0_perpasses = [b.get_value('t0_perpass', u.d, component=component, context='component') for component in orbitrefs]
    periods = [b.get_value('period', u.d, component=component, context='component') for component in orbitrefs]

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

    # mean_anoms = [mean_anom(t0, t0_perpass, period) for t0_perpass, period in zip(t0_perpasses, periods)]
    mean_anoms = [b.get_value('mean_anom', u.rad, component=component, context='component') for component in orbitrefs]

    return dynamics_bs(times, masses, smas, eccs, incls, per0s, long_ans, \
                    mean_anoms, t0, vgamma, stepsize, orbiterror, ltte,
                    return_roche_euler=return_roche_euler)

Response: Parse parameters in the bundle and call dynamics function.


Instruction:
How would you explain what the following Python 3 function does
def dynamics_bs(times, masses, smas, eccs, incls, per0s, long_ans, mean_anoms,
        t0=0.0, vgamma=0.0, stepsize=0.01, orbiterror=1e-16, ltte=False,
        return_roche_euler=False):
    """
    Burlisch-Stoer integration of orbits to give positions and velocities
    of any given number of stars in hierarchical orbits.  This code
    currently uses the NBody code in Josh Carter's photodynam code
    available here:

    [[TODO: include link]]

    If using the Nbody mode in PHOEBE, please cite him as well:

    [[TODO: include citation]]

    See :func:`dynamics_from_bundle` for a wrapper around this function
    which automatically handles passing everything in the correct order
    and in the correct units.

    For each iterable input, stars and orbits should be listed in order
    from primary -> secondary for each nested hierarchy level.  Each
    iterable for orbits should have length one less than those for each
    star (ie if 3 masses are provided, then 2 smas, eccs, etc need to
    be provided)

    Args:
        times: (iterable) times at which to compute positions and
            velocities for each star
        masses: (iterable) mass for each star in [solMass]
        smas: (iterable) semi-major axis for each orbit [AU]
        eccs: (iterable) eccentricities for each orbit
        incls: (iterable) inclinations for each orbit [rad]
        per0s: (iterable) longitudes of periastron for each orbit [rad]
        long_ans: (iterable) longitudes of the ascending node for each
            orbit [rad]
        mean_anoms: (iterable) mean anomalies for each orbit
        t0: (float) time at which to start the integrations
        stepsize: (float, optional) stepsize of the integrations
            [default: 0.01]
        orbiterror: (float, optional) orbiterror of the integrations
            [default: 1e-16]
        ltte: (bool, default False) whether to account for light travel time effects.

    Returns:
        t, xs, ys, zs, vxs, vys, vzs.  t is a numpy array of all times,
        the remaining are a list of numpy arrays (a numpy array per
        star - in order given by b.hierarchy.get_stars()) for the cartesian
        positions and velocities of each star at those same times.

    """

    if not _can_bs:
        raise ImportError("photodynam is not installed (http://github.com/phoebe-project/photodynam)")

    times = _ensure_tuple(times)
    masses = _ensure_tuple(masses)
    smas = _ensure_tuple(smas)
    eccs = _ensure_tuple(eccs)
    incls = _ensure_tuple(incls)
    per0s = _ensure_tuple(per0s)
    long_ans = _ensure_tuple(long_ans)
    mean_anoms = _ensure_tuple(mean_anoms)

    # TODO: include vgamma!!!!
    # print "*** bs.do_dynamics", masses, smas, eccs, incls, per0s, long_ans, mean_anoms, t0
    d = photodynam.do_dynamics(times, masses, smas, eccs, incls, per0s, long_ans, mean_anoms, t0, stepsize, orbiterror, ltte, return_roche_euler)
    # d is in the format: {'t': (...), 'x': ( (1,2,3), (1,2,3), ...), 'y': ..., 'z': ...}

    nobjects = len(masses)
    ntimes = len(times)

    # TODO: need to return euler angles... if that even makes sense?? Or maybe we
    # need to make a new place in orbit??

    au_to_solrad = (1*u.AU).to(u.solRad).value

    ts = np.array(d['t'])
    xs = [(-1*np.array([d['x'][ti][oi] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
    ys = [(-1*np.array([d['y'][ti][oi] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
    zs = [(np.array([d['z'][ti][oi] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
    vxs = [(-1*np.array([d['vx'][ti][oi] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
    vys = [(-1*np.array([d['vy'][ti][oi] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
    vzs = [(np.array([d['vz'][ti][oi] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]

    if return_roche_euler:
        # raise NotImplementedError("euler angles for BS not currently supported")
        # a (sma), e (ecc), in (incl), o (per0?), ln (long_an?), m (mean_anom?)
        ds = [(np.array([d['kepl_a'][ti][oi] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
        # TODO: fix this
        Fs = [(np.array([1.0 for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
        # TODO: check to make sure this is the right angle
        # TODO: need to add np.pi for secondary component?
        # true anomaly + periastron
        ethetas = [(np.array([d['kepl_o'][ti][oi]+d['kepl_m'][ti][oi]+np.pi/2 for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
        # elongans = [(np.array([d['kepl_ln'][ti][oi]+long_ans[0 if oi==0 else oi-1] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
        elongans = [(np.array([d['kepl_ln'][ti][oi]+long_ans[0 if oi==0 else oi-1] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
        # eincls = [(np.array([d['kepl_in'][ti][oi]+incls[0 if oi==0 else oi-1] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]
        eincls = [(np.array([d['kepl_in'][ti][oi]+np.pi-incls[0 if oi==0 else oi-1] for ti in range(ntimes)])*au_to_solrad) for oi in range(nobjects)]

        # d, solRad, solRad/d, rad
        return ts, xs, ys, zs, vxs, vys, vzs, ds, Fs, ethetas, elongans, eincls

    else:

        # d, solRad, solRad/d
        return ts, xs, ys, zs, vxs, vys, vzs

Response: This function is used to generate a Burlisch - Stoer integration of orbits for a given set of time intervals.


Instruction:
Write a Python 3 function for
returning a dictionary of all visible or partial triangles that are only horizon.

Response:
def only_horizon(meshes, xs, ys, zs, expose_horizon=False):
    """
    Check all visible or partial triangles to see if they're behind the horizon,
    by checking the direction of the z-component of the normals (ie hidden if mu<0)
    """

    # if visibility == 0, it should remain 0
    # if visibility == 0.5, it should stay 0.5 if mu > 0 else it should become 0
    # if visibility == 1, it should stay 1 if mu > 0 else it should become 0

    # this can all by easily done by multiplying by int(mu>0) (1 if visible, 0 if hidden)

    return {comp_no: mesh.visibilities * (mesh.mus > 0).astype(int) for comp_no, mesh in meshes.items()}, None, None


Instruction:
How would you explain what the following Python 3 function does
def native(meshes, xs, ys, zs, expose_horizon=False, horizon_method='boolean'):

    centers_flat = meshes.get_column_flat('centers')
    vertices_flat = meshes.get_column_flat('vertices')
    triangles_flat = meshes.get_column_flat('triangles')  # should handle offset automatically

    if horizon_method=='boolean':
        normals_flat = meshes.get_column_flat('tnormals')
    elif horizon_method=='linear':
        normals_flat = meshes.get_column_flat('vnormals')
    else:
        raise NotImplementedError

    # viewing_vector is defined as star -> earth
    # NOTE: this will need to flip if we change the convention on the z-direction
    viewing_vector = np.array([0., 0., 1.])

    # we need to send in ALL vertices but only the visible triangle information
    info = libphoebe.mesh_visibility(viewing_vector,
                                     vertices_flat,
                                     triangles_flat,
                                     normals_flat,
                                     tvisibilities=True,
                                     taweights=True,
                                     method=horizon_method,
                                     horizon=expose_horizon)

    visibilities = meshes.unpack_column_flat(info['tvisibilities'], computed_type='triangles')
    weights = meshes.unpack_column_flat(info['taweights'], computed_type='triangles')

    if expose_horizon:
        horizons = info['horizon']

        # TODO: we need to do this per component and somehow return them in
        # a predictable order or as a dictionary a la the other returned quantities
        horizons = [vertices_flat[horizon_i] for horizon_i in horizons]

    else:
        horizons = None

    return visibilities, weights, horizons

Response: This function returns the native representation of a single resource in a single resource.


Instruction:
How would you code a function in Python 3 to
compute the convex graham of a set of meshes.

Response:
def graham(meshes, xs, ys, zs, expose_horizon=False):
    """
    convex_graham
    """

    distance_factor = 1.0  # TODO: make this an option (what does it even do)?

    # first lets handle the horizon
    visibilities, weights, horizon = only_horizon(meshes, xs, ys, zs)

    # Order the bodies from front to back.  We can do this through zs (which are
    # the z-coordinate positions of each body in the system.
    # Those indices are in the same order as the meshes['comp_no']
    # (needing to add 1 because comp_no starts at 1 not 0)

    # TODO: I don't think this whole comp_no thing is going to work with nested
    # triples.. may need to rethink the whole meshes.component_by_no thing

    front_to_back_comp_nos = np.argsort(zs)[::-1]+1
    nbodies = len(front_to_back_comp_nos)

    for i_front in range(0, nbodies-1):
        # for a binary, i_front will only be 0
        comp_no_front = front_to_back_comp_nos[i_front]
        comp_front = meshes.component_by_no(comp_no_front)
        mesh_front = meshes[comp_front]
        visibility_front = visibilities[comp_front]

        for i_back in range(i_front+1, nbodies):
            # for a binary, i_back will only be 1
            comp_no_back = front_to_back_comp_nos[i_back]
            comp_back = meshes.component_by_no(comp_no_back)
            mesh_back = meshes[comp_back]
            visibility_back = visibilities[comp_back]

            # If mesh_back is entirely hidden, then we can skip any checks and
            # leave it hidden.  Note that here we need to check visibility instead
            # of mesh['visibility'] or mesh_back['visibility'] since we are not
            # adjusting those values in memory.
            if np.all(visibility_back==0.0):
                continue

            # Determine a scale factor for the triangle
            min_size_back = mesh_back.areas.min()
            distance = distance_factor * 2.0/3**0.25*np.sqrt(min_size_back)

            # Select only those triangles that are not hidden
            tri_back_vis = mesh_back.vertices_per_triangle[visibility_back > 0.0].reshape(-1,9)
            tri_front_vis = mesh_front.vertices_per_triangle[visibility_front > 0.0].reshape(-1,9)

            back = np.vstack([tri_back_vis[:,0:2], tri_back_vis[:,3:5], tri_back_vis[:,6:8]])
            front = np.vstack([tri_front_vis[:,0:2], tri_front_vis[:,3:5], tri_front_vis[:,6:8]])

            # Star in front ---> star in back
            if not front.shape[0]:
                continue

            hull, inside = _graham_scan_inside_hull(front, back)
            hidden = inside.reshape(3,-1).all(axis=0)
            visible = ~(inside.reshape(3,-1).any(axis=0))

            # Triangles that are partially hidden are those that are not
            # completely hidden, but do have at least one vertex hidden
            partial = ~hidden & ~visible

            # These returned visibilities are only from mesh_back_vis
            # So to apply back to our master visibilities parameter, we need
            # to find the correct inds.
            visibility_back[visibility_back > 0.0] = 1.0*visible + 0.5*partial

            ###################################################
            ## TODO: port the following code to be included  ##
            ###################################################

            # It's possible that some triangles that do not have overlapping
            # vertices, still are partially covered (i.e. if the objects fall
            # in between the vertices)
            #visible1 = ~star1.mesh['hidden']
            #backc = star1.mesh['center'][visible1,0:2]
            #if not len(backc):
            #    continue
            #
            #subset_partial = closest_points(hull, backc, distance)
            #
            #if not len(subset_partial):
            #    continue
            #
            #arg = np.where(visible1)[0][subset_partial]
            #star1.mesh['visible'][arg] = False
            #star1.mesh['partial'][arg] = True

    return visibilities, None, None


Instruction:
Explain what the following Python 3 code does
def _get_system_ps(b, item, context='component'):
    # TODO: make this a decorator?
    if isinstance(item, list) and len(item)==1:
        item = item[0]

    if isinstance(item, ParameterSet):
        return item.filter(context=context, check_visible=False)
    elif isinstance(item, str):
        return b.filter(item, context=context, check_visible=False)
    else:
        logger.debug("_get_system_ps got {}".format(item))
        raise NotImplementedError("_get_system_ps does not support item with type: {}".format(type(item)))

Response: Get the system PS from a list of parametersets


Instruction:
Can you generate a brief explanation for the following Python 3 code
def roche_requiv_L1(q, syncpar, ecc, sma, incl_star, long_an_star, incl_orb, long_an_orb, compno=1):
    return ConstraintParameter(q._bundle, "requiv_L1(%s, %d)" % (", ".join(["{%s}" % (param.uniquetwig if hasattr(param, 'uniquetwig') else param.expr) for param in (q, syncpar, ecc, sma, incl_star, long_an_star, incl_orb, long_an_orb)]), compno))

Response: Create a constraint parameter that is used for roche requiv_L1.


Instruction:
Create a Python 3 function to
create a constraint parameter that is used for roche requiv contacting a single site.

Response:
def roche_requiv_contact_L1(q, sma, compno=1):
    """
    TODO: add documentation
    """
    return ConstraintParameter(q._bundle, "requiv_contact_L1(%s, %d)" % (", ".join(["{%s}" % (param.uniquetwig if hasattr(param, 'uniquetwig') else param.expr) for param in (q, sma)]), compno))


Instruction:
Can you generate the documentation for the following Python 3 function
def requiv_to_pot_contact(requiv, q, sma, compno=1):
    return ConstraintParameter(requiv._bundle, "requiv_to_pot_contact({}, {}, {}, {})".format(_get_expr(requiv), _get_expr(q), _get_expr(sma), compno))

Response: Returns a constraint parameter that can be used to convert a requiv to a potential contact.


Instruction:
Write a Python 3 script to
return a constraint parameter that can be used to create a requiv contact constraint.

Response:
def pot_to_requiv_contact(pot, q, sma, compno=1):
    """
    TODO: add documentation
    """
    return ConstraintParameter(pot._bundle, "pot_to_requiv_contact({}, {}, {}, {})".format(_get_expr(pot), _get_expr(q), _get_expr(sma), compno))


Instruction:
Can you write a function in Python 3 where it
returns a constraint parameter for the esinw2per0 constraint.

Response:
def esinw2per0(ecc, esinw):
    """
    TODO: add documentation
    """
    return ConstraintParameter(ecc._bundle, "esinw2per0({}, {})".format(_get_expr(ecc), _get_expr(esinw)))


Instruction:
Can you generate the documentation for the following Python 3 function
def ecosw2per0(ecc, ecosw):
    # print "***", "ecosw2per0({}, {})".format(_get_expr(ecc), _get_expr(ecosw))
    return ConstraintParameter(ecc._bundle, "ecosw2per0({}, {})".format(_get_expr(ecc), _get_expr(ecosw)))

Response: Returns a constraint parameter for the ecosw2per0 constraint.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def t0_perpass_to_supconj(t0_perpass, period, ecc, per0):
    return ConstraintParameter(t0_perpass._bundle, "t0_perpass_to_supconj({}, {}, {}, {})".format(_get_expr(t0_perpass), _get_expr(period), _get_expr(ecc), _get_expr(per0)))

Response: t0_perpass_to_supconj is a constraint parameter that is used to convert per - pass period ecc and per0 to supconj period.


Instruction:
Can you generate the documentation for the following Python 3 function
def t0_supconj_to_perpass(t0_supconj, period, ecc, per0):
    return ConstraintParameter(t0_supconj._bundle, "t0_supconj_to_perpass({}, {}, {}, {})".format(_get_expr(t0_supconj), _get_expr(period), _get_expr(ecc), _get_expr(per0)))

Response: t0_supconj_to_perpass - > t0_supconj_to_perpass


Instruction:
Make a summary of the following Python 3 code
def t0_ref_to_supconj(t0_ref, period, ecc, per0):
    return ConstraintParameter(t0_ref._bundle, "t0_ref_to_supconj({}, {}, {}, {})".format(_get_expr(t0_ref), _get_expr(period), _get_expr(ecc), _get_expr(per0)))

Response: t0_ref_to_supconj - converts t0_ref to supplementary t0_ref


Instruction:
How would you implement a function in Python 3 that
creates a constraint for asini in an orbit.

Response:
def asini(b, orbit, solve_for=None):
    """
    Create a constraint for asini in an orbit.

    If any of the required parameters ('asini', 'sma', 'incl') do not
    exist in the orbit, they will be created.

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str orbit: the label of the orbit in which this
        constraint should be built
    :parameter str solve_for:  if 'asini' should not be the derived/constrained
        parameter, provide which other parameter should be derived
        (ie 'sma' or 'incl')
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    """

    orbit_ps = _get_system_ps(b, orbit)

    # We want to get the parameters in THIS orbit, but calling through
    # the bundle in case we need to create it.
    # To do that, we need to know the search parameters to get items from this PS.
    metawargs = orbit_ps.meta
    metawargs.pop('qualifier')

    # Now we'll define the parameters in case they don't exist and need to be created
    sma_def = FloatParameter(qualifier='sma', value=8.0, default_unit=u.solRad, description='Semi major axis')
    incl_def = FloatParameter(qualifier='incl', value=90.0, default_unit=u.deg, description='Orbital inclination angle')
    asini_def = FloatParameter(qualifier='asini', value=8.0, default_unit=u.solRad, description='Projected semi major axis')

    # And now call get_or_create on the bundle
    sma, created = b.get_or_create('sma', sma_def, **metawargs)
    incl, created = b.get_or_create('incl', incl_def, **metawargs)
    asini, created = b.get_or_create('asini', asini_def, **metawargs)

    if solve_for in [None, asini]:
        lhs = asini
        rhs = sma * sin(incl)

    elif solve_for == sma:
        lhs = sma
        rhs = asini / sin(incl)

    elif solve_for == incl:
        lhs = incl
        rhs = arcsin(asini/sma)

    else:
        raise NotImplementedError

    #- return lhs, rhs, args_as_pss
    return lhs, rhs, {'orbit': orbit}


Instruction:
Here you have a function in Python 3, explain what it does
def esinw(b, orbit, solve_for=None, **kwargs):
    orbit_ps = _get_system_ps(b, orbit)

    metawargs = orbit_ps.meta
    metawargs.pop('qualifier')

    esinw_def = FloatParameter(qualifier='esinw', value=0.0, default_unit=u.dimensionless_unscaled, limits=(-1.0,1.0), description='Eccentricity times sin of argument of periastron')
    esinw, created = b.get_or_create('esinw', esinw_def, **metawargs)

    ecc = b.get_parameter(qualifier='ecc', **metawargs)
    per0 = b.get_parameter(qualifier='per0', **metawargs)

    if solve_for in [None, esinw]:
        lhs = esinw
        rhs = ecc * sin(per0)
    elif solve_for == ecc:
        lhs = ecc
        rhs = esinw / sin(per0)
    elif solve_for == per0:
        lhs = per0
        #rhs = arcsin(esinw/ecc)
        rhs = esinw2per0(ecc, esinw)

    else:
        raise NotImplementedError

    return lhs, rhs, {'orbit': orbit}

Response: Create a constraint for esinw in an orbit.


Instruction:
Here you have a function in Python 3, explain what it does
def ecosw(b, orbit, solve_for=None, **kwargs):
    orbit_ps = _get_system_ps(b, orbit)

    metawargs = orbit_ps.meta
    metawargs.pop('qualifier')

    ecosw_def = FloatParameter(qualifier='ecosw', value=0.0, default_unit=u.dimensionless_unscaled, limits=(-1.0,1.0), description='Eccentricity times cos of argument of periastron')
    ecosw, created = b.get_or_create('ecosw', ecosw_def, **metawargs)

    ecc = b.get_parameter(qualifier='ecc', **metawargs)
    per0 = b.get_parameter(qualifier='per0', **metawargs)

    if solve_for in [None, ecosw]:
        lhs = ecosw
        rhs = ecc * cos(per0)

    elif solve_for == ecc:
        lhs = ecc
        rhs = ecosw / cos(per0)
    elif solve_for == per0:
        lhs = per0
        #rhs = arccos(ecosw/ecc)
        rhs = ecosw2per0(ecc, ecosw)
    else:
        raise NotImplementedError

    return lhs, rhs, {'orbit': orbit}

Response: Create a constraint for ecosw in an orbit.


Instruction:
How would you explain what the following Python 3 function does
def t0_perpass_supconj(b, orbit, solve_for=None, **kwargs):

    orbit_ps = _get_system_ps(b, orbit)

    metawargs = orbit_ps.meta
    metawargs.pop('qualifier')

    # by default both t0s exist in an orbit, so we don't have to worry about creating either
    t0_perpass = b.get_parameter(qualifier='t0_perpass', **metawargs)
    t0_supconj = b.get_parameter(qualifier='t0_supconj', **metawargs)
    period = b.get_parameter(qualifier='period', **metawargs)
    ecc = b.get_parameter(qualifier='ecc', **metawargs)
    per0 = b.get_parameter(qualifier='per0', **metawargs)

    if solve_for in [None, t0_perpass]:
        lhs = t0_perpass
        rhs = t0_supconj_to_perpass(t0_supconj, period, ecc, per0)

    elif solve_for == t0_supconj:
        lhs = t0_supconj
        rhs = t0_perpass_to_supconj(t0_perpass, period, ecc, per0)

    else:
        raise NotImplementedError

    return lhs, rhs, {'orbit': orbit}

Response: Create a constraint for t0_perpass and t0_supconj in an orbit


Instruction:
How would you explain what the following Python 3 function does
def t0_ref_supconj(b, orbit, solve_for=None, **kwargs):

    orbit_ps = _get_system_ps(b, orbit)

    metawargs = orbit_ps.meta
    metawargs.pop('qualifier')

    # by default both t0s exist in an orbit, so we don't have to worry about creating either
    t0_ref = b.get_parameter(qualifier='t0_ref', **metawargs)
    t0_supconj = b.get_parameter(qualifier='t0_supconj', **metawargs)
    period = b.get_parameter(qualifier='period', **metawargs)
    ecc = b.get_parameter(qualifier='ecc', **metawargs)
    per0 = b.get_parameter(qualifier='per0', **metawargs)

    if solve_for in [None, t0_ref]:
        lhs = t0_ref
        rhs = t0_supconj_to_ref(t0_supconj, period, ecc, per0)

    elif solve_for == t0_supconj:
        lhs = t0_supconj
        rhs = t0_ref_to_supconj(t0_ref, period, ecc, per0)

    else:
        raise NotImplementedError

    return lhs, rhs, {'orbit': orbit}

Response: Create a constraint for t0_ref in an orbit - allowing translating between t0_ref and t0_supconj.


Instruction:
Explain what the following Python 3 code does
def _true_anom_to_phase(true_anom, period, ecc, per0):
    phshift = 0

    mean_anom = true_anom - (ecc*sin(true_anom))*u.deg

    Phi = (mean_anom + per0) / (360*u.deg) - 1./4

    # phase = Phi - (phshift - 0.25 + per0/(360*u.deg)) * period
    phase = (Phi*u.d - (phshift - 0.25 + per0/(360*u.deg)) * period)*(u.cycle/u.d)

    return phase

Response: Convert true anom to phase


Instruction:
Can you write a function in Python 3 where it
gets PH_SUPCONJ for orbit b

Response:
def ph_supconj(b, orbit, solve_for=None, **kwargs):
    """
    TODO: add documentation
    """
    orbit_ps = _get_system_ps(b, orbit)

    # metawargs = orbit_ps.meta
    #metawargs.pop('qualifier')

    # t0_ph0 and phshift both exist by default, so we don't have to worry about creating either
    # t0_ph0 = orbit_ps.get_parameter(qualifier='t0_ph0')
    # phshift = orbit_ps.get_parameter(qualifier='phshift')
    ph_supconj = orbit_ps.get_parameter(qualifier='ph_supconj')
    per0 = orbit_ps.get_parameter(qualifier='per0')
    ecc = orbit_ps.get_parameter(qualifier='ecc')
    period = orbit_ps.get_parameter(qualifier='period')

    # true_anom_supconj = pi/2 - per0
    # mean_anom_supconj = true_anom_supconj - ecc*sin(true_anom_supconj)
    # ph_supconj = (mean_anom_supconj + per0) / (2 * pi) - 1/4

    if solve_for in [None, ph_supconj]:
        lhs = ph_supconj

        #true_anom_supconj = np.pi/2*u.rad - per0
        true_anom_supconj = -1*(per0 - 360*u.deg)

        rhs = _true_anom_to_phase(true_anom_supconj, period, ecc, per0)

    #elif solve_for in [per0]:
    #    raise NotImplementedError("phshift constraint does not support solving for per0 yet")
    else:
        raise NotImplementedError

    return lhs, rhs, {'orbit': orbit}


Instruction:
Can you implement a function in Python 3 that
creates a constraint for frequency given a period

Response:
def freq(b, component, solve_for=None, **kwargs):
    """
    Create a constraint for frequency (either orbital or rotational) given a period.

    freq = 2 * pi / period

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str component: the label of the orbit or component in which this
        constraint should be built
    :parameter str solve_for:  if 'freq' should not be the derived/constrained
        parameter, provide which other parameter should be derived
        (ie 'period')
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    """

    component_ps = _get_system_ps(b, component)

    #metawargs = component_ps.meta
    #metawargs.pop('qualifier')

    period = component_ps.get_parameter(qualifier='period', check_visible=False)
    freq = component_ps.get_parameter(qualifier='freq', check_visible=False)

    if solve_for in [None, freq]:
        lhs = freq
        rhs = 2 * np.pi / period

    elif solve_for == period:
        lhs = period
        rhs = 2 * np.pi / freq

    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component}


Instruction:
Here you have a function in Python 3, explain what it does
def keplers_third_law_hierarchical(b, orbit1, orbit2, solve_for=None, **kwargs):

    hier = b.hierarchy

    orbit1_ps = _get_system_ps(b, orbit1)
    orbit2_ps = _get_system_ps(b, orbit2)

    sma1 = orbit1_ps.get_parameter(qualifier='sma')
    sma2 = orbit2_ps.get_parameter(qualifier='sma')

    q1 = orbit1_ps.get_parameter(qualifier='q')
    q2 = orbit2_ps.get_parameter(qualifier='q')

    period1 = orbit1_ps.get_parameter(qualifier='period')
    period2 = orbit2_ps.get_parameter(qualifier='period')

    # NOTE: orbit1 is the outer, so we need to check orbit2... which will
    # be the OPPOSITE component as that of the mass we're solving for
    if hier.get_primary_or_secondary(orbit2_ps.component) == 'primary':
        qthing1 = 1.0+q1
    else:
        qthing1 = 1.0+1./q1

    if solve_for in [None, sma1]:
        lhs = sma1
        rhs = (sma2**3 * qthing1 * period1**2/period2**2)**"(1./3)"
    else:
        # TODO: add other options to solve_for
        raise NotImplementedError

    return lhs, rhs, {'orbit1': orbit1, 'orbit2': orbit2}

Response: Keplers three - law hierarchical orbit.


Instruction:
Here you have a function in Python 3, explain what it does
def irrad_frac(b, component, solve_for=None, **kwargs):

    comp_ps = b.get_component(component=component)

    irrad_frac_refl_bol = comp_ps.get_parameter(qualifier='irrad_frac_refl_bol')
    irrad_frac_lost_bol = comp_ps.get_parameter(qualifier='irrad_frac_lost_bol')

    if solve_for in [irrad_frac_lost_bol, None]:
        lhs = irrad_frac_lost_bol
        rhs = 1.0 - irrad_frac_refl_bol
    elif solve_for in [irrad_frac_refl_bol]:
        lhs = irrad_frac_refl_bol
        rhs = 1.0 - irrad_frac_lost_bol
    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component}

Response:
Creates a constraint to ensure that energy is conserved and all incident
 light is accounted for the given component.


Instruction:
Here you have a function in Python 3, explain what it does
def semidetached(b, component, solve_for=None, **kwargs):
    comp_ps = b.get_component(component=component)

    requiv = comp_ps.get_parameter(qualifier='requiv')
    requiv_critical = comp_ps.get_parameter(qualifier='requiv_max')

    if solve_for in [requiv, None]:
        lhs = requiv
        rhs = 1.0*requiv_critical
    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component}

Response: Create a constraint to force requiv to be semidetached


Instruction:
Write a Python 3 function for
creating a constraint for the mass of a star based on Kepler s third - order component orbit.

Response:
def mass(b, component, solve_for=None, **kwargs):
    """
    Create a constraint for the mass of a star based on Kepler's third
    law from its parent orbit.

    If 'mass' does not exist in the component, it will be created

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str component: the label of the star in which this
        constraint should be built
    :parameter str solve_for:  if 'mass' should not be the derived/constrained
        parameter, provide which other parameter should be derived
        (ie 'q', sma', 'period')
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    :raises NotImplementedError: if the hierarchy is not found
    :raises NotImplementedError: if the value of solve_for is not yet implemented
    """
    # TODO: optimize this - this is currently by far the most expensive constraint (due mostly to the parameter multiplication)

    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for mass requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    metawargs = component_ps.meta
    metawargs.pop('qualifier')
    mass_def = FloatParameter(qualifier='mass', value=1.0, default_unit=u.solMass, description='Mass')
    mass, created = b.get_or_create('mass', mass_def, **metawargs)

    metawargs = parentorbit_ps.meta
    metawargs.pop('qualifier')
    sma = b.get_parameter(qualifier='sma', **metawargs)
    period = b.get_parameter(qualifier='period', **metawargs)
    q = b.get_parameter(qualifier='q', **metawargs)

    G = c.G.to('solRad3 / (solMass d2)')
    G.keep_in_solar_units = True

    if hier.get_primary_or_secondary(component) == 'primary':
        qthing = 1.0+q
    else:
        qthing = 1.0+1./q

    if solve_for in [None, mass]:

        lhs = mass
        rhs = (4*np.pi**2 * sma**3 ) / (period**2 * qthing * G)

    elif solve_for==sma:

        lhs = sma
        rhs = ((mass * period**2 * qthing * G)/(4 * np.pi**2))**"(1./3)"

    elif solve_for==period:

        lhs = period
        rhs = ((4 * np.pi**2 * sma**3)/(mass * qthing * G))**"(1./2)"

    elif solve_for==q:
        # TODO: implement this so that one mass can be solved for sma and the
        # other can be solved for q.  The tricky thing is that we actually
        # have qthing here... so we'll probably need to handle the primary
        # vs secondary case separately.
        raise NotImplementedError

    else:
        # TODO: solve for other options
        raise NotImplementedError

    return lhs, rhs, {'component': component}


Instruction:
How would you implement a function in Python 3 that
creates a constraint for the semi - major axes of the star in which the component is in the parent orbit.

Response:
def comp_sma(b, component, solve_for=None, **kwargs):
    """
    Create a constraint for the star's semi-major axes WITHIN its
    parent orbit.  This is NOT the same as the semi-major axes OF
    the parent orbit

    If 'sma' does not exist in the component, it will be created

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str component: the label of the star in which this
        constraint should be built
    :parameter str solve_for:  if 'sma@star' should not be the derived/constrained
        parameter, provide which other parameter should be derived
        (ie 'sma@orbit', 'q')
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    """
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for comp_sma requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    metawargs = component_ps.meta
    metawargs.pop('qualifier')
    compsma_def = FloatParameter(qualifier='sma', value=4.0, default_unit=u.solRad, description='Semi major axis of the component in the orbit')
    compsma, created = b.get_or_create('sma', compsma_def, **metawargs)

    metawargs = parentorbit_ps.meta
    metawargs.pop('qualifier')
    sma = b.get_parameter(qualifier='sma', **metawargs)
    q = b.get_parameter(qualifier='q', **metawargs)

    # NOTE: similar logic is also in dynamics.keplerian.dynamics_from_bundle to
    # handle nested hierarchical orbits.  If changing any of the logic here,
    # it should be changed there as well.

    if hier.get_primary_or_secondary(component) == 'primary':
        qthing = (1. + 1./q)
    else:
        qthing = (1. + q)

    if solve_for in [None, compsma]:
        lhs = compsma
        rhs = sma / qthing

    elif solve_for == sma:
        lhs = sma
        rhs = compsma * qthing

    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component}


Instruction:
Can you create a Python 3 function that
creates a constraint to determine the requiv_detached_max value of a given component.

Response:
def requiv_detached_max(b, component, solve_for=None, **kwargs):
    """
    Create a constraint to determine the critical (at L1) value of
    requiv.

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str component: the label of the star in which this
        constraint should be built
    :parameter str solve_for:  if 'requiv_max' should not be the derived/constrained
        parameter, provide which other parameter should be derived
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    """

    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for requiv_detached_max requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)

    if parentorbit == 'component':
        raise ValueError("cannot constrain requiv_detached_max for single star")

    parentorbit_ps = _get_system_ps(b, parentorbit)

    requiv_max = component_ps.get_parameter(qualifier='requiv_max')
    q = parentorbit_ps.get_parameter(qualifier='q')
    syncpar = component_ps.get_parameter(qualifier='syncpar')
    ecc = parentorbit_ps.get_parameter(qualifier='ecc')
    sma = parentorbit_ps.get_parameter(qualifier='sma')
    incl_star = component_ps.get_parameter(qualifier='incl')
    long_an_star = component_ps.get_parameter(qualifier='long_an')
    incl_orbit = parentorbit_ps.get_parameter(qualifier='incl')
    long_an_orbit = parentorbit_ps.get_parameter(qualifier='long_an')

    if solve_for in [None, requiv_max]:
        lhs = requiv_max

        rhs = roche_requiv_L1(q, syncpar, ecc, sma,
                              incl_star, long_an_star,
                              incl_orbit, long_an_orbit,
                              hier.get_primary_or_secondary(component, return_ind=True))
    else:
        raise NotImplementedError("requiv_detached_max can only be solved for requiv_max")

    return lhs, rhs, {'component': component}


Instruction:
Make a summary of the following Python 3 code
def potential_contact_min(b, component, solve_for=None, **kwargs):
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for requiv_contact_min requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    pot_min = component_ps.get_parameter(qualifier='pot_min')
    q = parentorbit_ps.get_parameter(qualifier='q')

    if solve_for in [None, pot_min]:
        lhs = pot_min

        rhs = roche_potential_contact_L23(q)
    else:
        raise NotImplementedError("potential_contact_min can only be solved for requiv_min")

    return lhs, rhs, {'component': component}

Response: Create a constraint to determine the minimum potential contact for a given component.


Instruction:
Can you implement a function in Python 3 that
creates a constraint to determine the maximum potential contact for a given component.

Response:
def potential_contact_max(b, component, solve_for=None, **kwargs):
    """
    Create a constraint to determine the critical (at L1) value of
    potential at which a constact will underflow.  This will only be used
    for contacts for pot_min

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str component: the label of the star in which this
        constraint should be built
    :parameter str solve_for:  if 'pot_max' should not be the derived/constrained
        parameter, provide which other parameter should be derived
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    """
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for requiv_contact_max requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    pot_max = component_ps.get_parameter(qualifier='pot_max')
    q = parentorbit_ps.get_parameter(qualifier='q')

    if solve_for in [None, pot_max]:
        lhs = pot_max

        rhs = roche_potential_contact_L1(q)
    else:
        raise NotImplementedError("potential_contact_max can only be solved for requiv_max")

    return lhs, rhs, {'component': component}


Instruction:
Make a summary of the following Python 3 code
def requiv_contact_min(b, component, solve_for=None, **kwargs):
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for requiv_contact_min requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    requiv_min = component_ps.get_parameter(qualifier='requiv_min')
    q = parentorbit_ps.get_parameter(qualifier='q')
    sma = parentorbit_ps.get_parameter(qualifier='sma')

    if solve_for in [None, requiv_min]:
        lhs = requiv_min

        rhs = roche_requiv_contact_L1(q, sma, hier.get_primary_or_secondary(component, return_ind=True))
    else:
        raise NotImplementedError("requiv_contact_min can only be solved for requiv_min")

    return lhs, rhs, {'component': component}

Response: Create a constraint to determine the minimum requiv contact for a given component.


Instruction:
Can you tell what is the following Python 3 function doing
def requiv_contact_max(b, component, solve_for=None, **kwargs):
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for requiv_contact_max requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    requiv_max = component_ps.get_parameter(qualifier='requiv_max')
    q = parentorbit_ps.get_parameter(qualifier='q')
    sma = parentorbit_ps.get_parameter(qualifier='sma')

    if solve_for in [None, requiv_max]:
        lhs = requiv_max

        rhs = roche_requiv_contact_L23(q, sma, hier.get_primary_or_secondary(component, return_ind=True))
    else:
        raise NotImplementedError("requiv_contact_max can only be solved for requiv_max")

    return lhs, rhs, {'component': component}

Response: This function returns a constraint to determine the maximum requiv contact for a given component.


Instruction:
Can you tell what is the following Python 3 function doing
def fillout_factor(b, component, solve_for=None, **kwargs):
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for requiv_contact_max requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    pot = component_ps.get_parameter(qualifier='pot')
    fillout_factor = component_ps.get_parameter(qualifier='fillout_factor')
    q = parentorbit_ps.get_parameter(qualifier='q')

    if solve_for in [None, fillout_factor]:
        lhs = fillout_factor

        rhs = roche_pot_to_fillout_factor(q, pot)
    elif solve_for in [pot]:
        lhs = pot

        rhs = roche_fillout_factor_to_pot(q, fillout_factor)
    else:
        raise NotImplementedError("fillout_factor can not be solved for {}".format(solve_for))

    return lhs, rhs, {'component': component}

Response: Create a constraint to determine the fillout factor of a contact envelope.


Instruction:
Write a Python 3 script for
creating a constraint for the rotation period of a star given its orbital and synchronicity parameters.

Response:
def rotation_period(b, component, solve_for=None, **kwargs):
    """
    Create a constraint for the rotation period of a star given its orbital
    period and synchronicity parameters.

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str component: the label of the star in which this
        constraint should be built
    :parameter str solve_for:  if 'period@star' should not be the derived/constrained
        parameter, provide which other parameter should be derived
        (ie 'syncpar@star', 'period@orbit')
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    """
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for comp_sma requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    metawargs = component_ps.meta
    metawargs.pop('qualifier')
    period_star = b.get_parameter(qualifier='period', **metawargs)
    syncpar_star = b.get_parameter(qualifier='syncpar', **metawargs)

    metawargs = parentorbit_ps.meta
    metawargs.pop('qualifier')
    period_orbit = b.get_parameter(qualifier='period', **metawargs)

    if solve_for in [None, period_star]:
        lhs = period_star
        rhs = period_orbit / syncpar_star

    elif solve_for == syncpar_star:
        lhs = syncpar_star
        rhs = period_orbit / period_star

    elif solve_for == period_orbit:
        lhs = period_orbit
        rhs = syncpar_star * period_star

    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component}


Instruction:
How would you explain what the following Python 3 function does
def pitch(b, component, solve_for=None, **kwargs):

    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for pitch requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    incl_comp = component_ps.get_parameter(qualifier='incl')
    pitch_comp = component_ps.get_parameter(qualifier='pitch')
    incl_orb = parentorbit_ps.get_parameter(qualifier='incl')

    if solve_for in [None, incl_comp]:
        lhs = incl_comp
        rhs = incl_orb + pitch_comp

    elif solve_for == incl_orb:
        lhs = incl_orb
        rhs = incl_comp - pitch_comp

    elif solve_for == pitch_comp:
        lhs = pitch_comp
        rhs = incl_comp - incl_orb

    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component}

Response: Create a constraint for the inclination of a star relative to its parent orbit


Instruction:
Can you create a Python 3 function that
creates a constraint for inclination of a star relative to its parent orbit

Response:
def yaw(b, component, solve_for=None, **kwargs):
    """
    Create a constraint for the inclination of a star relative to its parent orbit

    :parameter b: the :class:`phoebe.frontend.bundle.Bundle`
    :parameter str component: the label of the star in which this
        constraint should be built
    :parameter str solve_for:  if 'long_an@star' should not be the derived/constrained
        parameter, provide which other parameter should be derived
        (ie 'long_an@orbit', 'yaw@star')
    :returns: lhs (Parameter), rhs (ConstraintParameter), args (list of arguments
        that were passed to this function)
    """

    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for yaw requires hierarchy")

    component_ps = _get_system_ps(b, component)

    parentorbit = hier.get_parent_of(component)
    parentorbit_ps = _get_system_ps(b, parentorbit)

    long_an_comp = component_ps.get_parameter(qualifier='long_an')
    yaw_comp = component_ps.get_parameter(qualifier='yaw')
    long_an_orb = parentorbit_ps.get_parameter(qualifier='long_an')

    if solve_for in [None, long_an_comp]:
        lhs = long_an_comp
        rhs = long_an_orb + yaw_comp

    elif solve_for == long_an_orb:
        lhs = long_an_orb
        rhs = long_an_comp - yaw_comp

    elif solve_for == yaw_comp:
        lhs = yaw_comp
        rhs = long_an_comp - long_an_orb

    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component}


Instruction:
Given the following Python 3 function, write the documentation
def time_ephem(b, component, dataset, solve_for=None, **kwargs):
    hier = b.get_hierarchy()
    if not len(hier.get_value()):
        # TODO: change to custom error type to catch in bundle.add_component
        # TODO: check whether the problem is 0 hierarchies or more than 1
        raise NotImplementedError("constraint for time_ecl requires hierarchy")

    if component=='_default':
        # need to do this so that the constraint won't fail before being copied
        parentorbit = hier.get_top()
    else:
        parentorbit = hier.get_parent_of(component)

    parentorbit_ps = _get_system_ps(b, parentorbit)

    filterwargs = {}
    if component is not None:
        filterwargs['component'] = component
    if dataset is not None:
        filterwargs['dataset'] = dataset

    time_ephem = b.get_parameter(qualifier='time_ephems', **filterwargs)
    t0 = parentorbit_ps.get_parameter(qualifier='t0_supconj')  # TODO: make sure t0_supconj makes sense here
    period = parentorbit_ps.get_parameter(qualifier='period')
    phshift = parentorbit_ps.get_parameter(qualifier='phshift')
    dpdt = parentorbit_ps.get_parameter(qualifier='dpdt')
    esinw_ = parentorbit_ps.get_parameter(qualifier='esinw')

    N = b.get_parameter(qualifier='Ns', **filterwargs)

    if solve_for in [None, time_ephem]:

        # TODO: N is always an int, but we want to include the expected phase of eclipse (ie N+ph_ecl) based on which component and esinw/ecosw
        # then we can have bundle.add_component automatically default to add all components instead of just the primary

        # same as Bundle.to_time except phase can be > 1
        lhs = time_ephem
        # we have to do a trick here since dpdt is in sec/yr and floats are
        # assumed to have the same unit during subtraction or addition.
        one = 1.0*(u.s/u.s)
        if component!='_default' and hier.get_primary_or_secondary(component)=='secondary':
            # TODO: make sure this constraint updates if the hierarchy changes?
            N = N + 0.5 + esinw_  # TODO: check this
        rhs = t0 + ((N - phshift) * period) / (-1 * (N - phshift) * dpdt + one)
        #rhs = (N-phshift)*period
    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component, 'dataset': dataset}

Response: get the time_ephemeris of a bundle


Instruction:
Write a Python 3 function for
computing the ETV column from the time_ephems and time_ecls

Response:
def etv(b, component, dataset, solve_for=None, **kwargs):
    """
    compute the ETV column from the time_ephem and time_ecl columns (used in the
        ETV dataset)
    """

    time_ephem = b.get_parameter(qualifier='time_ephems', component=component, dataset=dataset, context=['dataset', 'model'])  # need to provide context to avoid getting the constraint
    time_ecl = b.get_parameter(qualifier='time_ecls', component=component, dataset=dataset)
    etv = b.get_parameter(qualifier='etvs', component=component, dataset=dataset)

    if solve_for in [None, etv]:
        lhs = etv
        rhs = time_ecl - time_ephem
    else:
        raise NotImplementedError

    return lhs, rhs, {'component': component, 'dataset': dataset}


Instruction:
How would you explain what the following Python 3 function does
def is_float(value):
    return isinstance(value, float) or isinstance(value, int) or isinstance(value, np.float64), float(value)

Response: must be a float


Instruction:
Create a Python 3 function to
check if value is a positive integer or a tuple or list of positive integers

Response:
def is_valid_shape(value):
    """must be a positive integer or a tuple/list of positive integers"""
    if is_int_positive(value):
        return True, value
    elif isinstance(value, tuple) or isinstance(value, list):
        for v in value:
            if not is_int_positive(v):
                return False, value
        return True, value
    else:
        return False, value


Instruction:
Can you generate a brief explanation for the following Python 3 code
def quantity(self):
        if not _has_astropy:
            raise ImportError("astropy must be installed for unit/quantity support")

        if self.unit is None:
            raise ValueError("unit is not set, cannot convert to quantity")

        return self.array * self.unit

Response: Returns the underlying astropy quantity


Instruction:
Make a summary of the following Python 3 code
def to(self, unit):
        if not _has_astropy:
            raise ImportError("astropy must be installed for unit/quantity support")

        if self.unit is None:
            raise ValueError("no units currently set")

        if not is_unit_or_unitstring(unit)[0]:
            raise ValueError("unit not recognized")

        mult_factor = self.unit.to(unit)
        copy = self.copy() * mult_factor
        copy.unit = unit
        return copy

Response: Returns a new nparray object with the new units converted to the given unit.