Instruction:
Can you write a function in Python 3 where it
returns the capacity for the run.

Response:
def get_cap(self, cycle=None, dataset_number=None,
                method="back-and-forth",
                shift=0.0,
                categorical_column=False,
                label_cycle_number=False,
                split=False,
                interpolated=False,
                dx=0.1,
                number_of_points=None,
                dynamic=False,
                ):
        """Gets the capacity for the run.
        For cycle=None: not implemented yet, cycle set to 1.

        Args:
            cycle (int): cycle number.
            method (string): how the curves are given
                "back-and-forth" - standard back and forth; discharge
                    (or charge) reversed from where charge (or discharge) ends.
                "forth" - discharge (or charge) continues along x-axis.
                "forth-and-forth" - discharge (or charge) also starts at 0
                    (or shift if not shift=0.0)
            shift: start-value for charge (or discharge) (typically used when
                plotting shifted-capacity).
            categorical_column: add a categorical column showing if it is
                charge or discharge.
            dataset_number (int): test number (default first)
                (usually not used).
            label_cycle_number (bool): add column for cycle number
                (tidy format).
            split (bool): return a list of c and v instead of the defualt
                that is to return them combined in a DataFrame. This is only
                possible for some specific combinations of options (neither
                categorical_colum=True or label_cycle_number=True are
                allowed).
            interpolated (bool): set to True if you would like to get
                interpolated data (typically if you want to save disk space
                or memory). Defaults to False.
            dx (float): the step used when interpolating.
            number_of_points (int): number of points to use (over-rides dx)
                for interpolation (i.e. the length of the interpolated data).
            dynamic: for dynamic retrieving data from cellpy-file.
                [NOT IMPLEMNETED YET]

        Returns:
            pandas.DataFrame ((cycle) voltage, capacity, (direction (-1, 1)))
                unless split is explicitly set to True. Then it returns a tuple
                with capacity (mAh/g) and voltage.
        """

        dataset_number = self._validate_dataset_number(dataset_number)
        if dataset_number is None:
            self._report_empty_dataset()
            return

        # if cycle is not given, then this function should
        # iterate through cycles
        if cycle is None:
            cycle = self.get_cycle_numbers()

        if not isinstance(cycle, (collections.Iterable,)):
            cycle = [cycle]

        if split and not (categorical_column or label_cycle_number):
            return_dataframe = False
        else:
            return_dataframe = True

        method = method.lower()
        if method not in ["back-and-forth", "forth", "forth-and-forth"]:
            warnings.warn(f"method '{method}' is not a valid option "
                          f"- setting to 'back-and-forth'")
            method = "back-and-forth"

        capacity = None
        voltage = None
        cycle_df = pd.DataFrame()

        initial = True
        for current_cycle in cycle:
            # self.logger.debug(f"processing cycle {current_cycle}")
            try:
                cc, cv = self.get_ccap(current_cycle, dataset_number)
                dc, dv = self.get_dcap(current_cycle, dataset_number)
            except NullData as e:
                self.logger.debug(e)
                self.logger.debug("breaking out of loop")
                break

            if cc.empty:
                self.logger.debug("get_ccap returns empty cc Series")

            if dc.empty:
                self.logger.debug("get_ccap returns empty dc Series")

            if initial:
                # self.logger.debug("(initial cycle)")
                prev_end = shift
                initial = False

            if self._cycle_mode == "anode":
                _first_step_c = dc
                _first_step_v = dv
                _last_step_c = cc
                _last_step_v = cv
            else:
                _first_step_c = cc
                _first_step_v = cv
                _last_step_c = dc
                _last_step_v = dv

            if method == "back-and-forth":
                _last = np.amax(_first_step_c)
                # should change amax to last point
                _first = None
                _new_first = None
                if _last_step_c is not None:
                    _last_step_c = _last - _last_step_c + prev_end
                else:
                    self.logger.debug("no last charge step found")
                if _first_step_c is not None:
                    _first = _first_step_c.iat[0]
                    _first_step_c += prev_end
                    _new_first = _first_step_c.iat[0]
                else:
                    self.logger.debug("probably empty (_first_step_c is None)")
                # self.logger.debug(f"current shifts used: prev_end = {prev_end}")
                # self.logger.debug(f"shifting start from {_first} to "
                #                   f"{_new_first}")

                prev_end = np.amin(_last_step_c)
                # should change amin to last point

            elif method == "forth":
                _last = np.amax(_first_step_c)
                # should change amax to last point
                if _last_step_c is not None:
                    _last_step_c += _last + prev_end
                else:
                    self.logger.debug("no last charge step found")
                if _first_step_c is not None:
                    _first_step_c += prev_end
                else:
                    self.logger.debug("no first charge step found")

                prev_end = np.amax(_last_step_c)
                # should change amin to last point

            elif method == "forth-and-forth":
                if _last_step_c is not None:
                    _last_step_c += shift
                else:
                    self.logger.debug("no last charge step found")
                if _first_step_c is not None:
                    _first_step_c += shift
                else:
                    self.logger.debug("no first charge step found")

            if return_dataframe:

                try:
                    _first_df = pd.DataFrame(
                            {
                                "voltage": _first_step_v.values,
                                "capacity": _first_step_c.values
                             }
                    )
                    if interpolated:
                        _first_df = _interpolate_df_col(
                            _first_df, y="capacity", x="voltage",
                            dx=dx, number_of_points=number_of_points,
                            direction=-1
                        )
                    if categorical_column:
                        _first_df["direction"] = -1

                    _last_df = pd.DataFrame(
                        {
                            "voltage": _last_step_v.values,
                            "capacity": _last_step_c.values
                        }
                    )
                    if interpolated:
                        _last_df = _interpolate_df_col(
                            _last_df, y="capacity", x="voltage",
                            dx=dx, number_of_points=number_of_points,
                            direction=1
                        )
                    if categorical_column:
                        _last_df["direction"] = 1

                except AttributeError:
                    self.logger.info(f"could not extract cycle {current_cycle}")
                else:
                    c = pd.concat([_first_df, _last_df], axis=0)
                    if label_cycle_number:
                        c.insert(0, "cycle", current_cycle)
                        # c["cycle"] = current_cycle
                        # c = c[["cycle", "voltage", "capacity", "direction"]]
                    if cycle_df.empty:
                        cycle_df = c
                    else:
                        cycle_df = pd.concat([cycle_df, c], axis=0)

            else:
                logging.warning("returning non-dataframe")
                c = pd.concat([_first_step_c, _last_step_c], axis=0)
                v = pd.concat([_first_step_v, _last_step_v], axis=0)

                capacity = pd.concat([capacity, c], axis=0)
                voltage = pd.concat([voltage, v], axis=0)

        if return_dataframe:
            return cycle_df
        else:
            return capacity, voltage


Instruction:
Here you have a function in Python 3, explain what it does
def get_ocv(self, cycles=None, direction="up",
                remove_first=False,
                interpolated=False,
                dx=None,
                number_of_points=None):

        """get the open curcuit voltage relaxation curves.

        Args:
            cycles (list of ints or None): the cycles to extract from
                (selects all if not given).
            direction ("up", "down", or "both"): extract only relaxations that
                is performed during discharge for "up" (because then the
                voltage relaxes upwards) etc.
            remove_first: remove the first relaxation curve (typically,
                the first curve is from the initial rest period between
                assembling the cell to the actual testing/cycling starts)
            interpolated (bool): set to True if you want the data to be
                interpolated (e.g. for creating smaller files)
            dx (float): the step used when interpolating.
            number_of_points (int): number of points to use (over-rides dx)
                for interpolation (i.e. the length of the interpolated data).

        Returns:
            A pandas.DataFrame with cycle-number, step-number, step-time, and
                voltage columns.
        """

        if cycles is None:
            cycles = self.get_cycle_numbers()
        else:
            if not isinstance(cycles, (list, tuple)):
                cycles = [cycles, ]
            else:
                remove_first = False

        ocv_rlx_id = "ocvrlx"
        if direction == "up":
            ocv_rlx_id += "_up"
        elif direction == "down":
            ocv_rlx_id += "_down"

        step_table = self.dataset.step_table
        dfdata = self.dataset.dfdata

        ocv_steps = step_table.loc[
                    step_table["cycle"].isin(cycles), :
                    ]

        ocv_steps = ocv_steps.loc[
                    ocv_steps.type.str.startswith(ocv_rlx_id), :
                    ]

        if remove_first:
            ocv_steps = ocv_steps.iloc[1:, :]

        step_time_label = self.headers_normal.step_time_txt
        voltage_label = self.headers_normal.voltage_txt
        cycle_label = self.headers_normal.cycle_index_txt
        step_label = self.headers_normal.step_index_txt

        selected_df = dfdata.where(
            dfdata[cycle_label].isin(ocv_steps.cycle) &
            dfdata[step_label].isin(ocv_steps.step)
        ).dropna()

        selected_df = selected_df.loc[
            :, [cycle_label, step_label, step_time_label, voltage_label]
        ]

        if interpolated:
            if dx is None and number_of_points is None:
                dx = prms.Reader.time_interpolation_step
            new_dfs = list()
            groupby_list = [cycle_label, step_label]

            for name, group in selected_df.groupby(groupby_list):
                new_group = _interpolate_df_col(
                    group,
                    x=step_time_label,
                    y=voltage_label,
                    dx=dx,
                    number_of_points=number_of_points,
                )

                for i, j in zip(groupby_list, name):
                    new_group[i] = j
                new_dfs.append(new_group)

            selected_df = pd.concat(new_dfs)

        return selected_df

Response: get the open curcuit voltage relaxation curves for a given set of cycles


Instruction:
Write a Python 3 function that can
get the OCV data for a given cycle.

Response:
def get_ocv_old(self, cycle_number=None, ocv_type='ocv', dataset_number=None):
        """Find ocv data in DataSet (voltage vs time).

        Args:
            cycle_number (int): find for all cycles if None.
            ocv_type ("ocv", "ocvrlx_up", "ocvrlx_down"):
                     ocv - get up and down (default)
                     ocvrlx_up - get up
                     ocvrlx_down - get down
            dataset_number (int): test number (default first)
                (usually not used).
        Returns:
                if cycle_number is not None
                    ocv or [ocv_up, ocv_down]
                    ocv (and ocv_up and ocv_down) are list
                    containg [time,voltage] (that are Series)

                if cycle_number is None
                    [ocv1,ocv2,...ocvN,...] N = cycle
                    ocvN = pandas DataFrame containing the columns
                    cycle inded, step time, step index, data point, datetime,
                        voltage
                    (TODO: check if copy or reference of dfdata is returned)
        """
        # function for getting ocv curves
        dataset_number = self._validate_dataset_number(dataset_number)
        if dataset_number is None:
            self._report_empty_dataset()
            return
        if ocv_type in ['ocvrlx_up', 'ocvrlx_down']:
            ocv = self._get_ocv(dataset_number=None,
                                ocv_type=ocv_type,
                                select_last=True,
                                select_columns=True,
                                cycle_number=cycle_number,
                                )
            return ocv
        else:
            ocv_up = self._get_ocv(dataset_number=None,
                                   ocv_type='ocvrlx_up',
                                   select_last=True,
                                   select_columns=True,
                                   cycle_number=cycle_number,
                                   )
            ocv_down = self._get_ocv(dataset_number=None,
                                     ocv_type='ocvrlx_down',
                                     select_last=True,
                                     select_columns=True,
                                     cycle_number=cycle_number,
                                     )
            return ocv_up, ocv_down


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_number_of_cycles(self, dataset_number=None, steptable=None):
        if steptable is None:
            dataset_number = self._validate_dataset_number(dataset_number)
            if dataset_number is None:
                self._report_empty_dataset()
                return
            d = self.datasets[dataset_number].dfdata
            no_cycles = np.amax(d[self.headers_normal.cycle_index_txt])
        else:
            no_cycles = np.amax(steptable[self.headers_step_table.cycle])
        return no_cycles

Response: Get the number of cycles in the test.


Instruction:
Write a Python 3 script for
getting a list containing all the cycle numbers in the test.

Response:
def get_cycle_numbers(self, dataset_number=None, steptable=None):
        """Get a list containing all the cycle numbers in the test."""
        if steptable is None:
            dataset_number = self._validate_dataset_number(dataset_number)
            if dataset_number is None:
                self._report_empty_dataset()
                return
            d = self.datasets[dataset_number].dfdata
            cycles = np.unique(d[self.headers_normal.cycle_index_txt])
        else:
            cycles = np.unique(steptable[self.headers_step_table.cycle])
        return cycles


Instruction:
Make a summary of the following Python 3 code
def get_converter_to_specific(self, dataset=None, mass=None,
                                  to_unit=None, from_unit=None):
        """get the convertion values

        Args:
            dataset: DataSet object
            mass: mass of electrode (for example active material in mg)
            to_unit: (float) unit of input, f.ex. if unit of charge
              is mAh and unit of mass is g, then to_unit for charge/mass
              will be 0.001 / 1.0 = 0.001
            from_unit: float) unit of output, f.ex. if unit of charge
              is mAh and unit of mass is g, then to_unit for charge/mass
              will be 1.0 / 0.001 = 1000.0

        Returns:
            multiplier (float) from_unit/to_unit * mass

        """

        if not dataset:
            dataset_number = self._validate_dataset_number(None)
            if dataset_number is None:
                self._report_empty_dataset()
                return
            dataset = self.datasets[dataset_number]

        if not mass:
            mass = dataset.mass

        if not to_unit:
            to_unit_cap = self.cellpy_units["charge"]
            to_unit_mass = self.cellpy_units["specific"]
            to_unit = to_unit_cap / to_unit_mass
        if not from_unit:
            from_unit_cap = self.raw_units["charge"]
            from_unit_mass = self.raw_units["mass"]
            from_unit = from_unit_cap / from_unit_mass

        return from_unit / to_unit / mass

Response: get the conversion values for the specific electrode


Instruction:
Can you generate a brief explanation for the following Python 3 code
def set_mass(self, masses, dataset_number=None, validated=None):
        self._set_run_attribute("mass", masses, dataset_number=dataset_number,
                                validated=validated)

Response: Sets the mass for the test.


Instruction:
Explain what the following Python 3 code does
def set_tot_mass(self, masses, dataset_number=None, validated=None):
        self._set_run_attribute("tot_mass", masses,
                                dataset_number=dataset_number,
                                validated=validated)

Response: Sets the total mass for the test.


Instruction:
Can you create a Python 3 function that
sets the nominal cap for the test.

Response:
def set_nom_cap(self, nom_caps, dataset_number=None, validated=None):
        """Sets the mass (masses) for the test (datasets).
        """
        self._set_run_attribute("nom_cap", nom_caps,
                                dataset_number=dataset_number,
                                validated=validated)


Instruction:
Can you tell what is the following Python 3 function doing
def set_col_first(df, col_names):

        column_headings = df.columns
        column_headings = column_headings.tolist()
        try:
            for col_name in col_names:
                i = column_headings.index(col_name)
                column_headings.pop(column_headings.index(col_name))
                column_headings.insert(0, col_name)

        finally:
            df = df.reindex(columns=column_headings)
            return df

Response: set selected columns first in a pandas. DataFrame.


Instruction:
Explain what the following Python 3 code does
def get_summary(self, dataset_number=None, use_dfsummary_made=False):
        dataset_number = self._validate_dataset_number(dataset_number)
        if dataset_number is None:
            self._report_empty_dataset()
            return None

        test = self.get_dataset(dataset_number)

        # This is a bit convoluted; in the old days, we used an attribute
        # called dfsummary_made,
        # that was set to True when the summary was made successfully.
        # It is most likely never
        # used anymore. And will most probably be deleted.
        if use_dfsummary_made:
            dfsummary_made = test.dfsummary_made
        else:
            dfsummary_made = True

        if not dfsummary_made:
            warnings.warn("Summary is not made yet")
            return None
        else:
            self.logger.info("returning datasets[test_no].dfsummary")
            return test.dfsummary

Response: Retrieve summary returned as a pandas DataFrame.


Instruction:
Given the following Python 3 function, write the documentation
def make_summary(self, find_ocv=False, find_ir=False,
                     find_end_voltage=False,
                     use_cellpy_stat_file=None, all_tests=True,
                     dataset_number=0, ensure_step_table=True,
                     convert_date=False):
        """Convenience function that makes a summary of the cycling data."""

        # first - check if we need some "instrument-specific" prms
        if self.tester == "arbin":
            convert_date = True

        if ensure_step_table is None:
            ensure_step_table = self.ensure_step_table
        # Cycle_Index	Test_Time(s)	Test_Time(h)	Date_Time	Current(A)
        # Current(mA)	Voltage(V)	Charge_Capacity(Ah)	Discharge_Capacity(Ah)
        # Charge_Energy(Wh)	Discharge_Energy(Wh)	Internal_Resistance(Ohm)
        # AC_Impedance(Ohm)	ACI_Phase_Angle(Deg)	Charge_Time(s)
        # DisCharge_Time(s)	Vmax_On_Cycle(V)	Coulombic_Efficiency
        if use_cellpy_stat_file is None:
            use_cellpy_stat_file = prms.Reader.use_cellpy_stat_file
            self.logger.debug("using use_cellpy_stat_file from prms")
            self.logger.debug(f"use_cellpy_stat_file: {use_cellpy_stat_file}")

        if all_tests is True:
            for j in range(len(self.datasets)):
                txt = "creating summary for file "
                test = self.datasets[j]
                if not self._is_not_empty_dataset(test):
                    self.logger.info("empty test %i" % j)
                    return
                if isinstance(test.loaded_from, (list, tuple)):
                    for f in test.loaded_from:
                        txt += f
                        txt += "\n"
                else:
                    txt += str(test.loaded_from)

                if not test.mass_given:
                    txt += " mass for test %i is not given" % j
                    txt += " setting it to %f mg" % test.mass
                self.logger.debug(txt)

                self._make_summary(j,
                                   find_ocv=find_ocv,
                                   find_ir=find_ir,
                                   find_end_voltage=find_end_voltage,
                                   use_cellpy_stat_file=use_cellpy_stat_file,
                                   ensure_step_table=ensure_step_table,
                                   convert_date=convert_date,
                                   )
        else:
            self.logger.debug("creating summary for only one test")
            dataset_number = self._validate_dataset_number(dataset_number)
            if dataset_number is None:
                self._report_empty_dataset()
                return
            self._make_summary(dataset_number,
                               find_ocv=find_ocv,
                               find_ir=find_ir,
                               find_end_voltage=find_end_voltage,
                               use_cellpy_stat_file=use_cellpy_stat_file,
                               ensure_step_table=ensure_step_table,
                               convert_date=convert_date,
                               )
        return self

Response: Convenience function that makes a summary of the cycling data.


Instruction:
Create a Python 3 function for
generating a single HTML page from an epub file.

Response:
def single_html(epub_file_path, html_out=sys.stdout, mathjax_version=None,
                numchapters=None, includes=None):
    """Generate complete book HTML."""
    epub = cnxepub.EPUB.from_file(epub_file_path)
    if len(epub) != 1:
        raise Exception('Expecting an epub with one book')

    package = epub[0]
    binder = cnxepub.adapt_package(package)
    partcount.update({}.fromkeys(parts, 0))
    partcount['book'] += 1

    html = cnxepub.SingleHTMLFormatter(binder, includes=includes)

    # Truncate binder to the first N chapters where N = numchapters.
    logger.debug('Full binder: {}'.format(cnxepub.model_to_tree(binder)))
    if numchapters is not None:
        apply_numchapters(html.get_node_type, binder, numchapters)
        logger.debug('Truncated Binder: {}'.format(
            cnxepub.model_to_tree(binder)))

    # Add mathjax to the page.
    if mathjax_version:
        etree.SubElement(
            html.head,
            'script',
            src=MATHJAX_URL.format(mathjax_version=mathjax_version))

    print(str(html), file=html_out)
    if hasattr(html_out, 'name'):
        # html_out is a file, close after writing
        html_out.close()


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _pack_prms():

    config_dict = {
        "Paths": prms.Paths.to_dict(),
        "FileNames": prms.FileNames.to_dict(),
        "Db": prms.Db.to_dict(),
        "DbCols": prms.DbCols.to_dict(),
        "DataSet": prms.DataSet.to_dict(),
        "Reader": prms.Reader.to_dict(),
        "Instruments": prms.Instruments.to_dict(),
        # "excel_db_cols": prms.excel_db_cols.to_dict(),
        # "excel_db_filename_cols": prms.excel_db_filename_cols.to_dict(),
        "Batch": prms.Batch.to_dict(),
    }
    return config_dict

Response: Pack the prms into a dictionary that can be used to save the log files.


Instruction:
How would you explain what the following Python 3 function does
def _read_prm_file(prm_filename):
    logger.debug("Reading config-file: %s" % prm_filename)
    try:
        with open(prm_filename, "r") as config_file:
            prm_dict = yaml.load(config_file)
    except yaml.YAMLError:
        raise ConfigFileNotRead
    else:
        _update_prms(prm_dict)

Response: read the prm file


Instruction:
How would you explain what the following Python 3 function does
def _get_prm_file(file_name=None, search_order=None):
    if file_name is not None:
        if os.path.isfile(file_name):
            return file_name
        else:
            logger.info("Could not find the prm-file")

    default_name = prms._prm_default_name
    prm_globtxt = prms._prm_globtxt

    script_dir = os.path.abspath(os.path.dirname(__file__))

    search_path = dict()
    search_path["curdir"] = os.path.abspath(os.path.dirname(sys.argv[0]))
    search_path["filedir"] = script_dir
    search_path["userdir"] = os.path.expanduser("~")

    if search_order is None:
        search_order = ["userdir", ]  # ["curdir","filedir", "userdir",]
    else:
        search_order = search_order

    # The default name for the prm file is at the moment in the script-dir,@
    # while default searching is in the userdir (yes, I know):
    prm_default = os.path.join(script_dir, default_name)

    # -searching-----------------------
    search_dict = OrderedDict()

    for key in search_order:
        search_dict[key] = [None, None]
        prm_directory = search_path[key]
        default_file = os.path.join(prm_directory, default_name)

        if os.path.isfile(default_file):
            # noinspection PyTypeChecker
            search_dict[key][0] = default_file

        prm_globtxt_full = os.path.join(prm_directory, prm_globtxt)

        user_files = glob.glob(prm_globtxt_full)

        for f in user_files:
            if os.path.basename(f) != os.path.basename(default_file):
                search_dict[key][1] = f
                break

    # -selecting----------------------
    prm_file = None
    for key, file_list in search_dict.items():
        if file_list[-1]:
            prm_file = file_list[-1]
            break
        else:
            if not prm_file:
                prm_file = file_list[0]

    if prm_file:
        prm_filename = prm_file
    else:
        prm_filename = prm_default

    return prm_filename

Response: returns the name of the prm file


Instruction:
Can you generate the documentation for the following Python 3 function
def info():
    print("convenience function for listing prms")
    print(type(prms))
    print(prms.__name__)
    print(f"prm file: {_get_prm_file()}")

    for key in prms.__dict__:
        if isinstance(prms.__dict__[key], box.Box):
            print()
            print(80 * "=")
            print(f"prms.{key}:")
            print(80 * "-")
            for subkey in prms.__dict__[key]:
                print(
                    f"prms.{key}.{subkey} = ",
                    f"{prms.__dict__[key][subkey]}"
                )
            print(80 * "=")

Response:
this function will show only the box - type
    attributes and their content in the cellpy. prms module


Instruction:
Can you tell what is the following Python 3 function doing
def _replace_tex_math(node, mml_url, mc_client=None, retry=0):

    math = node.attrib['data-math'] or node.text
    if math is None:
        return None

    eq = {}
    if mc_client:
        math_key = hashlib.md5(math.encode('utf-8')).hexdigest()
        eq = json.loads(mc_client.get(math_key) or '{}')

    if not eq:
        res = requests.post(mml_url, {'math': math.encode('utf-8'),
                                      'mathType': 'TeX',
                                      'mml': 'true'})
        if res:  # Non-error response from requests
            eq = res.json()
            if mc_client:
                mc_client.set(math_key, res.text)

    if 'components' in eq and len(eq['components']) > 0:
        for component in eq['components']:
            if component['format'] == 'mml':
                mml = etree.fromstring(component['source'])
        if node.tag.endswith('span'):
            mml.set('display', 'inline')
        elif node.tag.endswith('div'):
            mml.set('display', 'block')
        mml.tail = node.tail
        return mml
    else:
        logger.warning('Retrying math TeX conversion: '
                       '{}'.format(json.dumps(eq, indent=4)))
        retry += 1
        if retry < 2:
            return _replace_tex_math(node, mml_url, mc_client, retry)

    return None

Response: call mml - api to replace TeX math in body of node with mathml


Instruction:
Can you create a Python 3 function that
creates a callback function to replace an exercise by fetching from an external server.

Response:
def exercise_callback_factory(match, url_template,
                              mc_client=None, token=None, mml_url=None):
    """Create a callback function to replace an exercise by fetching from
    a server."""

    def _replace_exercises(elem):
        item_code = elem.get('href')[len(match):]
        url = url_template.format(itemCode=item_code)
        exercise = {}
        if mc_client:
            mc_key = item_code + (token or '')
            exercise = json.loads(mc_client.get(mc_key) or '{}')

        if not exercise:
            if token:
                headers = {'Authorization': 'Bearer {}'.format(token)}
                res = requests.get(url, headers=headers)
            else:
                res = requests.get(url)
            if res:
                # grab the json exercise, run it through Jinja2 template,
                # replace element w/ it
                exercise = res.json()
                if mc_client:
                    mc_client.set(mc_key, res.text)

        if exercise['total_count'] == 0:
            logger.warning('MISSING EXERCISE: {}'.format(url))

            XHTML = '{{{}}}'.format(HTML_DOCUMENT_NAMESPACES['xhtml'])
            missing = etree.Element(XHTML + 'div',
                                    {'class': 'missing-exercise'},
                                    nsmap=HTML_DOCUMENT_NAMESPACES)
            missing.text = 'MISSING EXERCISE: tag:{}'.format(item_code)
            nodes = [missing]
        else:
            html = EXERCISE_TEMPLATE.render(data=exercise)
            try:
                nodes = etree.fromstring('<div>{}</div>'.format(html))
            except etree.XMLSyntaxError:  # Probably HTML
                nodes = etree.HTML(html)[0]  # body node

            if mml_url:
                for node in nodes.xpath('//*[@data-math]'):
                    mathml = _replace_tex_math(node, mml_url, mc_client)
                    if mathml is not None:
                        mparent = node.getparent()
                        mparent.replace(node, mathml)
                    else:
                        mathtext = node.get('data-math') or node.text or ''
                        logger.warning('BAD TEX CONVERSION: "%s" URL: %s'
                                       % (mathtext.encode('utf-8'), url))

        parent = elem.getparent()
        if etree.QName(parent.tag).localname == 'p':
            elem = parent
            parent = elem.getparent()

        parent.remove(elem)  # Special case - assumes single wrapper elem
        for child in nodes:
            parent.append(child)

    xpath = '//xhtml:a[contains(@href, "{}")]'.format(match)
    return (xpath, _replace_exercises)


Instruction:
Given the following Python 3 function, write the documentation
def html_listify(tree, root_xl_element, extensions, list_type='ol'):
    for node in tree:
        li_elm = etree.SubElement(root_xl_element, 'li')
        if node['id'] not in extensions:  # no extension, no associated file
            span_elm = lxml.html.fragment_fromstring(
                node['title'], create_parent='span')
            li_elm.append(span_elm)
        else:
            a_elm = lxml.html.fragment_fromstring(
                node['title'], create_parent='a')
            a_elm.set('href', ''.join([node['id'], extensions[node['id']]]))
            li_elm.append(a_elm)
        if node['id'] is not None and node['id'] != 'subcol':
            li_elm.set('cnx-archive-uri', node['id'])
        if node['shortId'] is not None:
            li_elm.set('cnx-archive-shortid', node['shortId'])
        if 'contents' in node:
            elm = etree.SubElement(li_elm, list_type)
            html_listify(node['contents'], elm, extensions)

Response: Convert a node tree into an xhtml nested list - of - lists.


Instruction:
Explain what the following Python 3 code does
def _generate_ids(self, document, content):
        existing_ids = content.xpath('//*/@id')
        elements = [
            'p', 'dl', 'dt', 'dd', 'table', 'div', 'section', 'figure',
            'blockquote', 'q', 'code', 'pre', 'object', 'img', 'audio',
            'video',
            ]
        elements_xpath = '|'.join(['.//{}|.//xhtml:{}'.format(elem, elem)
                                  for elem in elements])

        data_types = [
            'equation', 'list', 'exercise', 'rule', 'example', 'note',
            'footnote-number', 'footnote-ref', 'problem', 'solution', 'media',
            'proof', 'statement', 'commentary'
            ]
        data_types_xpath = '|'.join(['.//*[@data-type="{}"]'.format(data_type)
                                     for data_type in data_types])

        xpath = '|'.join([elements_xpath, data_types_xpath])

        mapping = {}  # old id -> new id

        for node in content.xpath(xpath, namespaces=HTML_DOCUMENT_NAMESPACES):
            old_id = node.attrib.get('id')
            document_id = document.id.replace('_', '')
            if old_id:
                new_id = 'auto_{}_{}'.format(document_id, old_id)
            else:
                random_number = random.randint(0, 100000)
                new_id = 'auto_{}_{}'.format(document_id, random_number)
            while new_id in existing_ids:
                random_number = random.randint(0, 100000)
                new_id = 'auto_{}_{}'.format(document_id, random_number)
            node.attrib['id'] = new_id
            if old_id:
                mapping[old_id] = new_id
            existing_ids.append(new_id)

        for a in content.xpath('//a[@href]|//xhtml:a[@href]',
                               namespaces=HTML_DOCUMENT_NAMESPACES):
            href = a.attrib['href']
            if href.startswith('#') and href[1:] in mapping:
                a.attrib['href'] = '#{}'.format(mapping[href[1:]])

Response: Generate unique ids for html elements in page content so that it s possible to link to them.


Instruction:
Explain what the following Python 3 code does
def get_node_type(self, node, parent=None):
        if isinstance(node, CompositeDocument):
            return 'composite-page'
        elif isinstance(node, (Document, DocumentPointer)):
            return 'page'
        elif isinstance(node, Binder) and parent is None:
            return 'book'
        for child in node:
            if isinstance(child, TranslucentBinder):
                return 'unit'
        return 'chapter'

Response: Returns the type of node.


Instruction:
Implement a function in Python 3 to
pack the given directory into an epub file.

Response:
def pack_epub(directory, file):
    """Pack the given ``directory`` into an epub (i.e. zip) archive
    given as ``file``, which can be a file-path or file-like object.
    """
    with zipfile.ZipFile(file, 'w', zipfile.ZIP_DEFLATED) as zippy:
        base_path = os.path.abspath(directory)
        for root, dirs, filenames in os.walk(directory):
            # Strip the absolute path
            archive_path = os.path.relpath(root, base_path)
            for filename in filenames:
                filepath = os.path.join(root, filename)
                archival_filepath = os.path.join(archive_path, filename)
                zippy.write(filepath, archival_filepath)


Instruction:
How would you explain what the following Python 3 function does
def unpack_epub(file, directory):
    if zipfile.is_zipfile(file):
        # Extract the epub to the current working directory.
        with zipfile.ZipFile(file, 'r') as zf:
            zf.extractall(path=directory)

Response: Unpack the given file to the given directory.


Instruction:
How would you explain what the following Python 3 function does
def from_file(cls, file):
        root = None
        if zipfile.is_zipfile(file):
            unpack_dir = tempfile.mkdtemp('-epub')
            # Extract the epub to the current working directory.
            with zipfile.ZipFile(file, 'r') as zf:
                zf.extractall(path=unpack_dir)
            root = unpack_dir
        elif os.path.isdir(file):
            root = file
        else:
            raise TypeError("Can't decipher what should be done "
                            "with the given file.")

        # NOTE We ignore the mimetype file, as it's not extremely important
        #      to anything done here.

        # Build a blank epub object then parse the packages.
        container_xml_filepath = os.path.join(root,
                                              EPUB_CONTAINER_XML_RELATIVE_PATH)
        container_xml = etree.parse(container_xml_filepath)

        packages = []
        for pkg_filepath in container_xml.xpath(
                '//ns:rootfile/@full-path',
                namespaces=EPUB_CONTAINER_XML_NAMESPACES):
            filepath = os.path.join(root, pkg_filepath)
            packages.append(Package.from_file(filepath))
        return cls(packages=packages, root=root)

Response: Create an object from a file or a directory.


Instruction:
Create a Python 3 function to
export to file which is a file - like object.

Response:
def to_file(epub, file):
        """Export to ``file``, which is a *file* or *file-like object*."""
        directory = tempfile.mkdtemp('-epub')
        # Write out the contents to the filesystem.
        package_filenames = []
        for package in epub:
            opf_filepath = Package.to_file(package, directory)
            opf_filename = os.path.basename(opf_filepath)
            package_filenames.append(opf_filename)

        # Create the container.xml
        container_xml_filepath = os.path.join(directory,
                                              EPUB_CONTAINER_XML_RELATIVE_PATH)
        template = jinja2.Template(CONTAINER_XML_TEMPLATE,
                                   trim_blocks=True, lstrip_blocks=True)
        os.makedirs(os.path.dirname(container_xml_filepath))  # FIXME PY3
        with open(container_xml_filepath, 'w') as fb:
            xml = template.render(package_filenames=package_filenames)
            fb.write(xml)
        # Write the mimetype file.
        with open(os.path.join(directory, 'mimetype'), 'w') as fb:
            fb.write("application/epub+zip")

        # Pack everything up
        pack_epub(directory, file=file)


Instruction:
Implement a Python 3 function for
creating an object from a file - like object.

Response:
def from_file(cls, file):
        """Create the object from a *file* or *file-like object*."""
        opf_xml = etree.parse(file)
        # Check if ``file`` is file-like.
        if hasattr(file, 'read'):
            name = os.path.basename(file.name)
            root = os.path.abspath(os.path.dirname(file.name))
        else:  # ...a filepath
            name = os.path.basename(file)
            root = os.path.abspath(os.path.dirname(file))
        parser = OPFParser(opf_xml)

        # Roll through the item entries
        manifest = opf_xml.xpath('/opf:package/opf:manifest/opf:item',
                                 namespaces=EPUB_OPF_NAMESPACES)
        pkg_items = []
        for item in manifest:
            absolute_filepath = os.path.join(root, item.get('href'))
            properties = item.get('properties', '').split()
            is_navigation = 'nav' in properties
            media_type = item.get('media-type')
            pkg_items.append(Item.from_file(absolute_filepath,
                                            media_type=media_type,
                                            is_navigation=is_navigation,
                                            properties=properties))
        # Ignore spine ordering, because it is not important
        #   for our use cases.
        return cls(name, pkg_items, parser.metadata)


Instruction:
Implement a function in Python 3 to
write the package to the given directory.

Response:
def to_file(package, directory):
        """Write the package to the given ``directory``.
        Returns the OPF filename.
        """
        opf_filepath = os.path.join(directory, package.name)

        # Create the directory structure
        for name in ('contents', 'resources',):
            path = os.path.join(directory, name)
            if not os.path.exists(path):
                os.mkdir(path)

        # Write the items to the filesystem
        locations = {}  # Used when rendering
        for item in package:
            if item.media_type == 'application/xhtml+xml':
                base = os.path.join(directory, 'contents')
            else:
                base = os.path.join(directory, 'resources')
            filename = item.name
            filepath = os.path.join(base, filename)
            locations[item] = os.path.relpath(filepath, directory)
            with open(filepath, 'wb') as item_file:
                item_file.write(item.data.read())

        # Write the OPF
        template = jinja2.Template(OPF_TEMPLATE,
                                   trim_blocks=True, lstrip_blocks=True)
        with open(opf_filepath, 'wb') as opf_file:
            opf = template.render(package=package, locations=locations)
            if not isinstance(opf, bytes):
                opf = opf.encode('utf-8')
            opf_file.write(opf)

        return opf_filepath


Instruction:
Can you create a Python 3 function that
loads a DataFrame with all the needed info about the experiment

Response:
def from_file(self, file_name=None):
        """Loads a DataFrame with all the needed info about the experiment"""

        file_name = self._check_file_name(file_name)

        with open(file_name, 'r') as infile:
            top_level_dict = json.load(infile)

        pages_dict = top_level_dict['info_df']
        pages = pd.DataFrame(pages_dict)
        self.pages = pages
        self.file_name = file_name
        self._prm_packer(top_level_dict['metadata'])
        self.generate_folder_names()
        self.paginate()


Instruction:
How would you implement a function in Python 3 that
saves a DataFrame with all the needed info about the experiment

Response:
def to_file(self, file_name=None):
        """Saves a DataFrame with all the needed info about the experiment"""

        file_name = self._check_file_name(file_name)
        pages = self.pages

        top_level_dict = {
            'info_df': pages,
            'metadata': self._prm_packer()
        }

        jason_string = json.dumps(
            top_level_dict,
            default=lambda info_df: json.loads(
                info_df.to_json()
            )
        )

        self.paginate()

        with open(file_name, 'w') as outfile:
            outfile.write(jason_string)

        self.file_name = file_name
        logging.info("Saved file to {}".format(file_name))


Instruction:
Here you have a function in Python 3, explain what it does
def generate_folder_names(self):
        self.project_dir = os.path.join(prms.Paths.outdatadir, self.project)
        self.batch_dir = os.path.join(self.project_dir, self.name)
        self.raw_dir = os.path.join(self.batch_dir, "raw_data")

Response: Set appropriate folder names.


Instruction:
How would you code a function in Python 3 to
create the folders where we would like to put results etc.

Response:
def paginate(self):
        """Make folders where we would like to put results etc."""

        project_dir = self.project_dir
        raw_dir = self.raw_dir
        batch_dir = self.batch_dir

        if project_dir is None:
            raise UnderDefined("no project directory defined")
        if raw_dir is None:
            raise UnderDefined("no raw directory defined")
        if batch_dir is None:
            raise UnderDefined("no batcb directory defined")

        # create the folders
        if not os.path.isdir(project_dir):
            os.mkdir(project_dir)
            logging.info(f"created folder {project_dir}")
        if not os.path.isdir(batch_dir):
            os.mkdir(batch_dir)
            logging.info(f"created folder {batch_dir}")
        if not os.path.isdir(raw_dir):
            os.mkdir(raw_dir)
            logging.info(f"created folder {raw_dir}")

        return project_dir, batch_dir, raw_dir


Instruction:
Make a summary of the following Python 3 code
def generate_file_name(self):
        if not self.project:
            raise UnderDefined("project name not given")

        out_data_dir = prms.Paths.outdatadir
        project_dir = os.path.join(out_data_dir, self.project)
        file_name = "cellpy_batch_%s.json" % self.name
        self.file_name = os.path.join(project_dir, file_name)

Response: generate a suitable file name for the experiment


Instruction:
Write a Python 3 function for
delivering some info to you about the class.

Response:
def info(self):
        """Delivers some info to you about the class."""

        print("Sorry, but I don't have much to share.")
        print("This is me:")
        print(self)
        print("And these are the experiments assigned to me:")
        print(self.experiments)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def assign(self, experiment):

        self.experiments.append(experiment)
        self.farms.append(empty_farm)

Response: Assign an experiment to the current set of active experiments.


Instruction:
Given the following Python 3 function, write the documentation
def model_to_tree(model, title=None, lucent_id=TRANSLUCENT_BINDER_ID):
    id = model.ident_hash
    if id is None and isinstance(model, TranslucentBinder):
        id = lucent_id
    md = model.metadata
    shortid = md.get('shortId', md.get('cnx-archive-shortid'))
    title = title is not None and title or md.get('title')
    tree = {'id': id, 'title': title, 'shortId': shortid}
    if hasattr(model, '__iter__'):
        contents = tree['contents'] = []
        for node in model:
            item = model_to_tree(node, model.get_title_for_node(node),
                                 lucent_id=lucent_id)
            contents.append(item)
    return tree

Response: Given a TranslucentBinder model return a tree object.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def flatten_tree_to_ident_hashes(item_or_tree,
                                 lucent_id=TRANSLUCENT_BINDER_ID):
    """Flatten a tree to id and version values (ident_hash)."""
    if 'contents' in item_or_tree:
        tree = item_or_tree
        if tree['id'] != lucent_id:
            yield tree['id']
        for i in tree['contents']:
            # yield from flatten_tree_to_ident_hashs(i, lucent_id)
            for x in flatten_tree_to_ident_hashes(i, lucent_id):
                yield x
    else:
        item = item_or_tree
        yield item['id']

Response: Flatten a tree to id and version values ( ident_hash ).


Instruction:
Explain what the following Python 3 code does
def flatten_model(model):
    yield model
    if isinstance(model, (TranslucentBinder, Binder,)):
        for m in model:
            # yield from flatten_model(m)
            for x in flatten_model(m):
                yield x

Response: Flatten a model down to a list of models.


Instruction:
Implement a Python 3 function for
flattening the model down to a list of documents.

Response:
def flatten_to_documents(model, include_pointers=False):
    """Flatten the model to a list of documents (aka ``Document`` objects).
    This is to flatten a ``Binder``'ish model down to a list of documents.
    If ``include_pointers`` has been set to ``True``, ``DocumentPointers``
    will also be included in the results.

    """
    types = [Document]
    if include_pointers:
        types.append(DocumentPointer)
    types = tuple(types)

    def _filter(m):
        return isinstance(m, types)

    return flatten_to(model, _filter)


Instruction:
Can you write a function in Python 3 where it
gives a uri determine if it is internal or external.

Response:
def _discover_uri_type(uri):
    """Given a ``uri``, determine if it is internal or external."""
    parsed_uri = urlparse(uri)
    if not parsed_uri.netloc:
        if parsed_uri.scheme == 'data':
            type_ = INLINE_REFERENCE_TYPE
        else:
            type_ = INTERNAL_REFERENCE_TYPE
    else:
        type_ = EXTERNAL_REFERENCE_TYPE
    return type_


Instruction:
Create a Python 3 function for
parsing the references to Reference instances.

Response:
def _parse_references(xml):
    """Parse the references to ``Reference`` instances."""
    references = []
    ref_finder = HTMLReferenceFinder(xml)
    for elm, uri_attr in ref_finder:
        type_ = _discover_uri_type(elm.get(uri_attr))
        references.append(Reference(elm, type_, uri_attr))
    return references


Instruction:
Make a summary of the following Python 3 code
def _set_uri_from_bound_model(self):
        value = self._uri_template.format(self._bound_model.id)
        self.elm.set(self._uri_attr, value)

Response: Set the uri from the bound model.


Instruction:
Here you have a function in Python 3, explain what it does
def bind(self, model, template="{}"):
        self._bound_model = model
        self._uri_template = template
        self._set_uri_from_bound_model()

Response: Bind the model to the reference.


Instruction:
How would you explain what the following Python 3 function does
def index_bounds(x):
    if isinstance(x, (pd.DataFrame, pd.Series)):
        return x.iloc[0], x.iloc[-1]
    else:
        return x[0], x[-1]

Response: returns tuple with first and last item


Instruction:
Explain what the following Python 3 code does
def dqdv_cycle(cycle, splitter=True, **kwargs):

    c_first = cycle.loc[cycle["direction"] == -1]
    c_last = cycle.loc[cycle["direction"] == 1]

    converter = Converter(**kwargs)
    converter.set_data(c_first["capacity"], c_first["voltage"])
    converter.inspect_data()
    converter.pre_process_data()
    converter.increment_data()
    converter.post_process_data()
    voltage_first = converter.voltage_processed
    incremental_capacity_first = converter.incremental_capacity

    if splitter:
        voltage_first = np.append(voltage_first, np.NaN)
        incremental_capacity_first = np.append(incremental_capacity_first,
                                               np.NaN)

    converter = Converter(**kwargs)
    converter.set_data(c_last["capacity"], c_last["voltage"])
    converter.inspect_data()
    converter.pre_process_data()
    converter.increment_data()
    converter.post_process_data()
    voltage_last = converter.voltage_processed[::-1]
    incremental_capacity_last = converter.incremental_capacity[::-1]
    voltage = np.concatenate((voltage_first,
                              voltage_last))
    incremental_capacity = np.concatenate((incremental_capacity_first,
                                           incremental_capacity_last))

    return voltage, incremental_capacity

Response: Convenience function for creating dq - dv data from given capacity and voltage cycle.


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

    # TODO: should add option for normalising based on first cycle capacity
    # this is e.g. done by first finding the first cycle capacity (nom_cap)
    # (or use nominal capacity given as input) and then propagating this to
    # Converter using the key-word arguments
    #   normalize=True, normalization_factor=1.0, normalization_roof=nom_cap

    ica_dfs = list()
    cycle_group = cycles.groupby("cycle")
    for cycle_number, cycle in cycle_group:

        v, dq = dqdv_cycle(cycle, splitter=True, **kwargs)
        _ica_df = pd.DataFrame(
            {
                "voltage": v,
                "dq": dq,
            }
        )
        _ica_df["cycle"] = cycle_number
        _ica_df = _ica_df[['cycle', 'voltage', 'dq']]
        ica_dfs.append(_ica_df)

    ica_df = pd.concat(ica_dfs)
    return ica_df

Response: Convenience function for creating dq - dv data from given capacity and voltage cycles.


Instruction:
Given the following Python 3 function, write the documentation
def dqdv(voltage, capacity, voltage_resolution=None, capacity_resolution=None,
         voltage_fwhm=0.01, pre_smoothing=True, diff_smoothing=False,
         post_smoothing=True, post_normalization=True,
         interpolation_method=None, gaussian_order=None, gaussian_mode=None, gaussian_cval=None,
         gaussian_truncate=None, points_pr_split=None, savgol_filter_window_divisor_default=None,
         savgol_filter_window_order=None, max_points=None, **kwargs):

    """Convenience functions for creating dq-dv data from given capacity
    and voltage data.

    Args:
        voltage: nd.array or pd.Series
        capacity: nd.array or pd.Series
        voltage_resolution: used for interpolating voltage data (e.g. 0.005)
        capacity_resolution: used for interpolating capacity data
        voltage_fwhm: used for setting the post-processing gaussian sigma
        pre_smoothing: set to True for pre-smoothing (window)
        diff_smoothing: set to True for smoothing during differentiation (window)
        post_smoothing: set to True for post-smoothing (gaussian)
        post_normalization: set to True for normalising to capacity
        interpolation_method: scipy interpolation method
        gaussian_order: int
        gaussian_mode: mode
        gaussian_cval:
        gaussian_truncate:
        points_pr_split: only used when investigating data using splits
        savgol_filter_window_divisor_default: used for window smoothing
        savgol_filter_window_order: used for window smoothing
        max_points: restricting to max points in vector (capacity-selected)

    Returns: voltage, dqdv

    Notes:
        PEC data (Helge)
            pre_smoothing = False
            diff_smoothing = False
            pos_smoothing = False
            voltage_resolution = 0.005
        PEC data (Preben)
            ...
        Arbin data (IFE)
            ...
    """

    converter = Converter(**kwargs)
    logging.debug("dqdv - starting")
    logging.debug("dqdv - created Converter obj")
    converter.pre_smoothing = pre_smoothing
    converter.post_smoothing = post_smoothing
    converter.smoothing = diff_smoothing
    converter.normalize = post_normalization
    converter.voltage_fwhm = voltage_fwhm
    logging.debug(f"converter.pre_smoothing: {converter.pre_smoothing}")
    logging.debug(f"converter.post_smoothing: {converter.post_smoothing}")
    logging.debug(f"converter.smoothing: {converter.smoothing}")
    logging.debug(f"converter.normalise: {converter.normalize}")
    logging.debug(f"converter.voltage_fwhm: {converter.voltage_fwhm}")

    if voltage_resolution is not None:
        converter.voltage_resolution = voltage_resolution

    if capacity_resolution is not None:
        converter.capacity_resolution = capacity_resolution

    if savgol_filter_window_divisor_default is not None:
        converter.savgol_filter_window_divisor_default = savgol_filter_window_divisor_default

        logging.debug(f"converter.savgol_filter_window_divisor_default: "
                      f"{converter.savgol_filter_window_divisor_default}")

    if savgol_filter_window_order is not None:
        converter.savgol_filter_window_order = savgol_filter_window_order

        logging.debug(f"converter.savgol_filter_window_order: "
                      f"{converter.savgol_filter_window_order}")

    if gaussian_mode is not None:
        converter.gaussian_mode = gaussian_mode

    if gaussian_order is not None:
        converter.gaussian_order = gaussian_order

    if gaussian_truncate is not None:
        converter.gaussian_truncate = gaussian_truncate

    if gaussian_cval is not None:
        converter.gaussian_cval = gaussian_cval

    if interpolation_method is not None:
        converter.interpolation_method = interpolation_method

    if points_pr_split is not None:
        converter.points_pr_split = points_pr_split

    if max_points is not None:
        converter.max_points = max_points

    converter.set_data(capacity, voltage)
    converter.inspect_data()
    converter.pre_process_data()
    converter.increment_data()
    converter.post_process_data()

    return converter.voltage_processed, converter.incremental_capacity

Response: Convenience function for creating dq - dv data from given voltage and capacity data.


Instruction:
Given the following Python 3 function, write the documentation
def _dqdv_combinded_frame(cell, **kwargs):

    cycles = cell.get_cap(
        method="forth-and-forth",
        categorical_column=True,
        label_cycle_number=True,
    )
    ica_df = dqdv_cycles(cycles, **kwargs)
    assert isinstance(ica_df, pd.DataFrame)
    return ica_df

Response: Returns full cycle dqdv data for all cycles as one pd. DataFrame.


Instruction:
Given the following Python 3 function, write the documentation
def dqdv_frames(cell, split=False, **kwargs):
    # TODO: should add option for normalising based on first cycle capacity
    # this is e.g. done by first finding the first cycle capacity (nom_cap)
    # (or use nominal capacity given as input) and then propagating this to
    # Converter using the key-word arguments
    #   normalize=True, normalization_factor=1.0, normalization_roof=nom_cap

    if split:
        return _dqdv_split_frames(cell, tidy=True, **kwargs)
    else:
        return _dqdv_combinded_frame(cell, **kwargs)

Response: Returns dqdv data as pandas. DataFrame for all cycles.


Instruction:
Can you generate the documentation for the following Python 3 function
def _dqdv_split_frames(cell, tidy=False, **kwargs):
    charge_dfs, cycles, minimum_v, maximum_v = _collect_capacity_curves(
        cell,
        direction="charge"
    )
    # charge_df = pd.concat(
    # charge_dfs, axis=1, keys=[k.name for k in charge_dfs])

    ica_charge_dfs = _make_ica_charge_curves(
        charge_dfs, cycles, minimum_v, maximum_v,
        **kwargs,
    )
    ica_charge_df = pd.concat(
        ica_charge_dfs,
        axis=1,
        keys=[k.name for k in ica_charge_dfs]
    )

    dcharge_dfs, cycles, minimum_v, maximum_v = _collect_capacity_curves(
        cell,
        direction="discharge"
    )
    ica_dcharge_dfs = _make_ica_charge_curves(
        dcharge_dfs, cycles, minimum_v, maximum_v,
        **kwargs,
    )
    ica_discharge_df = pd.concat(
        ica_dcharge_dfs,
        axis=1,
        keys=[k.name for k in ica_dcharge_dfs]
    )
    ica_charge_df.columns.names = ["cycle", "value"]
    ica_discharge_df.columns.names = ["cycle", "value"]

    if tidy:
        ica_charge_df = ica_charge_df.melt(
            "voltage",
            var_name="cycle",
            value_name="dq",
            col_level=0
        )
        ica_discharge_df = ica_discharge_df.melt(
            "voltage",
            var_name="cycle",
            value_name="dq",
            col_level=0
        )

    return ica_charge_df, ica_discharge_df

Response: Returns dqdv data as pandas. DataFrames for all cycles.


Instruction:
Implement a Python 3 function for
setting the data for the current object.

Response:
def set_data(self, capacity, voltage=None,
                 capacity_label="q", voltage_label="v"
                 ):
        """Set the data"""

        logging.debug("setting data (capacity and voltage)")

        if isinstance(capacity, pd.DataFrame):
            logging.debug("recieved a pandas.DataFrame")
            self.capacity = capacity[capacity_label]
            self.voltage = capacity[voltage_label]
        else:
            assert len(capacity) == len(voltage)
            self.capacity = capacity
            self.voltage = voltage


Instruction:
How would you code a function in Python 3 to
check and inspect the data

Response:
def inspect_data(self, capacity=None, voltage=None,
                     err_est=False, diff_est=False):
        """check and inspect the data"""

        logging.debug("inspecting the data")

        if capacity is None:
            capacity = self.capacity
        if voltage is None:
            voltage = self.voltage

        if capacity is None or voltage is None:
            raise NullData

        self.len_capacity = len(capacity)
        self.len_voltage = len(voltage)

        if self.len_capacity <= 1:
            raise NullData
        if self.len_voltage <= 1:
            raise NullData

        self.min_capacity, self.max_capacity = value_bounds(capacity)
        self.start_capacity, self.end_capacity = index_bounds(capacity)

        self.number_of_points = len(capacity)

        if diff_est:
            d_capacity = np.diff(capacity)
            d_voltage = np.diff(voltage)

            self.d_capacity_mean = np.mean(d_capacity)
            self.d_voltage_mean = np.mean(d_voltage)

        if err_est:

            splits = int(self.number_of_points / self.points_pr_split)
            rest = self.number_of_points % self.points_pr_split

            if splits < self.minimum_splits:
                txt = "no point in splitting, too little data"
                logging.debug(txt)
                self.errors.append("splitting: to few points")
            else:
                if rest > 0:
                    _cap = capacity[:-rest]
                    _vol = voltage[:-rest]
                else:
                    _cap = capacity
                    _vol = voltage

                c_pieces = np.split(_cap, splits)
                v_pieces = np.split(_vol, splits)
                # c_middle = int(np.amax(c_pieces) / 2)

                std_err = []
                c_pieces_avg = []
                for c, v in zip(c_pieces, v_pieces):
                    _slope, _intercept, _r_value, _p_value, _std_err = stats.linregress(c, v)
                    std_err.append(_std_err)
                    c_pieces_avg.append(np.mean(c))

                self.std_err_median = np.median(std_err)
                self.std_err_mean = np.mean(std_err)

        if not self.start_capacity == self.min_capacity:
            self.errors.append("capacity: start<>min")

        if not self.end_capacity == self.max_capacity:
            self.errors.append("capacity: end<>max")

        if self.normalizing_factor is None:
            self.normalizing_factor = self.end_capacity

        if self.normalizing_roof is not None:
            self.normalizing_factor = self.normalizing_factor * \
                                      self.end_capacity / self.normalizing_roof


Instruction:
Explain what the following Python 3 code does
def pre_process_data(self):

        logging.debug("pre-processing the data")

        capacity = self.capacity
        voltage = self.voltage

        # performing an interpolation in v(q) space
        logging.debug(" - interpolating voltage(capacity)")
        c1, c2 = index_bounds(capacity)
        if self.max_points is not None:
            len_capacity = min(self.max_points, self.len_capacity)
        elif self.capacity_resolution is not None:
            len_capacity = round(abs(c2-c1) / self.capacity_resolution, 0)
        else:
            len_capacity = self.len_capacity

        f = interp1d(capacity, voltage, kind=self.interpolation_method)

        self.capacity_preprocessed = np.linspace(c1, c2, len_capacity)
        self.voltage_preprocessed = f(self.capacity_preprocessed)

        if self.pre_smoothing:
            logging.debug(" - pre-smoothing (savgol filter window)")
            savgol_filter_window_divisor = np.amin(
                (self.savgol_filter_window_divisor_default, len_capacity / 5)
            )
            savgol_filter_window_length = int(
                len_capacity / savgol_filter_window_divisor
            )

            if savgol_filter_window_length % 2 == 0:
                savgol_filter_window_length -= 1
            savgol_filter_window_length = np.amax(
                [3, savgol_filter_window_length]
            )

            self.voltage_preprocessed = savgol_filter(
                self.voltage_preprocessed,
                savgol_filter_window_length,
                self.savgol_filter_window_order
            )

Response: perform some pre - processing of the data


Instruction:
Implement a function in Python 3 to
perform the dq - dv transform on the current state of the entry.

Response:
def increment_data(self):
        """perform the dq-dv transform"""

        # NOTE TO ASBJOERN: Probably insert method for "binning" instead of
        # differentiating here
        # (use self.increment_method as the variable for selecting method for)

        logging.debug("incrementing data")

        # ---- shifting to y-x ----------------------------------------
        v1, v2 = value_bounds(self.voltage_preprocessed)
        if self.voltage_resolution is not None:
            len_voltage = round(abs(v2 - v1) / self.voltage_resolution, 0)
        else:
            len_voltage = len(self.voltage_preprocessed)

        # ---- interpolating ------------------------------------------
        logging.debug(" - interpolating capacity(voltage)")
        f = interp1d(
            self.voltage_preprocessed,
            self.capacity_preprocessed,
            kind=self.interpolation_method
        )

        self.voltage_inverted = np.linspace(v1, v2, len_voltage)
        self.voltage_inverted_step = (v2 - v1) / (len_voltage - 1)
        self.capacity_inverted = f(self.voltage_inverted)

        if self.smoothing:
            logging.debug(" - smoothing (savgol filter window)")
            savgol_filter_window_divisor = np.amin(
                (self.savgol_filter_window_divisor_default, len_voltage / 5)
            )

            savgol_filter_window_length = int(
                len(self.voltage_inverted) / savgol_filter_window_divisor
            )

            if savgol_filter_window_length % 2 == 0:
                savgol_filter_window_length -= 1

            self.capacity_inverted = savgol_filter(
                self.capacity_inverted,
                np.amax([3, savgol_filter_window_length]),
                self.savgol_filter_window_order
            )

        # ---  diff --------------------
        if self.increment_method == "diff":
            logging.debug(" - diff using DIFF")
            self.incremental_capacity = np.ediff1d(self.capacity_inverted) / self.voltage_inverted_step
            self._incremental_capacity = self.incremental_capacity
            # --- need to adjust voltage ---
            self._voltage_processed = self.voltage_inverted[1:]
            self.voltage_processed = self.voltage_inverted[1:] - 0.5 * self.voltage_inverted_step  # centering

        elif self.increment_method == "hist":
            logging.debug(" - diff using HIST")
            # TODO: Asbjoern, maybe you can put your method here?
            raise NotImplementedError


Instruction:
Create a Python 3 function to
perform post - processing of the data of the current object of the class

Response:
def post_process_data(self, voltage=None, incremental_capacity=None,
                          voltage_step=None):
        """perform post-processing (smoothing, normalisation, interpolation) of
        the data"""

        logging.debug("post-processing data")

        if voltage is None:
            voltage = self.voltage_processed
            incremental_capacity = self.incremental_capacity
            voltage_step = self.voltage_inverted_step

        if self.post_smoothing:
            logging.debug(" - post smoothing (gaussian)")
            logging.debug(f"    * using voltage fwhm: {self.voltage_fwhm}")
            points_fwhm = int(self.voltage_fwhm / voltage_step)

            sigma = np.amax([1, points_fwhm / 2])

            self.incremental_capacity = gaussian_filter1d(
                incremental_capacity, sigma=sigma, order=self.gaussian_order,
                mode=self.gaussian_mode,
                cval=self.gaussian_cval,
                truncate=self.gaussian_truncate
            )

        if self.normalize:
            logging.debug(" - normalizing")
            area = simps(incremental_capacity, voltage)
            self.incremental_capacity = incremental_capacity * self.normalizing_factor / abs(area)

        fixed_range = False
        if isinstance(self.fixed_voltage_range, np.ndarray):
            fixed_range = True
        else:
            if self.fixed_voltage_range:
                fixed_range = True
        if fixed_range:
            logging.debug(" - using fixed voltage range (interpolating)")
            v1, v2, number_of_points = self.fixed_voltage_range
            v = np.linspace(v1, v2, number_of_points)
            f = interp1d(x=self.voltage_processed, y=self.incremental_capacity,
                         kind=self.interpolation_method, bounds_error=False,
                         fill_value=np.NaN)

            self.incremental_capacity = f(v)
            self.voltage_processed = v


Instruction:
Can you generate the documentation for the following Python 3 function
def easybake(ruleset, in_html, out_html):
    html = etree.parse(in_html)
    oven = Oven(ruleset)
    oven.bake(html)
    out_html.write(etree.tostring(html))

Response: This function bake the ruleset in_html into out_html.


Instruction:
Here you have a function in Python 3, explain what it does
def reconstitute(html):
    try:
        htree = etree.parse(html)
    except etree.XMLSyntaxError:
        html.seek(0)
        htree = etree.HTML(html.read())

    xhtml = etree.tostring(htree, encoding='utf-8')
    return adapt_single_html(xhtml)

Response: Given a file - like object as html reconstruct it into models.


Instruction:
Create a Python 3 function for
collating the contents of a binder into a new set .

Response:
def collate(binder, ruleset=None, includes=None):
    """Given a ``Binder`` as ``binder``, collate the content into a new set
    of models.
    Returns the collated binder.

    """
    html_formatter = SingleHTMLFormatter(binder, includes)
    raw_html = io.BytesIO(bytes(html_formatter))
    collated_html = io.BytesIO()

    if ruleset is None:
        # No ruleset found, so no cooking necessary.
        return binder

    easybake(ruleset, raw_html, collated_html)

    collated_html.seek(0)
    collated_binder = reconstitute(collated_html)

    return collated_binder


Instruction:
Create a Python 3 function for
adapting ``.epub.Package`` to a ``BinderItem`` and cascades the adaptation downward to ``DocumentItem`` and ``ResourceItem``. The results of this process provide the same interface as ``.models.Binder``, ``.models.Document`` and ``.models.Resource``.

Response:
def adapt_package(package):
    """Adapts ``.epub.Package`` to a ``BinderItem`` and cascades
    the adaptation downward to ``DocumentItem``
    and ``ResourceItem``.
    The results of this process provide the same interface as
    ``.models.Binder``, ``.models.Document`` and ``.models.Resource``.
    """
    navigation_item = package.navigation
    html = etree.parse(navigation_item.data)
    tree = parse_navigation_html_to_tree(html, navigation_item.name)
    return _node_to_model(tree, package)


Instruction:
Write a Python 3 function that can
adapt ``.epub.Item`` to a ``DocumentItem``.

Response:
def adapt_item(item, package, filename=None):
    """Adapts ``.epub.Item`` to a ``DocumentItem``.

    """
    if item.media_type == 'application/xhtml+xml':
        try:
            html = etree.parse(item.data)
        except Exception as exc:
            logger.error("failed parsing {}".format(item.name))
            raise
        metadata = DocumentPointerMetadataParser(
            html, raise_value_error=False)()
        item.data.seek(0)
        if metadata.get('is_document_pointer'):
            model = DocumentPointerItem(item, package)
        else:
            model = DocumentItem(item, package)
    else:
        model = Resource(item.name, item.data, item.media_type,
                         filename or item.name)
    return model


Instruction:
Given the following Python 3 function, write the documentation
def make_epub(binders, file):
    if not isinstance(binders, (list, set, tuple,)):
        binders = [binders]
    epub = EPUB([_make_package(binder) for binder in binders])
    epub.to_file(epub, file)

Response: Creates an EPUB file from a list of binders.


Instruction:
How would you explain what the following Python 3 function does
def make_publication_epub(binders, publisher, publication_message, file):
    if not isinstance(binders, (list, set, tuple,)):
        binders = [binders]
    packages = []
    for binder in binders:
        metadata = binder.metadata
        binder.metadata = deepcopy(metadata)
        binder.metadata.update({'publisher': publisher,
                                'publication_message': publication_message})
        packages.append(_make_package(binder))
        binder.metadata = metadata
    epub = EPUB(packages)
    epub.to_file(epub, file)

Response: Creates an epub file from a list of binders.


Instruction:
Make a summary of the following Python 3 code
def _make_package(binder):
    package_id = binder.id
    if package_id is None:
        package_id = hash(binder)

    package_name = "{}.opf".format(package_id)

    extensions = get_model_extensions(binder)

    template_env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)

    # Build the package item list.
    items = []
    # Build the binder as an item, specifically a navigation item.
    navigation_document = bytes(HTMLFormatter(binder, extensions))
    navigation_document_name = "{}{}".format(
        package_id,
        mimetypes.guess_extension('application/xhtml+xml', strict=False))
    item = Item(str(navigation_document_name),
                io.BytesIO(navigation_document),
                'application/xhtml+xml',
                is_navigation=True, properties=['nav'])
    items.append(item)
    resources = {}
    # Roll through the model list again, making each one an item.
    for model in flatten_model(binder):
        for resource in getattr(model, 'resources', []):
            resources[resource.id] = resource
            with resource.open() as data:
                item = Item(resource.id, data, resource.media_type)
            items.append(item)

        if isinstance(model, (Binder, TranslucentBinder,)):
            continue
        if isinstance(model, DocumentPointer):
            content = bytes(HTMLFormatter(model))
            item = Item(''.join([model.ident_hash, extensions[model.id]]),
                        io.BytesIO(content),
                        model.media_type)
            items.append(item)
            continue
        for reference in model.references:
            if reference.remote_type == INLINE_REFERENCE_TYPE:
                # has side effects - converts ref type to INTERNAL w/
                # appropriate uri, so need to replicate resource treatment from
                # above
                resource = _make_resource_from_inline(reference)
                model.resources.append(resource)
                resources[resource.id] = resource
                with resource.open() as data:
                    item = Item(resource.id, data, resource.media_type)
                items.append(item)
                reference.bind(resource, '../resources/{}')

            elif reference.remote_type == INTERNAL_REFERENCE_TYPE:
                filename = os.path.basename(reference.uri)
                resource = resources.get(filename)
                if resource:
                    reference.bind(resource, '../resources/{}')

        complete_content = bytes(HTMLFormatter(model))
        item = Item(''.join([model.ident_hash, extensions[model.id]]),
                    io.BytesIO(complete_content),
                    model.media_type)
        items.append(item)

    # Build the package.
    package = Package(package_name, items, binder.metadata)
    return package

Response: Makes an. epub. Package from a Binder instance.


Instruction:
Can you write a function in Python 3 where it
makes an object from a models. Reference that is of type INLINE. That is a data uri.

Response:
def _make_resource_from_inline(reference):
    """Makes an ``models.Resource`` from a ``models.Reference``
       of type INLINE. That is, a data: uri"""
    uri = DataURI(reference.uri)
    data = io.BytesIO(uri.data)
    mimetype = uri.mimetype
    res = Resource('dummy', data, mimetype)
    res.id = res.filename
    return res


Instruction:
Write a Python 3 function that can
make an. epub. Item from a. models. Document or. models. Resource.

Response:
def _make_item(model):
    """Makes an ``.epub.Item`` from
    a ``.models.Document`` or ``.models.Resource``
    """
    item = Item(model.id, model.content, model.media_type)
    return item


Instruction:
Write a Python 3 function for
giving a tree parse to a set of models

Response:
def _node_to_model(tree_or_item, package, parent=None,
                   lucent_id=TRANSLUCENT_BINDER_ID):
    """Given a tree, parse to a set of models"""
    if 'contents' in tree_or_item:
        # It is a binder.
        tree = tree_or_item
        # Grab the package metadata, so we have required license info
        metadata = package.metadata.copy()
        if tree['id'] == lucent_id:
            metadata['title'] = tree['title']
            binder = TranslucentBinder(metadata=metadata)
        else:
            try:
                package_item = package.grab_by_name(tree['id'])
                binder = BinderItem(package_item, package)
            except KeyError:  # Translucent w/ id
                metadata.update({
                   'title': tree['title'],
                   'cnx-archive-uri': tree['id'],
                   'cnx-archive-shortid': tree['shortId']})
                binder = Binder(tree['id'], metadata=metadata)
        for item in tree['contents']:
            node = _node_to_model(item, package, parent=binder,
                                  lucent_id=lucent_id)
            if node.metadata['title'] != item['title']:
                binder.set_title_for_node(node, item['title'])
        result = binder
    else:
        # It is a document.
        item = tree_or_item
        package_item = package.grab_by_name(item['id'])
        result = adapt_item(package_item, package)
    if parent is not None:
        parent.append(result)
    return result


Instruction:
How would you implement a function in Python 3 that
adapts a single html document generated by . formatters. SingleHTMLFormatter to a Binder object.

Response:
def adapt_single_html(html):
    """Adapts a single html document generated by
    ``.formatters.SingleHTMLFormatter`` to a ``models.Binder``
    """
    html_root = etree.fromstring(html)

    metadata = parse_metadata(html_root.xpath('//*[@data-type="metadata"]')[0])
    id_ = metadata['cnx-archive-uri'] or 'book'

    binder = Binder(id_, metadata=metadata)
    nav_tree = parse_navigation_html_to_tree(html_root, id_)

    body = html_root.xpath('//xhtml:body', namespaces=HTML_DOCUMENT_NAMESPACES)
    _adapt_single_html_tree(binder, body[0], nav_tree, top_metadata=metadata)

    return binder


Instruction:
Can you tell what is the following Python 3 function doing
def select_ocv_points(cellpydata, cycles=None, selection_method="martin",
                      number_of_points=5,
                      interval=10,
                      relative_voltage=False,
                      report_times=False,
                      direction=None):

    """Select points from the ocvrlx steps.

        Args:
            cellpydata: CellpyData-object
            cycles: list of cycle numbers to process (optional)
            selection_method: criteria for selecting points
                martin: select first and last, and then last/2, last/2/2 etc.
                    until you have reached the wanted number of points.
                fixed_time: select first, and then
            number_of_points: number of points you want.
            interval: interval between each point (in use only for methods
                where interval makes sense). If it is a list, then
                number_of_points will be calculated as len(interval) + 1 (and
                override the set number_of_points).
            relative_voltage: set to True if you would like the voltage to be
                relative to the voltage before starting the ocv rlx step.
                Defaults to False. Remark that for the initial rxl step (when
                you just have put your cell on the tester) does not have any
                prior voltage. The relative voltage will then be versus the
                first measurement point.
            report_times: also report the ocv rlx total time if True (defaults
                to False)
            direction ("up", "down" or "both"): select "up" if you would like
                to process only the ocv rlx steps where the voltage is relaxing
                upwards and vize versa. Defaults to "both".

        Returns:
            pandas.DataFrame

    """

    if cycles is None:
        cycles = cellpydata.get_cycle_numbers()
    else:
        if not isinstance(cycles, (list, tuple)):
            cycles = [cycles, ]

    if direction is None:
        direction = "both"

    if not isinstance(interval, (list, tuple)):
        interval = [float(interval) for _ in range(number_of_points-1)]

    ocv_rlx_id = "ocvrlx"

    step_table = cellpydata.dataset.step_table
    dfdata = cellpydata.dataset.dfdata

    ocv_steps = step_table.loc[
        step_table["cycle"].isin(cycles), :
    ]

    ocv_steps = ocv_steps.loc[
        ocv_steps.type.str.startswith(ocv_rlx_id), :
    ]

    if selection_method in ["fixed_times", "fixed_points", "selected_times"]:
        number_of_points = len(interval) + 1

    headers2 = []
    for j in range(number_of_points):
        n = str(j).zfill(2)
        headers2.append(f"point_{n}")

    # doing an iteration (thought I didnt have to, but...) (fix later)

    results_list = list()
    iter_range = number_of_points - 1
    if selection_method == "martin":
        iter_range -= 1

    for index, row in ocv_steps.iterrows():

        # voltage
        first, last, delta = (
            row['voltage_first'],
            row['voltage_last'],
            row['voltage_delta']
        )

        voltage_reference = 0.0

        if relative_voltage:
            if index > 0:
                reference_row = step_table.iloc[index-1, :]
                voltage_reference = reference_row['voltage_last']

            else:
                voltage_reference = first
                logging.warning("STEP 0: Using first point as ref voltage")

        # time
        start, end, duration = (
            row['step_time_first'],
            row['step_time_last'],
            row['step_time_delta']
        )

        cycle, step = (row['cycle'], row['step'])
        info = row['type']

        v_df = dfdata.loc[
            (dfdata["Cycle_Index"] == cycle) &
            (dfdata["Step_Index"] == step), ["Step_Time", "Voltage"]
        ]

        poi = []

        _end = end
        _start = start

        if report_times:
            t = str(datetime.timedelta(seconds=round(end-start, 0)))
            print(f"Cycle {cycle}:", end=" ")
            print(f"dt = {t}, dv = {first-last:6.3f}")

        for i, j in enumerate(range(max(1, iter_range))):
            if selection_method == "martin":
                logging.debug("using the 'martin'-method")
                _end = _end / 2.0
                poi.append(_end)

            elif selection_method == "fixed_times":
                logging.debug(f"using fixed times with interval {interval[i]}")
                _start = _start + interval[i]
                logging.debug(f"time: {_start}")
                poi.append(_start)
            else:
                # more methods to come?
                logging.info("this method is not implemented")
                return None

        if selection_method == "martin":
            poi.reverse()

        df_poi = pd.DataFrame({"Step_Time": poi})
        df_poi["Voltage"] = np.nan

        v_df = v_df.append(df_poi, ignore_index=True)
        v_df = v_df.sort_values("Step_Time").reset_index(drop=True)
        v_df["new"] = v_df["Voltage"].interpolate()

        voi = []
        for p in poi:
            _v = v_df.loc[v_df["Step_Time"].isin([p]), "new"].values
            _v = _v - voltage_reference
            voi.append(_v[0])

        poi.insert(0, start)
        voi.insert(0, first - voltage_reference)
        if selection_method == "martin":
            poi.append(end)
            voi.append(last - voltage_reference)

        d1 = {"cycle": cycle}
        d2 = {h: [v] for h, v in zip(headers2, voi)}
        d = {**d1, **d2}
        result = pd.DataFrame(d)
        result["step"] = step
        result["type"] = info
        results_list.append(result)

    final = pd.concat(results_list)

    if direction == "down":
        final = final.loc[final["type"] == "ocvrlx_down", :]
    elif direction == "up":
        final = final.loc[final["type"] == "ocvrlx_up", :]

    final = final.reset_index(drop=True)

    return final

Response: Select points from the ocv rlx steps.


Instruction:
Can you generate the documentation for the following Python 3 function
def get_best_fit_parameters_grouped(self):
        result_dict = dict()
        result_dict['ocv'] = [parameters['ocv'] for parameters in
                              self.best_fit_parameters]

        for i in range(self.circuits):
            result_dict['t' + str(i)] = [parameters['t' + str(i)] for parameters
                                         in self.best_fit_parameters]
            result_dict['w' + str(i)] = [parameters['w' + str(i)] for parameters
                                         in self.best_fit_parameters]
        return result_dict

Response: Returns a dictionary of the best fit parameters grouped by the circuits.


Instruction:
Given the following Python 3 function, write the documentation
def get_best_fit_parameters_translated_grouped(self):
        result_dict = dict()
        result_dict['ocv'] = [parameters['ocv'] for parameters in
                              self.best_fit_parameters_translated]
        result_dict['ir'] = [parameters['ir'] for parameters in
                             self.best_fit_parameters_translated]

        for i in range(self.circuits):
            result_dict['r' + str(i)] = [parameters['r' + str(i)] for parameters
                                         in self.best_fit_parameters_translated]
            result_dict['c' + str(i)] = [parameters['c' + str(i)] for parameters
                                         in self.best_fit_parameters_translated]
        return result_dict

Response: Returns the parameters as a dictionary of the real units for the best fit.


Instruction:
Given the following Python 3 function, write the documentation
def plot_summary(self, cycles=None):
        if cycles is None:
            cycles = [0]
        fig1 = plt.figure()
        ax1 = fig1.add_subplot(221)
        ax1.set_title('Fit')
        ax2 = fig1.add_subplot(222)
        ax2.set_title('OCV')
        ax3 = fig1.add_subplot(223)
        ax3.set_title('Tau')
        ax3.set_yscale("log")
        ax4 = fig1.add_subplot(224)
        ax4.set_title('Voltage Impact')

        plot_data = self.get_best_fit_data()
        for cycle in cycles:
            ax1.plot(plot_data[cycle][0], plot_data[cycle][1])
            ax1.plot(plot_data[cycle][0], plot_data[cycle][2])

        plot_data = self.get_best_fit_parameters_grouped()

        for i in range(self.circuits):
            ax3.plot(self.get_fit_cycles(), plot_data['t' + str(i)])
            ax4.plot(self.get_fit_cycles(), plot_data['w' + str(i)])

        ax2.plot(self.get_fit_cycles(), plot_data['ocv'])

Response: Convenience function for plotting the summary of the fit


Instruction:
Make a summary of the following Python 3 code
def plot_summary_translated(self):

        fig2 = plt.figure()
        ax1 = fig2.add_subplot(221)
        ax1.set_title('OCV (V)')
        ax2 = fig2.add_subplot(222)
        ax2.set_title('IR (Ohm)')
        ax3 = fig2.add_subplot(223)
        ax3.set_title('Resistances (Ohm)')
        ax4 = fig2.add_subplot(224)
        ax4.set_title('Capacitances (F)')
        ax4.set_yscale("log")

        plot_data = self.get_best_fit_parameters_translated_grouped()
        print(plot_data['ocv'])
        print(plot_data['ir'])
        print(plot_data['r0'])

        ax1.plot(self.get_fit_cycles(), plot_data['ocv'])
        ax2.plot(self.get_fit_cycles(), plot_data['ir'])

        for i in range(self.circuits):
            ax3.plot(self.get_fit_cycles(), plot_data['r' + str(i)])
            ax4.plot(self.get_fit_cycles(), plot_data['c' + str(i)])

        plt.show()

Response:
Convenience function for plotting the summary of the the
        fit.


Instruction:
Given the following Python 3 function, write the documentation
def set_cellpydata(self, cellpydata, cycle):
        self.data = cellpydata
        self.step_table = self.data.dataset  # hope it works...
        time_voltage = self.data.get_ocv(direction='up',
                                         cycles=cycle)
        time = time_voltage.Step_Time
        voltage = time_voltage.Voltage

        self.time = np.array(time)
        self.voltage = np.array(voltage)

Response: This method is used to set the data object for the next cycle in the cellpydata.


Instruction:
Can you tell what is the following Python 3 function doing
def run_fit(self):

        # Check if data is set
        if self.time is []:
            self.result = []
            return

        try:
            self.fit_model()
        except ValueError as e:
            print(e)
        except AttributeError as e:
            print(e)

Response: Perform the fit of the OCV model


Instruction:
Can you generate a brief explanation for the following Python 3 code
def parse_navigation_html_to_tree(html, id):
    def xpath(x):
        return html.xpath(x, namespaces=HTML_DOCUMENT_NAMESPACES)
    try:
        value = xpath('//*[@data-type="binding"]/@data-value')[0]
        is_translucent = value == 'translucent'
    except IndexError:
        is_translucent = False
    if is_translucent:
        id = TRANSLUCENT_BINDER_ID
    tree = {'id': id,
            'title': xpath('//*[@data-type="document-title"]/text()')[0],
            'contents': [x for x in _nav_to_tree(xpath('//xhtml:nav')[0])]
            }
    return tree

Response: Parse the given html object to a tree.


Instruction:
Write a Python 3 function for
giving an etree containing a navigation document structure containing a navigation document structure generate a tree structure containing the top level navigation elements.

Response:
def _nav_to_tree(root):
    """Given an etree containing a navigation document structure
    rooted from the 'nav' element, parse to a tree:
    {'id': <id>|'subcol', 'title': <title>, 'contents': [<tree>, ...]}
    """
    def expath(e, x):
        return e.xpath(x, namespaces=HTML_DOCUMENT_NAMESPACES)
    for li in expath(root, 'xhtml:ol/xhtml:li'):
        is_subtree = bool([e for e in li.getchildren()
                           if e.tag[e.tag.find('}')+1:] == 'ol'])
        if is_subtree:
            # It's a sub-tree and have a 'span' and 'ol'.
            itemid = li.get('cnx-archive-uri', 'subcol')
            shortid = li.get('cnx-archive-shortid')
            yield {'id': itemid,
                   # Title is wrapped in a span, div or some other element...
                   'title': squash_xml_to_text(expath(li, '*')[0],
                                               remove_namespaces=True),
                   'shortId': shortid,
                   'contents': [x for x in _nav_to_tree(li)],
                   }
        else:
            # It's a node and should only have an li.
            a = li.xpath('xhtml:a', namespaces=HTML_DOCUMENT_NAMESPACES)[0]
            yield {'id': a.get('href'),
                   'shortid': li.get('cnx-archive-shortid'),
                   'title': squash_xml_to_text(a, remove_namespaces=True)}


Instruction:
Can you write a function in Python 3 where it
returns a list of resource names found in the html metadata section.

Response:
def parse_resources(html):
    """Return a list of resource names found in the html metadata section."""
    xpath = '//*[@data-type="resources"]//xhtml:li/xhtml:a'
    for resource in html.xpath(xpath, namespaces=HTML_DOCUMENT_NAMESPACES):
        yield {
            'id': resource.get('href'),
            'filename': resource.text.strip(),
            }


Instruction:
Explain what the following Python 3 code does
def on_connect(self, client, userdata, flags, rc):
        '''
        Callback for when the client receives a ``CONNACK`` response from the
        broker.

        Parameters
        ----------
        client : paho.mqtt.client.Client
            The client instance for this callback.
        userdata : object
            The private user data as set in :class:`paho.mqtt.client.Client`
            constructor or :func:`paho.mqtt.client.Client.userdata_set`.
        flags : dict
            Response flags sent by the broker.

            The flag ``flags['session present']`` is useful for clients that
            are using clean session set to 0 only.

            If a client with clean session=0, that reconnects to a broker that
            it has previously connected to, this flag indicates whether the
            broker still has the session information for the client.

            If 1, the session still exists.
        rc : int
            The connection result.

            The value of rc indicates success or not:

              - 0: Connection successful
              - 1: Connection refused - incorrect protocol version
              - 2: Connection refused - invalid client identifier
              - 3: Connection refused - server unavailable
              - 4: Connection refused - bad username or password
              - 5: Connection refused - not authorised
              - 6-255: Currently unused.

        Notes
        -----

        Subscriptions should be defined in this method to ensure subscriptions
        will be renewed upon reconnecting after a loss of connection.
        '''
        super(SerialDeviceManager, self).on_connect(client, userdata, flags, rc)

        if rc == 0:
            self.mqtt_client.subscribe('serial_device/+/connect')
            self.mqtt_client.subscribe('serial_device/+/send')
            self.mqtt_client.subscribe('serial_device/+/close')
            self.mqtt_client.subscribe('serial_device/refresh_comports')
            self.refresh_comports()

Response: This method is called when a client connects to a specific broker.


Instruction:
Given the following Python 3 function, write the documentation
def _publish_status(self, port):
        '''
        Publish status for specified port.

        Parameters
        ----------
        port : str
            Device name/port.
        '''
        if port not in self.open_devices:
            status = {}
        else:
            device = self.open_devices[port].serial
            properties = ('port', 'baudrate', 'bytesize', 'parity', 'stopbits',
                          'timeout', 'xonxoff', 'rtscts', 'dsrdtr')
            status = {k: getattr(device, k) for k in properties}
        status_json = json.dumps(status)
        self.mqtt_client.publish(topic='serial_device/%s/status' % port,
                                 payload=status_json, retain=True)

Response: Publish status for specified port.


Instruction:
How would you implement a function in Python 3 that
handles close request. Parameters ---------- port : str Device name/port.

Response:
def _serial_close(self, port):
        '''
        Handle close request.

        Parameters
        ----------
        port : str
            Device name/port.
        '''
        if port in self.open_devices:
            try:
                self.open_devices[port].close()
            except Exception as exception:
                logger.error('Error closing device `%s`: %s', port, exception)
                return
        else:
            logger.debug('Device not connected to `%s`', port)
            self._publish_status(port)
            return