Customize

A new task can easily be added to Slitflow as a user-defined class. The first approach is to define a class directly in the Python script or Jupyter notebook inherited from a Slitflow Data class.

The script below defines a simple class in the executable script that adds one to the value of the table column, a class object being directly connected to a series of Data objects. This procedure does not enable user-defined classes to be added to the pipeline and run; however, it helps with new prototype classes.

import slitflow as sf


class AddOne(sf.tbl.table.Table):
   """Class should have brief description.
   """

   def set_info(self, param):
      self.info.copy_req(0)
      # this class should remove zero depth columns except for calc_col
      index_cols = self.info.get_column_name("index")
      self.info.delete_column(keeps=index_cols + [param["calc_col"]])
      # index column names are also required to specify which column should
      # be remained
      self.info.add_param(
            "index_cols", index_cols, "str", "Index column names")
      self.info.add_param(
            "calc_col", param["calc_col"], "str", "Column name to calculate")
      self.info.set_split_depth(param["split_depth"])

   @staticmethod
   def process(reqs, param):
      df = reqs[0].copy()
      df_result = df[param["index_cols"]].copy()
      df_result[param["calc_col"]] = df[param["calc_col"]].values + 1
      return df_result


# --- script from here ---
D1 = sf.tbl.create.Index()
D1.run([], {"type": "trajectory", "index_counts": [1, 2], "split_depth": 0})
D2 = sf.trj.random.Walk2DCenter()
D2.run([D1], {"diff_coeff": 0.1, "interval": 0.1, "n_step": 2,
            "length_unit": "um", "seed": 1, "split_depth": 0})
D3 = AddOne()
D3.run([D2], {"calc_col": "x_um", "split_depth": 0})
print(D3.data[0])
#    img_no  trj_no  frm_no      x_um
#         1       1       1  1.000000
#         1       1       2  1.229717
#         1       1       3  1.143202
# ...

The second approach is to add a class as a module file to the user subpackage folder of the Slitflow source code. This allows the user-defined class to be added to the pipeline and incorporated within a reusable analysis workflow, or to create a flowchart. The following example executes the AddOne class of a template module saved as an example in a user subpackage.

PL = sf.manager.Pipeline("path_to_project_directory")
obs_names = ["Sample1"]
PL.add(sf.tbl.create.Index(), 0, (1, 1), 'group1', 'index',
      obs_names, [], [],
      {"type": "trajectory", "index_counts": [1, 2], "split_depth": 0})
PL.add(sf.trj.random.Walk2DCenter(), 0, (1, 2), None, 'trj',
      obs_names, [(1, 1)], [0],
      {"diff_coeff": 0.1, "interval": 0.1, "n_step": 2,
      "length_unit": "um", "seed": 1, "split_depth": 0})
PL.add(sf.user.template.AddOne(), 0, (1, 3), None, 'one',
      obs_names, [(1, 2)], [0],
      {"calc_col": "x_um", "split_depth": 0})
PL.save("pipeline")
PL.run()

For more useful user-defined module files, consider moving them to the dev subpackage folder and pulling requests to the dev branch of the Slitflow repository to share them among users.