docs: 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