Instruction:
How would you code a function in Python 3 to
get object from generic date_based. detail view

Response:
def get_object_from_date_based_view(request, *args, **kwargs):  # noqa
    """
    Get object from generic date_based.detail view

    Parameters
    ----------
    request : instance
        An instance of HttpRequest

    Returns
    -------
    instance
        An instance of model object or None
    """
    import time
    import datetime
    from django.http import Http404
    from django.db.models.fields import DateTimeField
    try:
        from django.utils import timezone
        datetime_now = timezone.now
    except ImportError:
        datetime_now = datetime.datetime.now
    year, month, day = kwargs['year'], kwargs['month'], kwargs['day']
    month_format = kwargs.get('month_format', '%b')
    day_format = kwargs.get('day_format', '%d')
    date_field = kwargs['date_field']
    queryset = kwargs['queryset']
    object_id = kwargs.get('object_id', None)
    slug = kwargs.get('slug', None)
    slug_field = kwargs.get('slug_field', 'slug')

    try:
        tt = time.strptime(
                '%s-%s-%s' % (year, month, day),
                '%s-%s-%s' % ('%Y', month_format, day_format)
            )
        date = datetime.date(*tt[:3])
    except ValueError:
        raise Http404

    model = queryset.model

    if isinstance(model._meta.get_field(date_field), DateTimeField):
        lookup_kwargs = {
                '%s__range' % date_field: (
                    datetime.datetime.combine(date, datetime.time.min),
                    datetime.datetime.combine(date, datetime.time.max),
                )}
    else:
        lookup_kwargs = {date_field: date}

    now = datetime_now()
    if date >= now.date() and not kwargs.get('allow_future', False):
        lookup_kwargs['%s__lte' % date_field] = now
    if object_id:
        lookup_kwargs['pk'] = object_id
    elif slug and slug_field:
        lookup_kwargs['%s__exact' % slug_field] = slug
    else:
        raise AttributeError(
                "Generic detail view must be called with either an "
                "object_id or a slug/slug_field."
            )
    return get_object_or_404(queryset, **lookup_kwargs)


Instruction:
Given the following Python 3 function, write the documentation
def register(self, model, handler=None):
        from permission.handlers import PermissionHandler
        if model._meta.abstract:
            raise ImproperlyConfigured(
                    'The model %s is abstract, so it cannot be registered '
                    'with permission.' % model)
        if model in self._registry:
            raise KeyError("A permission handler class is already "
                            "registered for '%s'" % model)
        if handler is None:
            handler = settings.PERMISSION_DEFAULT_PERMISSION_HANDLER
        if isstr(handler):
            handler = import_string(handler)
        if not inspect.isclass(handler):
            raise AttributeError(
                    "`handler` attribute must be a class. "
                    "An instance was specified.")
        if not issubclass(handler, PermissionHandler):
            raise AttributeError(
                    "`handler` attribute must be a subclass of "
                    "`permission.handlers.PermissionHandler`")

        # Instantiate the handler to save in the registry
        instance = handler(model)
        self._registry[model] = instance

Response: Registers a permission handler for a django model.


Instruction:
Explain what the following Python 3 code does
def unregister(self, model):
        if model not in self._registry:
            raise KeyError("A permission handler class have not been "
                           "registered for '%s' yet" % model)
        # remove from registry
        del self._registry[model]

Response: Unregister a permission handler from the registry.


Instruction:
Write a Python 3 function that can
get permissions related to the application specified in constructor Returns ------- self. _app_perms_cache

Response:
def _get_app_perms(self, *args):
        """
        Get permissions related to the application specified in constructor

        Returns
        -------
        set
            A set instance of `app_label.codename` formatted permission strings
        """
        if not hasattr(self, '_app_perms_cache'):
            self._app_perms_cache = get_app_perms(self.app_label)
        return self._app_perms_cache


Instruction:
Explain what the following Python 3 code does
def _get_model_perms(self, *args):
        if not hasattr(self, '_model_perms_cache'):
            if self.model is None:
                self._model_perms_cache = set()
            else:
                self._model_perms_cache = get_model_perms(self.model)
        return self._model_perms_cache

Response: Get permissions related to the model specified in constructor. Returns ------- set A set instance of string formatted permission strings


Instruction:
How would you implement a function in Python 3 that
returns a list of permissions which this handler can treat.

Response:
def get_supported_permissions(self):
        """
        Get permissions which this handler can treat.
        Specified with :attr:`includes` and :attr:`excludes` of this instance.

        Returns
        -------
        set
            A set instance of `app_label.codename` formatted permission strings
        """
        if not hasattr(self, '_perms_cache'):
            if (self.includes and
                    isinstance(self.includes, collections.Callable)):
                includes = self.includes(self)
            else:
                includes = self.includes or []
            if (self.excludes and
                    isinstance(self.excludes, collections.Callable)):
                excludes = self.excludes(self)
            else:
                excludes = self.excludes or []
            includes = set(includes)
            excludes = set(excludes)
            includes = includes.difference(excludes)
            self._perms_cache = includes
        return self._perms_cache


Instruction:
Can you tell what is the following Python 3 function doing
def get_supported_app_labels(self):
        get_app_label = lambda x: x.split(".", 1)[0]
        if not hasattr(self, '_app_labels_cache'):
            perms = self.get_supported_permissions()
            self._app_labels_cache = set([get_app_label(x) for x in perms])
        return self._app_labels_cache

Response: Returns a set of app labels which this handler can treat.


Instruction:
How would you implement a function in Python 3 that
checks if user has permission of specified app_label.

Response:
def has_module_perms(self, user_obj, app_label):
        """
        Check if user have permission of specified app

        Parameters
        ----------
        user_obj : django user model instance
            A django user model instance which be checked
        app_label : string
            Django application name

        Returns
        -------
        boolean
            Whether the specified user have any permissions of specified app

        """
        cache_name = "_has_module_perms_%s_%s_cache" % (app_label, user_obj.pk)
        if hasattr(self, cache_name):
            return getattr(self, cache_name)
        if self.app_label != app_label:
            setattr(self, cache_name, False)
        else:
            for permission in self.get_supported_permissions():
                if user_obj.has_perm(permission):
                    setattr(self, cache_name, True)
                    return True
        setattr(self, cache_name, False)
        return False


Instruction:
Here you have a function in Python 3, explain what it does
def has_perm(self, user_obj, perm, obj=None):
        if perm not in self.get_supported_permissions():
            return False
        # use cache to reduce method call
        CACHE_NAME = '_logical_perms_cache'
        if not hasattr(user_obj, CACHE_NAME):
            setattr(user_obj, CACHE_NAME, {})
        cache = getattr(user_obj, CACHE_NAME)
        cachekey = "%s %s" % (perm, hash(obj))
        if cachekey not in cache:
            cache[cachekey] = self._has_perm(user_obj, perm, obj)
        return cache[cachekey]

Response: Check if user has permission of object perm.


Instruction:
Can you tell what is the following Python 3 function doing
def permission_required(perm, queryset_or_model=None,
                        login_url=None, raise_exception=False):
    """
    Permission check decorator for classbased/functional generic view

    This decorator works as class, method or function decorator without any
    modification.
    DO NOT use ``method_decorator`` or whatever while this decorator will use
    ``self`` argument for method of classbased generic view.

    Parameters
    ----------
    perm : string
        A permission string
    queryset_or_model : queryset or model
        A queryset or model for finding object.
        With classbased generic view, ``None`` for using view default queryset.
        When the view does not define ``get_queryset``, ``queryset``,
        ``get_object``, or ``object`` then ``obj=None`` is used to check
        permission.
        With functional generic view, ``None`` for using passed queryset.
        When non queryset was passed then ``obj=None`` is used to check
        permission.

    Examples
    --------
    >>> # As class decorator
    >>> @permission_required('auth.change_user')
    >>> class UpdateAuthUserView(UpdateView):
    ...     pass
    >>> # As method decorator
    >>> class UpdateAuthUserView(UpdateView):
    ...     @permission_required('auth.change_user')
    ...     def dispatch(self, request, *args, **kwargs):
    ...         pass
    >>> # As function decorator
    >>> @permission_required('auth.change_user')
    >>> def update_auth_user(request, *args, **kwargs):
    ...     pass

    .. Note::
        Classbased generic view is recommended while you can regulate the queryset
        with ``get_queryset()`` method.
        Detecting object from passed kwargs may not work correctly.
    """
    # convert model to queryset
    if queryset_or_model and issubclass(queryset_or_model, Model):
        queryset_or_model = queryset_or_model._default_manager.all()

    def wrapper(class_or_method):
        if inspect.isclass(class_or_method):
            from permission.decorators.classbase import \
                    permission_required as decorator
        else:
            # method_permission_required can handle method or function
            # correctly.
            from permission.decorators.methodbase import \
                    permission_required as decorator
        return decorator(perm, queryset_or_model,
                         login_url, raise_exception)(class_or_method)
    return wrapper

Response: Permission check decorator for classbased generic view.


Instruction:
Given the following Python 3 function, write the documentation
def get_perm_codename(perm, fail_silently=True):
    try:
        perm = perm.split('.', 1)[1]
    except IndexError as e:
        if not fail_silently:
            raise e
    return perm

Response: Get permission codename from permission - string.


Instruction:
Implement a function in Python 3 to
convert a permission instance to a permission - string.

Response:
def permission_to_perm(permission):
    """
    Convert a permission instance to a permission-string.

    Examples
    --------
    >>> permission = Permission.objects.get(
    ...     content_type__app_label='auth',
    ...     codename='add_user',
    ... )
    >>> permission_to_perm(permission)
    'auth.add_user'
    """
    app_label = permission.content_type.app_label
    codename = permission.codename
    return '%s.%s' % (app_label, codename)


Instruction:
Make a summary of the following Python 3 code
def perm_to_permission(perm):
    from django.contrib.auth.models import Permission
    try:
        app_label, codename = perm.split('.', 1)
    except (ValueError, IndexError):
        raise AttributeError(
            'The format of identifier string permission (perm) is wrong. '
            "It should be in 'app_label.codename'."
        )
    else:
        permission = Permission.objects.get(
            content_type__app_label=app_label,
            codename=codename
        )
        return permission

Response: Converts a permission - string to a permission instance.


Instruction:
Here you have a function in Python 3, explain what it does
def get_app_perms(model_or_app_label):
    from django.contrib.auth.models import Permission
    if isinstance(model_or_app_label, string_types):
        app_label = model_or_app_label
    else:
        # assume model_or_app_label is model class
        app_label = model_or_app_label._meta.app_label
    qs = Permission.objects.filter(content_type__app_label=app_label)
    perms = ('%s.%s' % (app_label, p.codename) for p in qs.iterator())
    return set(perms)

Response: Get permission - string list of the specified django application.


Instruction:
How would you explain what the following Python 3 function does
def get_model_perms(model):
    from django.contrib.auth.models import Permission
    app_label = model._meta.app_label
    model_name = model._meta.object_name.lower()
    qs = Permission.objects.filter(content_type__app_label=app_label,
                                   content_type__model=model_name)
    perms = ('%s.%s' % (app_label, p.codename) for p in qs.iterator())
    return set(perms)

Response: Returns a list of permission - string list of a given django model.


Instruction:
Can you implement a function in Python 3 that
checks if a user has permission of a specified object.

Response:
def has_perm(self, user_obj, perm, obj=None):
        """
        Check if user have permission (of object)

        If the user_obj is not authenticated, it return ``False``.

        If no object is specified, it return ``True`` when the corresponding
        permission was specified to ``True`` (changed from v0.7.0).
        This behavior is based on the django system.
        https://code.djangoproject.com/wiki/RowLevelPermissions

        If an object is specified, it will return ``True`` if the user is
        found in ``field_name`` of the object (e.g. ``obj.collaborators``).
        So once the object store the user as a collaborator in
        ``field_name`` attribute (default: ``collaborators``), the collaborator
        can change or delete the object (you can change this behavior to set
        ``any_permission``, ``change_permission`` or ``delete_permission``
        attributes of this instance).

        Parameters
        ----------
        user_obj : django user model instance
            A django user model instance which be checked
        perm : string
            `app_label.codename` formatted permission string
        obj : None or django model instance
            None or django model instance for object permission

        Returns
        -------
        boolean
            Whether the specified user have specified permission (of specified
            object).
        """
        if not is_authenticated(user_obj):
            return False
        # construct the permission full name
        change_permission = self.get_full_permission_string('change')
        delete_permission = self.get_full_permission_string('delete')
        if obj is None:
            # object permission without obj should return True
            # Ref: https://code.djangoproject.com/wiki/RowLevelPermissions
            if self.any_permission:
                return True
            if self.change_permission and perm == change_permission:
                return True
            if self.delete_permission and perm == delete_permission:
                return True
            return False
        elif user_obj.is_active:
            # get collaborator queryset
            collaborators = field_lookup(obj, self.field_name)
            if hasattr(collaborators, 'all'):
                collaborators = collaborators.all()
            if user_obj in collaborators:
                if self.any_permission:
                    # have any kind of permissions to the obj
                    return True
                if (self.change_permission and
                        perm == change_permission):
                    return True
                if (self.delete_permission and
                        perm == delete_permission):
                    return True
        return False


Instruction:
Implement a function in Python 3 to
add a permission logic to the specified django model.

Response:
def add_permission_logic(model, permission_logic):
    """
    Add permission logic to the model

    Parameters
    ----------
    model : django model class
        A django model class which will be treated by the specified permission
        logic
    permission_logic : permission logic instance
        A permission logic instance which will be used to determine permission
        of the model

    Examples
    --------
    >>> from django.db import models
    >>> from permission.logics import PermissionLogic
    >>> class Mock(models.Model):
    ...     name = models.CharField('name', max_length=120)
    >>> add_permission_logic(Mock, PermissionLogic())
    """
    if not isinstance(permission_logic, PermissionLogic):
        raise AttributeError(
        '`permission_logic` must be an instance of PermissionLogic')
    if not hasattr(model, '_permission_logics'):
        model._permission_logics = set()
    if not hasattr(model, '_permission_handler'):
        from permission.utils.handlers import registry
        # register default permission handler
        registry.register(model, handler=None)
    model._permission_logics.add(permission_logic)
    # store target model to the permission_logic instance
    permission_logic.model = model


Instruction:
How would you implement a function in Python 3 that
removes the specified permission logic from the specified model.

Response:
def remove_permission_logic(model, permission_logic, fail_silently=True):
    """
    Remove permission logic to the model

    Parameters
    ----------
    model : django model class
        A django model class which will be treated by the specified permission
        logic
    permission_logic : permission logic class or instance
        A permission logic class or instance which will be used to determine
        permission of the model
    fail_silently : boolean
        If `True` then do not raise KeyError even the specified permission logic
        have not registered.

    Examples
    --------
    >>> from django.db import models
    >>> from permission.logics import PermissionLogic
    >>> class Mock(models.Model):
    ...     name = models.CharField('name', max_length=120)
    >>> logic = PermissionLogic()
    >>> add_permission_logic(Mock, logic)
    >>> remove_permission_logic(Mock, logic)
    """
    if not hasattr(model, '_permission_logics'):
        model._permission_logics = set()
    if not isinstance(permission_logic, PermissionLogic):
        # remove all permission logic of related
        remove_set = set()
        for _permission_logic in model._permission_logics:
            if _permission_logic.__class__ == permission_logic:
                remove_set.add(_permission_logic)
        # difference
        model._permission_logics = model._permission_logics.difference(remove_set)
    else:
        if fail_silently and permission_logic not in model._permission_logics:
            pass
        else:
            model._permission_logics.remove(permission_logic)


Instruction:
Make a summary of the following Python 3 code
def autodiscover(module_name=None):
    from django.utils.module_loading import module_has_submodule
    from permission.compat import import_module
    from permission.conf import settings

    module_name = module_name or settings.PERMISSION_AUTODISCOVER_MODULE_NAME
    app_names = (app.name for app in apps.app_configs.values())

    for app in app_names:
        mod = import_module(app)
        # Attempt to import the app's perms module
        try:
            # discover the permission module
            discover(app, module_name=module_name)
        except:
            # Decide whether to bubble up this error. If the app just doesn't
            # have an perms module, we can just ignore the error attempting
            # to import it, otherwise we want it to bubble up.
            if module_has_submodule(mod, module_name):
                raise

Response:
Autodiscover INSTALLED_APPS perms. py modules and fail silently when not
    present.


Instruction:
Here you have a function in Python 3, explain what it does
def discover(app, module_name=None):
    from permission.compat import import_module
    from permission.compat import get_model
    from permission.conf import settings
    from permission.utils.logics import add_permission_logic

    variable_name = settings.PERMISSION_AUTODISCOVER_VARIABLE_NAME
    module_name = module_name or settings.PERMISSION_AUTODISCOVER_MODULE_NAME

    # import the module
    m = import_module('%s.%s' % (app, module_name))

    # check if the module have PERMISSION_LOGICS variable
    if hasattr(m, variable_name):
        # apply permission logics automatically
        permission_logic_set = getattr(m, variable_name)
        for model, permission_logic in permission_logic_set:
            if isinstance(model, six.string_types):
                # convert model string to model instance
                model = get_model(*model.split('.', 1))
            add_permission_logic(model, permission_logic)

Response: Discovers the modules and adds the permission logics to the specified module.


Instruction:
Write a Python 3 script to
check if user has permission of himself and permission of object.

Response:
def has_perm(self, user_obj, perm, obj=None):
        """
        Check if user have permission of himself

        If the user_obj is not authenticated, it return ``False``.

        If no object is specified, it return ``True`` when the corresponding
        permission was specified to ``True`` (changed from v0.7.0).
        This behavior is based on the django system.
        https://code.djangoproject.com/wiki/RowLevelPermissions

        If an object is specified, it will return ``True`` if the object is the
        user.
        So users can change or delete themselves (you can change this behavior
        to set ``any_permission``, ``change_permissino`` or
        ``delete_permission`` attributes of this instance).

        Parameters
        ----------
        user_obj : django user model instance
            A django user model instance which be checked
        perm : string
            `app_label.codename` formatted permission string
        obj : None or django model instance
            None or django model instance for object permission

        Returns
        -------
        boolean
            Whether the specified user have specified permission (of specified
            object).
        """
        if not is_authenticated(user_obj):
            return False
        # construct the permission full name
        change_permission = self.get_full_permission_string('change')
        delete_permission = self.get_full_permission_string('delete')
        # check if the user is authenticated
        if obj is None:
            # object permission without obj should return True
            # Ref: https://code.djangoproject.com/wiki/RowLevelPermissions
            if self.any_permission:
                return True
            if self.change_permission and perm == change_permission:
                return True
            if self.delete_permission and perm == delete_permission:
                return True
            return False
        elif user_obj.is_active:
            # check if the user trying to interact with himself
            if obj == user_obj:
                if self.any_permission:
                    # have any kind of permissions to himself
                    return True
                if (self.change_permission and
                        perm == change_permission):
                    return True
                if (self.delete_permission and
                        perm == delete_permission):
                    return True
        return False


Instruction:
Write a Python 3 script for
returning full permission string for the current object.

Response:
def get_full_permission_string(self, perm):
        """
        Return full permission string (app_label.perm_model)
        """
        if not getattr(self, 'model', None):
            raise AttributeError("You need to use `add_permission_logic` to "
                                 "register the instance to the model class "
                                 "before calling this method.")
        app_label = self.model._meta.app_label
        model_name = self.model._meta.object_name.lower()
        return "%s.%s_%s" % (app_label, perm, model_name)


Instruction:
Write a Python 3 function that can
check if user has permission of object.

Response:
def has_perm(self, user_obj, perm, obj=None):
        """
        Check if user have permission (of object) based on registered handlers.

        It will raise ``ObjectDoesNotExist`` exception when the specified
        string permission does not exist and
        ``PERMISSION_CHECK_PERMISSION_PRESENCE`` is ``True`` in ``settings``
        module.

        Parameters
        ----------
        user_obj : django user model instance
            A django user model instance which be checked
        perm : string
            `app_label.codename` formatted permission string
        obj : None or django model instance
            None or django model instance for object permission

        Returns
        -------
        boolean
            Whether the specified user have specified permission (of specified
            object).

        Raises
        ------
        django.core.exceptions.ObjectDoesNotExist
            If the specified string permission does not exist and
            ``PERMISSION_CHECK_PERMISSION_PRESENCE`` is ``True`` in ``settings``
            module.
        """
        if settings.PERMISSION_CHECK_PERMISSION_PRESENCE:
            # get permission instance from string permission (perm)
            # it raise ObjectDoesNotExists when the permission is not exists
            try:
                perm_to_permission(perm)
            except AttributeError:
                # Django 1.2 internally use wrong permission string thus ignore
                pass

        # get permission handlers fot this perm
        cache_name = '_%s_cache' % perm
        if hasattr(self, cache_name):
            handlers = getattr(self, cache_name)
        else:
            handlers = [h for h in registry.get_handlers()
                        if perm in h.get_supported_permissions()]
            setattr(self, cache_name, handlers)
        for handler in handlers:
            if handler.has_perm(user_obj, perm, obj=obj):
                return True
        return False


Instruction:
Here you have a function in Python 3, explain what it does
def has_module_perms(self, user_obj, app_label):
        # get permission handlers fot this perm
        cache_name = '_%s_cache' % app_label
        if hasattr(self, cache_name):
            handlers = getattr(self, cache_name)
        else:
            handlers = [h for h in registry.get_handlers()
                        if app_label in h.get_supported_app_labels()]
            setattr(self, cache_name, handlers)
        for handler in handlers:
            if handler.has_module_perms(user_obj, app_label):
                return True
        return False

Response: Check if user has permission of specified app based on registered modules.


Instruction:
Can you create a Python 3 function that
fetches the body from a message.

Response:
def get_body_from_message(message, maintype, subtype):
    """
    Fetchs the body message matching main/sub content type.
    """
    body = six.text_type('')
    for part in message.walk():
        if part.get('content-disposition', '').startswith('attachment;'):
            continue
        if part.get_content_maintype() == maintype and \
                part.get_content_subtype() == subtype:
            charset = part.get_content_charset()
            this_part = part.get_payload(decode=True)
            if charset:
                try:
                    this_part = this_part.decode(charset, 'replace')
                except LookupError:
                    this_part = this_part.decode('ascii', 'replace')
                    logger.warning(
                        'Unknown encoding %s encountered while decoding '
                        'text payload.  Interpreting as ASCII with '
                        'replacement, but some data may not be '
                        'represented as the sender intended.',
                        charset
                    )
                except ValueError:
                    this_part = this_part.decode('ascii', 'replace')
                    logger.warning(
                        'Error encountered while decoding text '
                        'payload from an incorrectly-constructed '
                        'e-mail; payload was converted to ASCII with '
                        'replacement, but some data may not be '
                        'represented as the sender intended.'
                    )
            else:
                this_part = this_part.decode('ascii', 'replace')

            body += this_part

    return body


Instruction:
Write a Python 3 script for
returning the diameter of a circle.

Response:
def diam_circle(AreaCircle):
    """Return the diameter of a circle."""
    ut.check_range([AreaCircle, ">0", "AreaCircle"])
    return np.sqrt(4 * AreaCircle / np.pi)


Instruction:
Create a Python 3 function to
return the density of water at a given temperature.

Response:
def density_water(temp):
    """Return the density of water at a given temperature.

    If given units, the function will automatically convert to Kelvin.
    If not given units, the function will assume Kelvin.
    """
    ut.check_range([temp, ">0", "Temperature in Kelvin"])
    rhointerpolated = interpolate.CubicSpline(WATER_DENSITY_TABLE[0],
                                                    WATER_DENSITY_TABLE[1])
    return np.asscalar(rhointerpolated(temp))


Instruction:
Given the following Python 3 function, write the documentation
def viscosity_kinematic(temp):
    ut.check_range([temp, ">0", "Temperature in Kelvin"])
    return (viscosity_dynamic(temp).magnitude
            / density_water(temp).magnitude)

Response: Return the kinematic viscosity of water at a given temperature.


Instruction:
Given the following Python 3 function, write the documentation
def re_pipe(FlowRate, Diam, Nu):
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [Diam, ">0", "Diameter"],
                   [Nu, ">0", "Nu"])
    return (4 * FlowRate) / (np.pi * Diam * Nu)

Response: Return the Reynolds Number for a pipe.


Instruction:
Create a Python 3 function to
return the hydraulic radius.

Response:
def radius_hydraulic(Width, DistCenter, openchannel):
    """Return the hydraulic radius.

    Width and DistCenter are length values and openchannel is a boolean.
    """
    ut.check_range([Width, ">0", "Width"], [DistCenter, ">0", "DistCenter"],
                   [openchannel, "boolean", "openchannel"])
    if openchannel:
        return (Width*DistCenter) / (Width + 2*DistCenter)
        # if openchannel is True, the channel is open. Otherwise, the channel
        # is assumed to have a top.
    else:
        return (Width*DistCenter) / (2 * (Width+DistCenter))


Instruction:
Write a Python 3 function that can
return the Reynolds Number for a rectangular channel.

Response:
def re_rect(FlowRate, Width, DistCenter, Nu, openchannel):
    """Return the Reynolds Number for a rectangular channel."""
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([FlowRate, ">0", "Flow rate"], [Nu, ">0", "Nu"])
    return (4 * FlowRate
            * radius_hydraulic(Width, DistCenter, openchannel).magnitude
            / (Width * DistCenter * Nu))


Instruction:
Write a Python 3 function for
returning the Reynolds Number for a general cross section.

Response:
def re_general(Vel, Area, PerimWetted, Nu):
    """Return the Reynolds Number for a general cross section."""
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([Vel, ">=0", "Velocity"], [Nu, ">0", "Nu"])
    return 4 * radius_hydraulic_general(Area, PerimWetted).magnitude * Vel / Nu


Instruction:
Explain what the following Python 3 code does
def fric(FlowRate, Diam, Nu, PipeRough):
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([PipeRough, "0-1", "Pipe roughness"])
    if re_pipe(FlowRate, Diam, Nu) >= RE_TRANSITION_PIPE:
        #Swamee-Jain friction factor for turbulent flow; best for
        #Re>3000 and ε/Diam < 0.02
        f = (0.25 / (np.log10(PipeRough / (3.7 * Diam)
                              + 5.74 / re_pipe(FlowRate, Diam, Nu) ** 0.9
                              )
                     ) ** 2
             )
    else:
        f = 64 / re_pipe(FlowRate, Diam, Nu)
    return f

Response: Return the friction factor for a pipe flow.


Instruction:
Write a Python 3 function for
returning the friction factor for a rectangular channel.

Response:
def fric_rect(FlowRate, Width, DistCenter, Nu, PipeRough, openchannel):
    """Return the friction factor for a rectangular channel."""
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([PipeRough, "0-1", "Pipe roughness"])
    if re_rect(FlowRate,Width,DistCenter,Nu,openchannel) >= RE_TRANSITION_PIPE:
        #Swamee-Jain friction factor adapted for rectangular channel.
        #Diam = 4*R_h in this case.
        return (0.25
                / (np.log10((PipeRough
                             / (3.7 * 4
                                * radius_hydraulic(Width, DistCenter,
                                                   openchannel).magnitude
                                )
                             )
                            + (5.74 / (re_rect(FlowRate, Width, DistCenter,
                                               Nu, openchannel) ** 0.9)
                               )
                            )
                    ) ** 2
                )
    else:
        return 64 / re_rect(FlowRate, Width, DistCenter, Nu, openchannel)


Instruction:
How would you implement a function in Python 3 that
returns the friction factor for a general channel.

Response:
def fric_general(Area, PerimWetted, Vel, Nu, PipeRough):
    """Return the friction factor for a general channel."""
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([PipeRough, "0-1", "Pipe roughness"])
    if re_general(Vel, Area, PerimWetted, Nu) >= RE_TRANSITION_PIPE:
        #Swamee-Jain friction factor adapted for any cross-section.
        #Diam = 4*R*h
        f= (0.25 /
            (np.log10((PipeRough
                       / (3.7 * 4
                          * radius_hydraulic_general(Area, PerimWetted).magnitude
                          )
                       )
                      + (5.74
                         / re_general(Vel, Area, PerimWetted, Nu) ** 0.9
                         )
                      )
             ) ** 2
            )
    else:
        f = 64 / re_general(Vel, Area, PerimWetted, Nu)
    return f


Instruction:
Given the following Python 3 function, write the documentation
def headloss_fric(FlowRate, Diam, Length, Nu, PipeRough):
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([Length, ">0", "Length"])
    return (fric(FlowRate, Diam, Nu, PipeRough)
            * 8 / (gravity.magnitude * np.pi**2)
            * (Length * FlowRate**2) / Diam**5
            )

Response: Return the major head loss in a single object.


Instruction:
Create a Python 3 function to
return the minor head loss due to expansions in a flow.

Response:
def headloss_exp(FlowRate, Diam, KMinor):
    """Return the minor head loss (due to expansions) in a pipe.

    This equation applies to both laminar and turbulent flows.
    """
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [Diam, ">0", "Diameter"],
                   [KMinor, ">=0", "K minor"])
    return KMinor * 8 / (gravity.magnitude * np.pi**2) * FlowRate**2 / Diam**4


Instruction:
Can you generate the documentation for the following Python 3 function
def headloss(FlowRate, Diam, Length, Nu, PipeRough, KMinor):
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    return (headloss_fric(FlowRate, Diam, Length, Nu, PipeRough).magnitude
            + headloss_exp(FlowRate, Diam, KMinor).magnitude)

Response: Return the total head loss from major and minor losses in a single flow.


Instruction:
Can you implement a function in Python 3 that
returns the major head loss due to wall shear in a rectangular channel.

Response:
def headloss_fric_rect(FlowRate, Width, DistCenter, Length, Nu, PipeRough, openchannel):
    """Return the major head loss due to wall shear in a rectangular channel.

    This equation applies to both laminar and turbulent flows.
    """
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([Length, ">0", "Length"])
    return (fric_rect(FlowRate, Width, DistCenter, Nu,
                      PipeRough, openchannel)
            * Length
            / (4 * radius_hydraulic(Width, DistCenter, openchannel).magnitude)
            * FlowRate**2
            / (2 * gravity.magnitude * (Width*DistCenter)**2)
            )


Instruction:
Can you generate a brief explanation for the following Python 3 code
def headloss_exp_rect(FlowRate, Width, DistCenter, KMinor):
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [Width, ">0", "Width"],
                   [DistCenter, ">0", "DistCenter"], [KMinor, ">=0", "K minor"])
    return (KMinor * FlowRate**2
            / (2 * gravity.magnitude * (Width*DistCenter)**2)
            )

Response: Return the minor head loss due to expansion in a rectangular channel.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def headloss_rect(FlowRate, Width, DistCenter, Length,
                  KMinor, Nu, PipeRough, openchannel):
    """Return the total head loss in a rectangular channel.

    Total head loss is a combination of the major and minor losses.
    This equation applies to both laminar and turbulent flows.
    """
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    return (headloss_exp_rect(FlowRate, Width, DistCenter, KMinor).magnitude
              + headloss_fric_rect(FlowRate, Width, DistCenter, Length,
                                   Nu, PipeRough, openchannel).magnitude)

Response: Return the total head loss in a rectangular channel.


Instruction:
How would you explain what the following Python 3 function does
def headloss_fric_general(Area, PerimWetted, Vel, Length, Nu, PipeRough):
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([Length, ">0", "Length"])
    return (fric_general(Area, PerimWetted, Vel, Nu, PipeRough) * Length
            / (4 * radius_hydraulic_general(Area, PerimWetted).magnitude)
            * Vel**2 / (2*gravity.magnitude)
            )

Response: Return the major head loss due to wall shear in the general case.


Instruction:
How would you code a function in Python 3 to
return the minor head loss due to expansion in the general case.

Response:
def headloss_exp_general(Vel, KMinor):
    """Return the minor head loss due to expansion in the general case.

    This equation applies to both laminar and turbulent flows.
    """
    #Checking input validity
    ut.check_range([Vel, ">0", "Velocity"], [KMinor, '>=0', 'K minor'])
    return KMinor * Vel**2 / (2*gravity.magnitude)


Instruction:
Create a Python 3 function for
returning the total head lossin the general case.

Response:
def headloss_gen(Area, Vel, PerimWetted, Length, KMinor, Nu, PipeRough):
    """Return the total head lossin the general case.

    Total head loss is a combination of major and minor losses.
    This equation applies to both laminar and turbulent flows.
    """
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    return (headloss_exp_general(Vel, KMinor).magnitude
            + headloss_fric_general(Area, PerimWetted, Vel,
                                     Length, Nu, PipeRough).magnitude)


Instruction:
Can you generate the documentation for the following Python 3 function
def headloss_manifold(FlowRate, Diam, Length, KMinor, Nu, PipeRough, NumOutlets):
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([NumOutlets, ">0, int", 'Number of outlets'])
    return (headloss(FlowRate, Diam, Length, Nu, PipeRough, KMinor).magnitude
            * ((1/3 )
               + (1 / (2*NumOutlets))
               + (1 / (6*NumOutlets**2))
               )
            )

Response: Return the total head loss through the manifold.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def flow_orifice(Diam, Height, RatioVCOrifice):
    #Checking input validity
    ut.check_range([Diam, ">0", "Diameter"],
                   [RatioVCOrifice, "0-1", "VC orifice ratio"])
    if Height > 0:
        return (RatioVCOrifice * area_circle(Diam).magnitude
                * np.sqrt(2 * gravity.magnitude * Height))
    else:
        return 0

Response: Return the flow rate of the orifice.


Instruction:
How would you code a function in Python 3 to
return the vertical flow rate of the orifice.

Response:
def flow_orifice_vert(Diam, Height, RatioVCOrifice):
    """Return the vertical flow rate of the orifice."""
    #Checking input validity
    ut.check_range([RatioVCOrifice, "0-1", "VC orifice ratio"])
    if Height > -Diam / 2:
        flow_vert = integrate.quad(lambda z: (Diam * np.sin(np.arccos(z/(Diam/2)))
                                                   * np.sqrt(Height - z)
                                                   ),
                                                   - Diam / 2,
                                                   min(Diam/2, Height))
        return flow_vert[0] * RatioVCOrifice * np.sqrt(2 * gravity.magnitude)
    else:
        return 0


Instruction:
Can you write a function in Python 3 where it
returns the head of the orifice.

Response:
def head_orifice(Diam, RatioVCOrifice, FlowRate):
    """Return the head of the orifice."""
    #Checking input validity
    ut.check_range([Diam, ">0", "Diameter"], [FlowRate, ">0", "Flow rate"],
                   [RatioVCOrifice, "0-1", "VC orifice ratio"])
    return ((FlowRate
             / (RatioVCOrifice * area_circle(Diam).magnitude)
             )**2
            / (2*gravity.magnitude)
            )


Instruction:
Here you have a function in Python 3, explain what it does
def area_orifice(Height, RatioVCOrifice, FlowRate):
    #Checking input validity
    ut.check_range([Height, ">0", "Height"], [FlowRate, ">0", "Flow rate"],
                   [RatioVCOrifice, "0-1, >0", "VC orifice ratio"])
    return FlowRate / (RatioVCOrifice * np.sqrt(2 * gravity.magnitude * Height))

Response: Return the area of the orifice.


Instruction:
How would you explain what the following Python 3 function does
def num_orifices(FlowPlant, RatioVCOrifice, HeadLossOrifice, DiamOrifice):
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    return np.ceil(area_orifice(HeadLossOrifice, RatioVCOrifice,
                                 FlowPlant).magnitude
                    / area_circle(DiamOrifice).magnitude)

Response: Return the number of orifices in a single orifile.


Instruction:
Create a Python 3 function to
return the flow rate for the laminar and turbulent transition.

Response:
def flow_transition(Diam, Nu):
    """Return the flow rate for the laminar/turbulent transition.

    This equation is used in some of the other equations for flow.
    """
    #Checking input validity
    ut.check_range([Diam, ">0", "Diameter"], [Nu, ">0", "Nu"])
    return np.pi * Diam * RE_TRANSITION_PIPE * Nu / 4


Instruction:
Can you tell what is the following Python 3 function doing
def flow_hagen(Diam, HeadLossFric, Length, Nu):
    #Checking input validity
    ut.check_range([Diam, ">0", "Diameter"], [Length, ">0", "Length"],
                   [HeadLossFric, ">=0", "Headloss due to friction"],
                   [Nu, ">0", "Nu"])
    return (np.pi*Diam**4) / (128*Nu) * gravity.magnitude * HeadLossFric / Length

Response: Return the flow rate for laminar flow with only major losses.


Instruction:
Can you create a Python 3 function that
returns the flow rate for turbulent flow with only major losses.

Response:
def flow_swamee(Diam, HeadLossFric, Length, Nu, PipeRough):
    """Return the flow rate for turbulent flow with only major losses."""
    #Checking input validity
    ut.check_range([Diam, ">0", "Diameter"], [Length, ">0", "Length"],
                   [HeadLossFric, ">0", "Headloss due to friction"],
                   [Nu, ">0", "Nu"], [PipeRough, "0-1", "Pipe roughness"])
    logterm = np.log10(PipeRough / (3.7 * Diam)
                       + 2.51 * Nu * np.sqrt(Length / (2 * gravity.magnitude
                                                         * HeadLossFric
                                                         * Diam**3)
                                              )
                       )
    return ((-np.pi / np.sqrt(2)) * Diam**(5/2) * logterm
            * np.sqrt(gravity.magnitude * HeadLossFric / Length)
            )


Instruction:
Can you generate a brief explanation for the following Python 3 code
def flow_pipemajor(Diam, HeadLossFric, Length, Nu, PipeRough):
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    FlowHagen = flow_hagen(Diam, HeadLossFric, Length, Nu).magnitude
    if FlowHagen < flow_transition(Diam, Nu).magnitude:
        return FlowHagen
    else:
        return flow_swamee(Diam, HeadLossFric, Length, Nu, PipeRough).magnitude

Response: Return the flow rate with only major losses.


Instruction:
Here you have a function in Python 3, explain what it does
def flow_pipeminor(Diam, HeadLossExpans, KMinor):
    #Checking input validity - inputs not checked here are checked by
    #functions this function calls.
    ut.check_range([HeadLossExpans, ">=0", "Headloss due to expansion"],
                   [KMinor, ">0", "K minor"])
    return (area_circle(Diam).magnitude * np.sqrt(2 * gravity.magnitude
                                                  * HeadLossExpans
                                                  / KMinor)
            )

Response: Return the flow rate with only minor losses.


Instruction:
Write a Python 3 function that can
return the flow in a straight pipe.

Response:
def flow_pipe(Diam, HeadLoss, Length, Nu, PipeRough, KMinor):
    """Return the the flow in a straight pipe.

    This function works for both major and minor losses and
    works whether the flow is laminar or turbulent.
    """
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    if KMinor == 0:
        FlowRate = flow_pipemajor(Diam, HeadLoss, Length, Nu,
                                  PipeRough).magnitude
    else:
        FlowRatePrev = 0
        err = 1.0
        FlowRate = min(flow_pipemajor(Diam, HeadLoss, Length,
                                      Nu, PipeRough).magnitude,
                       flow_pipeminor(Diam, HeadLoss, KMinor).magnitude
                       )
        while err > 0.01:
            FlowRatePrev = FlowRate
            HLFricNew = (HeadLoss * headloss_fric(FlowRate, Diam, Length,
                                                  Nu, PipeRough).magnitude
                         / (headloss_fric(FlowRate, Diam, Length,
                                          Nu, PipeRough).magnitude
                            + headloss_exp(FlowRate, Diam, KMinor).magnitude
                            )
                         )
            FlowRate = flow_pipemajor(Diam, HLFricNew, Length,
                                      Nu, PipeRough).magnitude
            if FlowRate == 0:
                err = 0.0
            else:
                err = (abs(FlowRate - FlowRatePrev)
                       / ((FlowRate + FlowRatePrev) / 2)
                       )
    return FlowRate


Instruction:
Can you generate the documentation for the following Python 3 function
def diam_swamee(FlowRate, HeadLossFric, Length, Nu, PipeRough):
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [Length, ">0", "Length"],
                   [HeadLossFric, ">0", "Headloss due to friction"],
                   [Nu, ">0", "Nu"], [PipeRough, "0-1", "Pipe roughness"])
    a = ((PipeRough ** 1.25)
         * ((Length * FlowRate**2)
            / (gravity.magnitude * HeadLossFric)
            )**4.75
         )
    b = (Nu * FlowRate**9.4
         * (Length / (gravity.magnitude *  HeadLossFric)) ** 5.2
         )
    return 0.66 * (a+b)**0.04

Response: Return the inner diameter of a Swamee Jain flow.


Instruction:
Implement a Python 3 function for
returning the pipe IDiam that would result in given major losses.

Response:
def diam_pipemajor(FlowRate, HeadLossFric, Length, Nu, PipeRough):
    """Return the pipe IDiam that would result in given major losses.
    This function applies to both laminar and turbulent flow.
    """
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    DiamLaminar = diam_hagen(FlowRate, HeadLossFric, Length, Nu).magnitude
    if re_pipe(FlowRate, DiamLaminar, Nu) <= RE_TRANSITION_PIPE:
        return DiamLaminar
    else:
        return diam_swamee(FlowRate, HeadLossFric, Length,
                           Nu, PipeRough).magnitude


Instruction:
Here you have a function in Python 3, explain what it does
def diam_pipeminor(FlowRate, HeadLossExpans, KMinor):
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [KMinor, ">=0", "K minor"],
                   [HeadLossExpans, ">0", "Headloss due to expansion"])
    return (np.sqrt(4 * FlowRate / np.pi)
            * (KMinor / (2 * gravity.magnitude * HeadLossExpans)) ** (1/4)
            )

Response: Return the pipe ID that would result in the given minor losses.


Instruction:
Can you write a function in Python 3 where it
returns the pipe ID that would result in the given total head loss. This function applies to both laminar and turbulent flow and incorporates both minor and major losses.

Response:
def diam_pipe(FlowRate, HeadLoss, Length, Nu, PipeRough, KMinor):
    """Return the pipe ID that would result in the given total head loss.

    This function applies to both laminar and turbulent flow and
    incorporates both minor and major losses.
    """
    #Inputs do not need to be checked here because they are checked by
    #functions this function calls.
    if KMinor == 0:
        Diam = diam_pipemajor(FlowRate, HeadLoss, Length, Nu,
                              PipeRough).magnitude
    else:
        Diam = max(diam_pipemajor(FlowRate, HeadLoss,
                                  Length, Nu, PipeRough).magnitude,
                   diam_pipeminor(FlowRate, HeadLoss, KMinor).magnitude)
        err = 1.00
        while err > 0.001:
            DiamPrev = Diam
            HLFricNew = (HeadLoss * headloss_fric(FlowRate, Diam, Length,
                                                  Nu, PipeRough
                                                  ).magnitude
                         / (headloss_fric(FlowRate, Diam, Length,
                                          Nu, PipeRough
                                          ).magnitude
                                          + headloss_exp(FlowRate,
                                                         Diam, KMinor
                                                         ).magnitude
                            )
                         )
            Diam = diam_pipemajor(FlowRate, HLFricNew, Length, Nu, PipeRough
                                  ).magnitude
            err = abs(Diam - DiamPrev) / ((Diam + DiamPrev) / 2)
    return Diam


Instruction:
Can you create a Python 3 function that
returns the width of a rectangular weir.

Response:
def width_rect_weir(FlowRate, Height):
    """Return the width of a rectangular weir."""
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [Height, ">0", "Height"])
    return ((3 / 2) * FlowRate
            / (con.VC_ORIFICE_RATIO * np.sqrt(2 * gravity.magnitude) * Height ** (3 / 2))
            )


Instruction:
Write a Python 3 script for
returning the headloss of a weir.

Response:
def headloss_weir(FlowRate, Width):
    """Return the headloss of a weir."""
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [Width, ">0", "Width"])
    return (((3/2) * FlowRate
             / (con.VC_ORIFICE_RATIO * np.sqrt(2 * gravity.magnitude) * Width)
             ) ** (2/3))


Instruction:
Here you have a function in Python 3, explain what it does
def flow_rect_weir(Height, Width):
    #Checking input validity
    ut.check_range([Height, ">0", "Height"], [Width, ">0", "Width"])
    return ((2/3) * con.VC_ORIFICE_RATIO
            * (np.sqrt(2*gravity.magnitude) * Height**(3/2))
            * Width)

Response: Return the flow of a rectangular weir.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def height_water_critical(FlowRate, Width):
    #Checking input validity
    ut.check_range([FlowRate, ">0", "Flow rate"], [Width, ">0", "Width"])
    return (FlowRate / (Width * np.sqrt(gravity.magnitude))) ** (2/3)

Response: Return the critical local water depth.


Instruction:
Can you create a Python 3 function that
returns the horizontal velocity.

Response:
def vel_horizontal(HeightWaterCritical):
    """Return the horizontal velocity."""
    #Checking input validity
    ut.check_range([HeightWaterCritical, ">0", "Critical height of water"])
    return np.sqrt(gravity.magnitude * HeightWaterCritical)


Instruction:
How would you explain what the following Python 3 function does
def headloss_kozeny(Length, Diam, Vel, Porosity, Nu):
    #Checking input validity
    ut.check_range([Length, ">0", "Length"], [Diam, ">0", "Diam"],
                   [Vel, ">0", "Velocity"], [Nu, ">0", "Nu"],
                   [Porosity, "0-1", "Porosity"])
    return (K_KOZENY * Length * Nu
            / gravity.magnitude * (1-Porosity)**2
            / Porosity**3 * 36 * Vel
            / Diam ** 2)

Response: Return the Carmen Kozeny Sand Bed head loss.


Instruction:
How would you explain what the following Python 3 function does
def vol_per_rev_3_stop(color="", inner_diameter=0):
    if color != "":
        inner_diameter = ID_colored_tube(color)
    term1 = (R_pump * 2 * np.pi - k_nonlinear * inner_diameter) / u.rev
    term2 = np.pi * (inner_diameter ** 2) / 4
    return (term1 * term2).to(u.mL/u.rev)

Response: Return the volume per revolution of an Ismatec 6 roller pump on a 3 - stop tubing.


Instruction:
How would you explain what the following Python 3 function does
def ID_colored_tube(color):
    tubing_data_path = os.path.join(os.path.dirname(__file__), "data",
        "3_stop_tubing.txt")
    df = pd.read_csv(tubing_data_path, delimiter='\t')
    idx = df["Color"] == color
    return df[idx]['Diameter (mm)'].values[0] * u.mm

Response: Look up the inner diameter of Ismatec 3 - stop tubing given its color code.


Instruction:
Write a Python 3 function for
looking up the volume per revolution output by a Masterflex L / S pump through the L / S tubing of the given ID number.

Response:
def vol_per_rev_LS(id_number):
    """Look up the volume per revolution output by a Masterflex L/S pump
    through L/S tubing of the given ID number.

    :param id_number: Identification number of the L/S tubing. Valid numbers are 13-18, 24, 35, and 36.
    :type id_number: int

    :return: Volume per revolution output by a Masterflex L/S pump through the L/S tubing
    :rtype: float

    :Examples:

    >>> from aguaclara.research.peristaltic_pump import vol_per_rev_LS
    >>> from aguaclara.core.units import unit_registry as u
    >>> vol_per_rev_LS(13)
    <Quantity(0.06, 'milliliter / turn')>
    >>> vol_per_rev_LS(18)
    <Quantity(3.8, 'milliliter / turn')>
    """
    tubing_data_path = os.path.join(os.path.dirname(__file__), "data",
        "LS_tubing.txt")
    df = pd.read_csv(tubing_data_path, delimiter='\t')
    idx = df["Number"] == id_number
    return df[idx]['Flow (mL/rev)'].values[0] * u.mL/u.turn


Instruction:
Can you tell what is the following Python 3 function doing
def flow_rate(vol_per_rev, rpm):
    return (vol_per_rev * rpm).to(u.mL/u.s)

Response:
Return the flow rate of a pump given the volume of fluid pumped per
    revolution and the desired pump speed.


Instruction:
Can you generate the documentation for the following Python 3 function
def k_value_expansion(ent_pipe_id, exit_pipe_id, q,
                      fitting_angle=180, rounded=False,
                      nu=con.WATER_NU, pipe_rough=mats.PVC_PIPE_ROUGH):
    """Calculates the minor loss coefficient (k-value) of a square,
    tapered, or rounded expansion in a pipe. Defaults to square.

    To use tapered, set angle to something that isn't 180.

    To use rounded, set rounded to True.

    Parameters:
        ent_pipe_id: Entrance pipe's inner diameter from which fluid flows.
        exit_pipe_id: Exit pipe's inner diameter to which fluid flows.
        q: Fluid's flow rate.

        fitting_angle: Fitting angle. Default: square (180 degrees).
        rounded: Rounded fitting. Default: square (False).

        nu: Fluid's dynamic viscosity of the fluid. Default: room
            temperature water (1 * 10**-6 * m**2/s)
        pipe_rough: Pipe roughness. Default: PVC pipe roughness

    Returns:
        k-value of expansion.
    """

    if ent_pipe_id > exit_pipe_id:
        print('k_value_expansion: Entrance pipe\'s inner diameter is larger '
              'than exit pipe\'s inner diameter, using reduction instead.')
        return k_value_reduction(ent_pipe_id, exit_pipe_id, q,
                                 fitting_angle, rounded,
                                 nu, pipe_rough)

    f = pc.fric(q, ent_pipe_id, nu, pipe_rough)  # Darcy friction factor.
    re = pc.re_pipe(q, ent_pipe_id, nu)          # Entrance pipe's Reynolds number.

    fitting_type = _get_fitting_type(fitting_angle, rounded)

    if fitting_type == 'square':
        return _k_value_square_expansion(ent_pipe_id, exit_pipe_id, re, f)
    elif fitting_type == 'tapered':
        return _k_value_tapered_expansion(ent_pipe_id, exit_pipe_id, re, f)
    elif fitting_type == 'rounded':
        return _k_value_rounded_expansion(ent_pipe_id, exit_pipe_id, re)
    elif fitting_type == 'ambiguous':
        raise ValueError('The fitting is ambiguously both tapered and rounded. '
                         'Please set only either fitting_angle or rounded.')

Response: Calculates the minor loss coefficient of an expansion in a pipe.


Instruction:
Create a Python 3 function for
calculating the minor loss coefficient of a square or rounded reduction in a pipe.

Response:
def k_value_reduction(ent_pipe_id, exit_pipe_id, q,
                      fitting_angle=180, rounded=False,
                      nu=con.WATER_NU, pipe_rough=mats.PVC_PIPE_ROUGH):
    """Calculates the minor loss coefficient (k-value) of a square,
    tapered, or rounded reduction in a pipe. Defaults to square.

    To use tapered, set angle to something that isn't 180.

    To use rounded, set rounded to True.

    Parameters:
        ent_pipe_id: Entrance pipe's inner diameter from which fluid flows.
        exit_pipe_id: Exit pipe's inner diameter to which fluid flows.
        q: Fluid's q rate.

        fitting_angle: Fitting angle. Default: square (180 degrees).
        rounded: Rounded fitting. Default: square (False).

        nu: Fluid's dynamic viscosity of the fluid. Default: room
            temperature water (1 * 10**-6 * m**2/s)
        pipe_rough: Pipe roughness. Default: PVC pipe roughness

    Returns:
        k-value of reduction.
    """

    if ent_pipe_id < exit_pipe_id:
        print('k_value_reduction: Entrance pipe\'s inner diameter is less than '
              'exit pipe\'s inner diameter, using expansion instead.')
        return k_value_expansion(ent_pipe_id, exit_pipe_id, q,
                                 fitting_angle, rounded,
                                 nu, pipe_rough)

    f = pc.fric(q, ent_pipe_id, nu, pipe_rough)     # Darcy friction factor.
    re = pc.re_pipe(q, ent_pipe_id, nu)             # Entrance pipe's Reynolds number.

    fitting_type = _get_fitting_type(fitting_angle, rounded)

    if fitting_type == 'square':
        return _k_value_square_reduction(ent_pipe_id, exit_pipe_id, re, f)
    elif fitting_type == 'tapered':
        return _k_value_tapered_reduction(ent_pipe_id, exit_pipe_id, fitting_angle, re, f)
    elif fitting_type == 'rounded':
        return _k_value_rounded_reduction(ent_pipe_id, exit_pipe_id, re)
    elif fitting_type == 'ambiguous':
        raise ValueError('The fitting is ambiguously both tapered and rounded.'
                         'Please set only either fitting_angle or rounded.')


Instruction:
Can you generate the documentation for the following Python 3 function
def k_value_orifice(pipe_id, orifice_id, orifice_l, q,
                    nu=con.WATER_NU):
    """Calculates the minor loss coefficient of an orifice plate in a
    pipe.

    Parameters:
        pipe_id: Entrance pipe's inner diameter from which fluid flows.
        orifice_id: Orifice's inner diameter.
        orifice_l: Orifice's length from start to end.
        q: Fluid's q rate.

        nu: Fluid's dynamic viscosity of the fluid. Default: room
            temperature water (1 * 10**-6 * m**2/s)

    Returns:
        k-value at the orifice.
    """

    if orifice_id > pipe_id:
        raise ValueError('The orifice\'s inner diameter cannot be larger than'
                         'that of the entrance pipe.')

    re = pc.re_pipe(q, pipe_id, nu)  # Entrance pipe's Reynolds number.

    orifice_type = _get_orifice_type(orifice_l, orifice_id)

    if orifice_type == 'thin':
        return _k_value_thin_sharp_orifice(pipe_id, orifice_id, re)
    elif orifice_type == 'thick':
        return _k_value_thick_orifice(pipe_id, orifice_id, orifice_l, re)
    elif orifice_type == 'oversize':
        return k_value_reduction(pipe_id, orifice_id, q) \
               + k_value_expansion(orifice_id, pipe_id, q)

Response: Calculates the minor loss coefficient of an orifice plate in a pipe.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _k_value_square_reduction(ent_pipe_id, exit_pipe_id, re, f):

    if re < 2500:
        return (1.2 + (160 / re)) * ((ent_pipe_id / exit_pipe_id) ** 4)
    else:
        return (0.6 + 0.48 * f) * (ent_pipe_id / exit_pipe_id) ** 2\
            * ((ent_pipe_id / exit_pipe_id) ** 2 - 1)

Response: Returns the minor loss coefficient for a square reducer.


Instruction:
Implement a function in Python 3 to
return the minor loss coefficient for a tapered reducer.

Response:
def _k_value_tapered_reduction(ent_pipe_id, exit_pipe_id, fitting_angle, re, f):
    """Returns the minor loss coefficient for a tapered reducer.

    Parameters:
        ent_pipe_id: Entrance pipe's inner diameter.
        exit_pipe_id: Exit pipe's inner diameter.
        fitting_angle: Fitting angle between entrance and exit pipes.
        re: Reynold's number.
        f: Darcy friction factor.
    """

    k_value_square_reduction = _k_value_square_reduction(ent_pipe_id, exit_pipe_id,
                                                         re, f)

    if 45 < fitting_angle <= 180:
        return k_value_square_reduction * np.sqrt(np.sin(fitting_angle / 2))
    elif 0 < fitting_angle <= 45:
        return k_value_square_reduction * 1.6 * np.sin(fitting_angle / 2)
    else:
        raise ValueError('k_value_tapered_reduction: The reducer angle ('
                         + fitting_angle + ') cannot be outside of [0,180].')


Instruction:
Explain what the following Python 3 code does
def drain_OD(q_plant, T, depth_end, SDR):
    nu = pc.viscosity_kinematic(T)
    K_minor = con.PIPE_ENTRANCE_K_MINOR + con.PIPE_EXIT_K_MINOR + con.EL90_K_MINOR
    drain_ID = pc.diam_pipe(q_plant, depth_end, depth_end, nu, mat.PVC_PIPE_ROUGH, K_minor)
    drain_ND = pipe.SDR_available_ND(drain_ID, SDR)
    return pipe.OD(drain_ND).magnitude

Response: Return the nominal diameter of the entrance tank drain pipe.


Instruction:
Can you tell what is the following Python 3 function doing
def num_plates_ET(q_plant, W_chan):
    num_plates = np.ceil(np.sqrt(q_plant / (design.ent_tank.CENTER_PLATE_DIST.magnitude
                                            * W_chan * design.ent_tank.CAPTURE_BOD_VEL.magnitude * np.sin(
                design.ent_tank.PLATE_ANGLE.to(u.rad).magnitude))))
    return num_plates

Response: Return the number of plates in the entrance tank.


Instruction:
Create a Python 3 function to
return the length of the plates in the entrance tank.

Response:
def L_plate_ET(q_plant, W_chan):
    """Return the length of the plates in the entrance tank.

    Parameters
    ----------
    q_plant: float
        Plant flow rate

    W_chan: float
        Width of channel

    Returns
    -------
    float
        ?

    Examples
    --------
    >>> from aguaclara.play import*
    >>> L_plate_ET(20*u.L/u.s,2*u.m)
    0.00194
    """
    L_plate = (q_plant / (num_plates_ET(q_plant, W_chan) * W_chan *
                          design.ent_tank.CAPTURE_BOD_VEL.magnitude * np.cos(
                design.ent_tank.PLATE_ANGLE.to(u.rad).magnitude)))
    - (design.ent_tank.PLATE_S.magnitude * np.tan(design.ent_tank.PLATE_ANGLE.to(u.rad).magnitude))
    return L_plate


Instruction:
Make a summary of the following Python 3 code
def alpha0_carbonate(pH):
    alpha0_carbonate = 1/(1+(K1_carbonate/invpH(pH)) *
                            (1+(K2_carbonate/invpH(pH))))
    return alpha0_carbonate

Response: Calculates the fraction of total carbonates in carbonic acid form.


Instruction:
Make a summary of the following Python 3 code
def alpha1_carbonate(pH):
    alpha1_carbonate = 1/((invpH(pH)/K1_carbonate) + 1 +
                          (K2_carbonate/invpH(pH)))
    return alpha1_carbonate

Response: Calculates the fraction of total carbonates in bicarbonate form.


Instruction:
How would you code a function in Python 3 to
calculate the fraction of total carbonates in carbonate form ( CO3 - 2

Response:
def alpha2_carbonate(pH):
    """Calculate the fraction of total carbonates in carbonate form (CO3-2)

    :param pH: pH of the system
    :type pH: float

    :return: Fraction of carbonates in carbonate form (CO3-2)
    :rtype: float

    :Examples:

    >>> from aguaclara.research.environmental_processes_analysis import alpha2_carbonate
    >>> round(alpha2_carbonate(10), 7)
    <Quantity(0.359881, 'dimensionless')>
    """
    alpha2_carbonate = 1/(1+(invpH(pH)/K2_carbonate) *
                            (1+(invpH(pH)/K1_carbonate)))
    return alpha2_carbonate


Instruction:
Explain what the following Python 3 code does
def ANC_closed(pH, total_carbonates):
    return (total_carbonates * (u.eq/u.mol * alpha1_carbonate(pH) +
            2 * u.eq/u.mol * alpha2_carbonate(pH)) +
            1 * u.eq/u.mol * Kw/invpH(pH) - 1 * u.eq/u.mol * invpH(pH))

Response:
Calculates the acid neutralizing capacity under a closed system
   .


Instruction:
Given the following Python 3 function, write the documentation
def aeration_data(DO_column, dirpath):
    #return the list of files in the directory
    filenames = os.listdir(dirpath)
    #extract the flowrates from the filenames and apply units
    airflows = ((np.array([i.split('.', 1)[0] for i in filenames])).astype(np.float32))
    #sort airflows and filenames so that they are in ascending order of flow rates
    idx = np.argsort(airflows)
    airflows = (np.array(airflows)[idx])*u.umole/u.s
    filenames = np.array(filenames)[idx]

    filepaths = [os.path.join(dirpath, i) for i in filenames]
    #DO_data is a list of numpy arrays. Thus each of the numpy data arrays can have different lengths to accommodate short and long experiments
    # cycle through all of the files and extract the column of data with oxygen concentrations and the times
    DO_data=[column_of_data(i,0,DO_column,-1,'mg/L') for i in filepaths]
    time_data=[(column_of_time(i,0,-1)).to(u.s) for i in filepaths]
    aeration_collection = collections.namedtuple('aeration_results','filepaths airflows DO_data time_data')
    aeration_results = aeration_collection(filepaths, airflows, DO_data, time_data)
    return aeration_results

Response: This function extracts the data from the folder containing tab delimited aeration data.


Instruction:
Given the following Python 3 function, write the documentation
def O2_sat(P_air, temp):
    fraction_O2 = 0.21
    P_O2 = P_air * fraction_O2
    return ((P_O2.to(u.atm).magnitude) *
            u.mg/u.L*np.exp(1727 / temp.to(u.K).magnitude - 2.105))

Response: Calculate satured oxygen concentration in mg / L for 278 K < T < 318 K


Instruction:
Create a Python 3 function to
extract the data from a ProCoDA Gran plot file.

Response:
def Gran(data_file_path):
    """Extract the data from a ProCoDA Gran plot file. The file must be the original tab delimited file.

    :param data_file_path: The path to the file. If the file is in the working directory, then the file name is sufficient.

    :return: collection of

        * **V_titrant** (*float*) - Volume of titrant in mL
        * **ph_data** (*numpy.array*) - pH of the sample
        * **V_sample** (*float*) - Volume of the original sample that was titrated in mL
        * **Normality_titrant** (*float*) - Normality of the acid used to titrate the sample in mole/L
        * **V_equivalent** (*float*) - Volume of acid required to consume all of the ANC in mL
        * **ANC** (*float*) - Acid Neutralizing Capacity of the sample in mole/L
    """
    df = pd.read_csv(data_file_path, delimiter='\t', header=5)
    V_t = np.array(pd.to_numeric(df.iloc[0:, 0]))*u.mL
    pH = np.array(pd.to_numeric(df.iloc[0:, 1]))
    df = pd.read_csv(data_file_path, delimiter='\t', header=-1, nrows=5)
    V_S = pd.to_numeric(df.iloc[0, 1])*u.mL
    N_t = pd.to_numeric(df.iloc[1, 1])*u.mole/u.L
    V_eq = pd.to_numeric(df.iloc[2, 1])*u.mL
    ANC_sample = pd.to_numeric(df.iloc[3, 1])*u.mole/u.L
    Gran_collection = collections.namedtuple('Gran_results', 'V_titrant ph_data V_sample Normality_titrant V_equivalent ANC')
    Gran = Gran_collection(V_titrant=V_t, ph_data=pH, V_sample=V_S,
                           Normality_titrant=N_t, V_equivalent=V_eq,
                           ANC=ANC_sample)
    return Gran


Instruction:
Can you create a Python 3 function that
calculates the effluent concentration of a conversative non - reacting CMFR at time t.

Response:
def CMFR(t, C_initial, C_influent):
    """Calculate the effluent concentration of a conversative (non-reacting)
    material with continuous input to a completely mixed flow reactor.

    Note: time t=0 is the time at which the material starts to flow into the
    reactor.

    :param C_initial: The concentration in the CMFR at time t=0.
    :type C_initial: float
    :param C_influent: The concentration entering the CMFR.
    :type C_influent: float
    :param t: The time(s) at which to calculate the effluent concentration. Time can be made dimensionless by dividing by the residence time of the CMFR.
    :type t: float or numpy.array

    :return: Effluent concentration
    :rtype: float

    :Examples:

    >>> from aguaclara.research.environmental_processes_analysis import CMFR
    >>> from aguaclara.core.units import unit_registry as u
    >>> round(CMFR(0.1, 0*u.mg/u.L, 10*u.mg/u.L), 7)
    <Quantity(0.9516258, 'milligram / liter')>
    >>> round(CMFR(0.9, 5*u.mg/u.L, 10*u.mg/u.L), 7)
    <Quantity(7.9671517, 'milligram / liter')>
    """
    return C_influent * (1-np.exp(-t)) + C_initial*np.exp(-t)


Instruction:
Given the following Python 3 function, write the documentation
def E_CMFR_N(t, N):
    return (N**N)/special.gamma(N) * (t**(N-1))*np.exp(-N*t)

Response: Calculates a dimensionless measure of the output tracer concentration from a spike input to a series of completely mixed flow reactors.


Instruction:
Implement a Python 3 function for
calculating a dimensionless measure of the output tracer concentration from a spike input to reactor with advection and dispersion.

Response:
def E_Advective_Dispersion(t, Pe):
    """Calculate a dimensionless measure of the output tracer concentration from
    a spike input to reactor with advection and dispersion.

    :param t: The time(s) at which to calculate the effluent concentration. Time can be made dimensionless by dividing by the residence time of the CMFR.
    :type t: float or numpy.array
    :param Pe: The ratio of advection to dispersion ((mean fluid velocity)/(Dispersion*flow path length))
    :type Pe: float

    :return: dimensionless measure of the output tracer concentration (concentration * volume of reactor) / (mass of tracer)
    :rtype: float

    :Examples:

    >>> from aguaclara.research.environmental_processes_analysis import E_Advective_Dispersion
    >>> round(E_Advective_Dispersion(0.5, 5), 7)
    0.4774864
    """
    # replace any times at zero with a number VERY close to zero to avoid
    # divide by zero errors
    if isinstance(t, list):
        t[t == 0] = 10**(-10)
    return (Pe/(4*np.pi*t))**(0.5)*np.exp((-Pe*((1-t)**2))/(4*t))


Instruction:
Create a Python 3 function for
using by Solver_CMFR_N. All inputs and outputs are unitless. This is The model function, f(x, ...). It takes the independent variable as the first argument and the parameters to fit as separate remaining arguments. :param t_seconds: List of times :type t_seconds: float list :param t_bar: Average time spent in the reactor :type t_bar: float :param C_bar: Average concentration (mass of tracer)/(volume of the reactor) :type C_bar: float :param N: Number of completely mixed flow reactors (CMFRs) in series, must be greater than 1 :type N: int :return: The model concentration as a function of time :rtype: float list :Examples: >>> from aguaclara.research.environmental_processes_analysis import Tracer_CMFR_N >>> from aguaclara.core.units import unit_registry as u >>> Tracer_CMFR_N([1, 2, 3, 4, 5]*u.s, 5*u.s, 10*u.mg/u.L, 3) <Quantity([2.96358283 6.50579498 8.03352597 7.83803116 6.72125423], 'milligram / liter')>

Response:
def Tracer_CMFR_N(t_seconds, t_bar, C_bar, N):
    """Used by Solver_CMFR_N. All inputs and outputs are unitless. This is
    The model function, f(x, ...). It takes the independent variable as the
    first argument and the parameters to fit as separate remaining arguments.

    :param t_seconds: List of times
    :type t_seconds: float list
    :param t_bar: Average time spent in the reactor
    :type t_bar: float
    :param C_bar: Average concentration (mass of tracer)/(volume of the reactor)
    :type C_bar: float
    :param N: Number of completely mixed flow reactors (CMFRs) in series, must be greater than 1
    :type N: int

    :return: The model concentration as a function of time
    :rtype: float list

    :Examples:

    >>> from aguaclara.research.environmental_processes_analysis import Tracer_CMFR_N
    >>> from aguaclara.core.units import unit_registry as u
    >>> Tracer_CMFR_N([1, 2, 3, 4, 5]*u.s, 5*u.s, 10*u.mg/u.L, 3)
    <Quantity([2.96358283 6.50579498 8.03352597 7.83803116 6.72125423], 'milligram / liter')>
    """
    return C_bar*E_CMFR_N(t_seconds/t_bar, N)


Instruction:
Given the following Python 3 function, write the documentation
def Solver_CMFR_N(t_data, C_data, theta_guess, C_bar_guess):
    C_unitless = C_data.magnitude
    C_units = str(C_bar_guess.units)
    t_seconds = (t_data.to(u.s)).magnitude
    # assume that a guess of 1 reactor in series is close enough to get a solution
    p0 = [theta_guess.to(u.s).magnitude, C_bar_guess.magnitude,1]
    popt, pcov = curve_fit(Tracer_CMFR_N, t_seconds, C_unitless, p0)
    Solver_theta = popt[0]*u.s
    Solver_C_bar = popt[1]*u(C_units)
    Solver_N = popt[2]
    Reactor_results = collections.namedtuple('Reactor_results','theta C_bar N')
    CMFR = Reactor_results(theta=Solver_theta, C_bar=Solver_C_bar, N=Solver_N)
    return CMFR

Response:
Use non - linear least squares to fit the function
 Tracer_CMFR_N t_seconds C_data C_bar_guess N to reactor data.


Instruction:
Create a Python 3 function for
using by Solver_AD_Pe. All inputs and outputs are unitless. This is the model function, f(x, ...). It takes the independent variable as the first argument and the parameters to fit as separate remaining arguments. :param t_seconds: List of times :type t_seconds: float list :param t_bar: Average time spent in the reactor :type t_bar: float :param C_bar: Average concentration ((mass of tracer)/(volume of the reactor)) :type C_bar: float :param Pe: The Peclet number for the reactor. :type Pe: float :return: The model concentration as a function of time :rtype: float list :Examples: >>> from aguaclara.research.environmental_processes_analysis import Tracer_AD_Pe >>> from aguaclara.core.units import unit_registry as u >>> Tracer_AD_Pe([1, 2, 3, 4, 5]*u.s, 5*u.s, 10*u.mg/u.L, 5) <Quantity([0.25833732 3.23793989 5.8349833 6.62508831 6.30783131], 'milligram / liter')>

Response:
def Tracer_AD_Pe(t_seconds, t_bar, C_bar, Pe):
    """Used by Solver_AD_Pe. All inputs and outputs are unitless. This is the
    model function, f(x, ...). It takes the independent variable as the
    first argument and the parameters to fit as separate remaining arguments.

    :param t_seconds: List of times
    :type t_seconds: float list
    :param t_bar: Average time spent in the reactor
    :type t_bar: float
    :param C_bar: Average concentration ((mass of tracer)/(volume of the reactor))
    :type C_bar: float
    :param Pe: The Peclet number for the reactor.
    :type Pe: float

    :return: The model concentration as a function of time
    :rtype: float list

    :Examples:

    >>> from aguaclara.research.environmental_processes_analysis import Tracer_AD_Pe
    >>> from aguaclara.core.units import unit_registry as u
    >>> Tracer_AD_Pe([1, 2, 3, 4, 5]*u.s, 5*u.s, 10*u.mg/u.L, 5)
    <Quantity([0.25833732 3.23793989 5.8349833  6.62508831 6.30783131], 'milligram / liter')>

    """
    return C_bar*E_Advective_Dispersion(t_seconds/t_bar, Pe)


Instruction:
How would you implement a function in Python 3 that
uses non - linear least squares to fit the functionTracer_AD_Pe to get a solution for a given set of time spent in one CMFR with units theta_guess and C_bar_guess.

Response:
def Solver_AD_Pe(t_data, C_data, theta_guess, C_bar_guess):
    """Use non-linear least squares to fit the function
    Tracer_AD_Pe(t_seconds, t_bar, C_bar, Pe) to reactor data.

    :param t_data: Array of times with units
    :type t_data: float list
    :param C_data: Array of tracer concentration data with units
    :type C_data: float list
    :param theta_guess: Estimate of time spent in one CMFR with units.
    :type theta_guess: float
    :param C_bar_guess: Estimate of average concentration with units ((mass of tracer)/(volume of one CMFR))
    :type C_bar_guess: float

    :return: tuple of

        * **theta** (*float*)- Residence time in seconds
        * **C_bar** (*float*) - Average concentration with same units as C_bar_guess
        * **Pe** (*float*) - Peclet number that best fits the data
    """
    #remove time=0 data to eliminate divide by zero error
    t_data = t_data[1:-1]
    C_data = C_data[1:-1]
    C_unitless = C_data.magnitude
    C_units = str(C_bar_guess.units)
    t_seconds = (t_data.to(u.s)).magnitude
    # assume that a guess of 1 reactor in series is close enough to get a solution
    p0 = [theta_guess.to(u.s).magnitude, C_bar_guess.magnitude,5]
    popt, pcov = curve_fit(Tracer_AD_Pe, t_seconds, C_unitless, p0, bounds=(0.01,np.inf))
    Solver_theta = popt[0]*u.s
    Solver_C_bar = popt[1]*u(C_units)
    Solver_Pe = popt[2]
    Reactor_results = collections.namedtuple('Reactor_results', 'theta C_bar Pe')
    AD = Reactor_results(theta=Solver_theta, C_bar=Solver_C_bar, Pe=Solver_Pe)
    return AD


Instruction:
Can you create a Python 3 function that
sets the number of significant figures used to print Pint Pandas and NumPy quantities.

Response:
def set_sig_figs(n=4):
    """Set the number of significant figures used to print Pint, Pandas, and
    NumPy quantities.

    Args:
        n (int): Number of significant figures to display.
    """
    u.default_format = '.' + str(n) + 'g'
    pd.options.display.float_format = ('{:,.' + str(n) + '}').format


Instruction:
Implement a function in Python 3 to
extract columns of data from a ProCoDA datalog based on date and time.

Response:
def get_data_by_time(path, columns, dates, start_time='00:00', end_time='23:59'):
    """Extract columns of data from a ProCoDA datalog based on date(s) and time(s)

    Note: Column 0 is time. The first data column is column 1.

    :param path: The path to the folder containing the ProCoDA data file(s)
    :type path: string
    :param columns: A single index of a column OR a list of indices of columns of data to extract.
    :type columns: int or int list
    :param dates: A single date or list of dates for which data was recorded, formatted "M-D-YYYY"
    :type dates: string or string list
    :param start_time: Starting time of data to extract, formatted 'HH:MM' (24-hour time)
    :type start_time: string, optional
    :param end_time: Ending time of data to extract, formatted 'HH:MM' (24-hour time)
    :type end_time: string, optional

    :return: a list containing the single column of data to extract, OR a list of lists containing the columns to extract, in order of the indices given in the columns variable
    :rtype: list or list list

    :Examples:

    .. code-block:: python

        data = get_data_by_time(path='/Users/.../ProCoDA Data/', columns=4, dates=['6-14-2018', '6-15-2018'], start_time='12:20', end_time='10:50')
        data = get_data_by_time(path='/Users/.../ProCoDA Data/', columns=[0,4], dates='6-14-2018', start_time='12:20', end_time='23:59')
        data = get_data_by_time(path='/Users/.../ProCoDA Data/', columns=[0,3,4], dates='6-14-2018')
    """
    data = data_from_dates(path, dates)

    first_time_column = pd.to_numeric(data[0].iloc[:, 0])
    start = max(day_fraction(start_time), first_time_column[0])
    start_idx = time_column_index(start, first_time_column)
    end_idx = time_column_index(day_fraction(end_time),
        pd.to_numeric(data[-1].iloc[:, 0])) + 1

    if isinstance(columns, int):
        return column_start_to_end(data, columns, start_idx, end_idx)
    else:
        result = []
        for c in columns:
            result.append(column_start_to_end(data, c, start_idx, end_idx))
    return result


Instruction:
Create a Python 3 function to
omit notes from a DataFrame object where notes are identified as rows with non - numerical entries in the first column.

Response:
def remove_notes(data):
    """Omit notes from a DataFrame object, where notes are identified as rows with non-numerical entries in the first column.

    :param data: DataFrame object to remove notes from
    :type data: Pandas.DataFrame

    :return: DataFrame object with no notes
    :rtype: Pandas.DataFrame
    """
    has_text = data.iloc[:, 0].astype(str).str.contains('(?!e-)[a-zA-Z]')
    text_rows = list(has_text.index[has_text])
    return data.drop(text_rows)


Instruction:
Write a Python 3 script to
convert a 24 - hour time to a fraction of a day.

Response:
def day_fraction(time):
    """Convert a 24-hour time to a fraction of a day.

    For example, midnight corresponds to 0.0, and noon to 0.5.

    :param time: Time in the form of 'HH:MM' (24-hour time)
    :type time: string

    :return: A day fraction
    :rtype: float

    :Examples:

    .. code-block:: python

        day_fraction("18:30")
    """
    hour = int(time.split(":")[0])
    minute = int(time.split(":")[1])
    return hour/24 + minute/1440


Instruction:
Can you generate a brief explanation for the following Python 3 code
def time_column_index(time, time_column):
    interval = time_column[1]-time_column[0]
    return int(round((time - time_column[0])/interval + .5))

Response:
Return the index of the lowest time in the column that is greater
    than or equal to the given time.


Instruction:
Write a Python 3 function for
returning a list DataFrames representing the ProCoDA datalogs stored in the given path and recorded on the given dates.

Response:
def data_from_dates(path, dates):
    """Return list DataFrames representing the ProCoDA datalogs stored in
    the given path and recorded on the given dates.

    :param path: The path to the folder containing the ProCoDA data file(s)
    :type path: string
    :param dates: A single date or list of dates for which data was recorded, formatted "M-D-YYYY"
    :type dates: string or string list

    :return: a list DataFrame objects representing the ProCoDA datalogs corresponding with the given dates
    :rtype: pandas.DataFrame list
    """
    if path[-1] != os.path.sep:
        path += os.path.sep

    if not isinstance(dates, list):
        dates = [dates]

    data = []
    for d in dates:
        filepath = path + 'datalog ' + d + '.xls'
        data.append(remove_notes(pd.read_csv(filepath, delimiter='\t')))

    return data


Instruction:
Can you write a function in Python 3 where it
returns a list of numeric data entries in the given column from the starting index to the ending index.

Response:
def column_start_to_end(data, column, start_idx, end_idx):
    """Return a list of numeric data entries in the given column from the starting
    index to the ending index. This can list can be compiled over one or more
    DataFrames.

    :param data: a list of DataFrames to extract data in one column from
    :type data: Pandas.DataFrame list
    :param column: a column index
    :type column: int
    :param start_idx: the index of the starting row
    :type start_idx: int
    :param start_idx: the index of the ending row
    :type start_idx: int

    :return: a list of data from the given column
    :rtype: float list
    """
    if len(data) == 1:
        result = list(pd.to_numeric(data[0].iloc[start_idx:end_idx, column]))
    else:
        result = list(pd.to_numeric(data[0].iloc[start_idx:, column]))
        for i in range(1, len(data)-1):
            data[i].iloc[0, 0] = 0
            result += list(pd.to_numeric(data[i].iloc[:, column]) +
                      (i if column == 0 else 0))
        data[-1].iloc[0, 0] = 0
        result += list(pd.to_numeric(data[-1].iloc[:end_idx, column]) +
                  (len(data)-1 if column == 0 else 0))

    return result


Instruction:
Implement a function in Python 3 to
read a ProCoDA file and extracts the time and data column for each iteration of the given state.

Response:
def get_data_by_state(path, dates, state, column):
    """Reads a ProCoDA file and extracts the time and data column for each
    iteration ofthe given state.

    Note: column 0 is time, the first data column is column 1.

    :param path: The path to the folder containing the ProCoDA data file(s), defaults to the current directory
    :type path: string
    :param dates: A single date or list of dates for which data was recorded, formatted "M-D-YYYY"
    :type dates: string or string list
    :param state: The state ID number for which data should be plotted
    :type state: int
    :param column: The integer index of the column that you want to extract OR the header of the column that you want to extract
    :type column: int or string

    :return: A list of lists of the time and data columns extracted for each iteration of the state. For example, if "data" is the output, data[i][:,0] gives the time column and data[i][:,1] gives the data column for the ith iteration of the given state and column. data[i][0] would give the first [time, data] pair.
    :type: list of lists of lists

    :Examples:

    .. code-block:: python

        data = get_data_by_state(path='/Users/.../ProCoDA Data/', dates=["6-19-2013", "6-20-2013"], state=1, column=28)
    """
    data_agg = []
    day = 0
    first_day = True
    overnight = False
    extension = ".xls"
    if path[-1] != '/':
        path += '/'

    if not isinstance(dates, list):
        dates = [dates]

    for d in dates:
        state_file = path + "statelog " + d + extension
        data_file = path + "datalog " + d + extension

        states = pd.read_csv(state_file, delimiter='\t')
        data = pd.read_csv(data_file, delimiter='\t')

        states = np.array(states)
        data = np.array(data)

        # get the start and end times for the state
        state_start_idx = states[:, 1] == state
        state_start = states[state_start_idx, 0]
        state_end_idx = np.append([False], state_start_idx[0:-1])
        state_end = states[state_end_idx, 0]

        if overnight:
            state_start = np.insert(state_start, 0, 0)
            state_end = np.insert(state_end, 0, states[0, 0])

        if state_start_idx[-1]:
            np.append(state_end, data[0, -1])

        # get the corresponding indices in the data array
        data_start = []
        data_end = []
        for i in range(np.size(state_start)):
            add_start = True
            for j in range(np.size(data[:, 0])):
                if (data[j, 0] > state_start[i]) and add_start:
                    data_start.append(j)
                    add_start = False
                if data[j, 0] > state_end[i]:
                    data_end.append(j-1)
                    break

        if first_day:
            start_time = data[0, 0]

        # extract data at those times
        for i in range(np.size(data_start)):
            t = data[data_start[i]:data_end[i], 0] + day - start_time
            if isinstance(column, int):
                c = data[data_start[i]:data_end[i], column]
            else:
                c = data[column][data_start[i]:data_end[i]]
            if overnight and i == 0:
                data_agg = np.insert(data_agg[-1], np.size(data_agg[-1][:, 0]),
                                     np.vstack((t, c)).T)
            else:
                data_agg.append(np.vstack((t, c)).T)

        day += 1
        if first_day:
            first_day = False
        if state_start_idx[-1]:
            overnight = True

    return data_agg


Instruction:
Given the following Python 3 function, write the documentation
def column_of_time(path, start, end=-1):
    df = pd.read_csv(path, delimiter='\t')
    start_time = pd.to_numeric(df.iloc[start, 0])*u.day
    day_times = pd.to_numeric(df.iloc[start:end, 0])
    time_data = np.subtract((np.array(day_times)*u.day), start_time)
    return time_data

Response: This function extracts the column of times from a ProCoDA data file.


Instruction:
How would you explain what the following Python 3 function does
def read_state_with_metafile(func, state, column, path, metaids=[],
                             extension=".xls", units=""):
    """Takes in a ProCoDA meta file and performs a function for all data of a
    certain state in each of the experiments (denoted by file paths in then
    metafile)

    Note: Column 0 is time. The first data column is column 1.

    :param func: A function that will be applied to data from each instance of the state
    :type func: function
    :param state: The state ID number for which data should be extracted
    :type state: int
    :param column: Index of the column that you want to extract OR header of the column that you want to extract
    :type column: int or string
    :param path: The file path of the ProCoDA data file (must be tab-delimited)
    :type path: string
    :param metaids: a list of the experiment IDs you'd like to analyze from the metafile
    :type metaids: string list, optional
    :param extension: The file extension of the tab delimited file. Defaults to ".xls" if no argument is passed in
    :type extension: string, optional
    :param units: The units you want to apply to the data, e.g. 'mg/L'. Defaults to "" (dimensionless)
    :type units: string, optional

    :return: ids (string list) - The list of experiment ids given in the metafile
    :return: outputs (list) - The outputs of the given function for each experiment

    :Examples:

    .. code-block:: python

        def avg_with_units(lst):
            num = np.size(lst)
            acc = 0
            for i in lst:
                acc = i + acc

            return acc / num

        path = "../tests/data/Test Meta File.txt"
        ids, answer = read_state_with_metafile(avg_with_units, 1, 28, path, [], ".xls", "mg/L")
    """
    outputs = []

    metafile = pd.read_csv(path, delimiter='\t', header=None)
    metafile = np.array(metafile)

    ids = metafile[1:, 0]

    if not isinstance(ids[0], str):
        ids = list(map(str, ids))

    if metaids:
        paths = []
        for i in range(len(ids)):
            if ids[i] in metaids:
                paths.append(metafile[i, 4])
    else:
        paths = metafile[1:, 4]

    basepath = os.path.join(os.path.split(path)[0], metafile[0, 4])

    # use a loop to evaluate each experiment in the metafile
    for i in range(len(paths)):
        # get the range of dates for experiment i
        day1 = metafile[i+1, 1]

        # modify the metafile date so that it works with datetime format
        if not (day1[2] == "-" or day1[2] == "/"):
            day1 = "0" + day1
        if not (day1[5] == "-" or day1[5] == "/"):
            day1 = day1[:3] + "0" + day1[3:]

        if day1[2] == "-":
            dt = datetime.strptime(day1, "%m-%d-%Y")
        else:
            dt = datetime.strptime(day1, "%m/%d/%y")
        duration = metafile[i+1, 3]

        if not isinstance(duration, int):
            duration = int(duration)

        date_list = []
        for j in range(duration):
            curr_day = dt.strftime("%m-%d-%Y")
            if curr_day[3] == "0":
                curr_day = curr_day[:3] + curr_day[4:]
            if curr_day[0] == "0":
                curr_day = curr_day[1:]

            date_list.append(curr_day)

            dt = dt + timedelta(days=1)

        path = str(Path(os.path.join(basepath, paths[i]))) + os.sep
        _, data = read_state(date_list, state, column, units, path, extension)

        outputs.append(func(data))

    return ids, outputs

Response: Takes in a ProCoDA meta file and performs a function for all data in each of the experiments and returns the state ID and the outputs of the function.


Instruction:
Can you tell what is the following Python 3 function doing
def write_calculations_to_csv(funcs, states, columns, path, headers, out_name,
                              metaids=[], extension=".xls"):
    """Writes each output of the given functions on the given states and data
    columns to a new column in the specified output file.

    Note: Column 0 is time. The first data column is column 1.

    :param funcs: A function or list of functions which will be applied in order to the data. If only one function is given it is applied to all the states/columns
    :type funcs: function or function list
    :param states: The state ID numbers for which data should be extracted. List should be in order of calculation or if only one state is given then it will be used for all the calculations
    :type states: string or string list
    :param columns: The index of a column, the header of a column, a list of indexes, OR a list of headers of the column(s) that you want to apply calculations to
    :type columns: int, string, int list, or string list
    :param path: Path to your ProCoDA metafile (must be tab-delimited)
    :type path: string
    :param headers: List of the desired header for each calculation, in order
    :type headers: string list
    :param out_name: Desired name for the output file. Can include a relative path
    :type out_name: string
    :param metaids: A list of the experiment IDs you'd like to analyze from the metafile
    :type metaids: string list, optional
    :param extension: The file extension of the tab delimited file. Defaults to ".xls" if no argument is passed in
    :type extension: string, optional

    :requires: funcs, states, columns, and headers are all of the same length if they are lists. Some being lists and some single values are okay.

    :return: out_name.csv (CVS file) - A CSV file with the each column being a new calcuation and each row being a new experiment on which the calcuations were performed
    :return: output (Pandas.DataFrame)- Pandas DataFrame holding the same data that was written to the output file
    """
    if not isinstance(funcs, list):
        funcs = [funcs] * len(headers)

    if not isinstance(states, list):
        states = [states] * len(headers)

    if not isinstance(columns, list):
        columns = [columns] * len(headers)

    data_agg = []
    for i in range(len(headers)):
        ids, data = read_state_with_metafile(funcs[i], states[i], columns[i],
                                             path, metaids, extension)
        data_agg = np.append(data_agg, [data])

    output = pd.DataFrame(data=np.vstack((ids, data_agg)).T,
                          columns=["ID"]+headers)
    output.to_csv(out_name, sep='\t')

    return output

Response: Writes each output of the given functions on the given states and data columns to a new column in the specified output file.