diff --git a/README.md b/README.md
index 63fdcd3e9585e6db4630506276c1031628269884..7f2bedde4d04044fcd03df163e7011707690df71 100644
--- a/README.md
+++ b/README.md
@@ -123,5 +123,11 @@ Folder `input_folder/results` contain three subfolders:
 # Orinal repo
 For the orignal repo, please take a look there: https://github.com/philwilkes/FSCT and https://github.com/philwilkes/TLS2trees
 
+# Orinal repo
 
+Sematic labels expected:
+1 - ground
+2 - vegetation
+3 - cwd
+4 - trunk
 
diff --git a/bash_helper_scripts/get_small_data_for_playground.sh b/bash_helper_scripts/get_small_data_for_playground.sh
index a0c5e0f2b06007b807018a42cf8a9201507e01eb..8b37daf4a4204bcf6e486d0fd30770ea8149a431 100755
--- a/bash_helper_scripts/get_small_data_for_playground.sh
+++ b/bash_helper_scripts/get_small_data_for_playground.sh
@@ -1,16 +1,22 @@
-TARGET_FOLDER=/home/nibio/mutable-outside-world/code/gitlab_fsct/instance_segmentation_classic/sample_playground
+#!/bin/bash
+
+# Define target folder
+TARGET_FOLDER="/home/nibio/mutable-outside-world/code/gitlab_fsct/instance_segmentation_classic/maciek"
+
+# Number of files you want to create
+NUM_FILES=$1
+
+# Delete old files in the target folder
 rm -rf $TARGET_FOLDER/*
 
+# Copy the original file to the target folder
 cp /home/nibio/mutable-outside-world/data/small_file_pipeline_test/small_file_pipeline_test.las $TARGET_FOLDER
 
-# change name of the file to first.laz 
+# Change the name of the original file to first.las
 mv $TARGET_FOLDER/small_file_pipeline_test.las $TARGET_FOLDER/first.las
 
-# make a copy of the file
-# cp $TARGET_FOLDER/first.las $TARGET_FOLDER/second.las
-
-# # make a copy of the file
-# cp $TARGET_FOLDER/first.las $TARGET_FOLDER/third.las
-
-# # make a copy of the file
-# cp $TARGET_FOLDER/first.las $TARGET_FOLDER/fourth.las
\ No newline at end of file
+# Make copies of the original file based on the number provided
+for (( i=2; i<=NUM_FILES; i++ ))
+do
+    cp $TARGET_FOLDER/first.las $TARGET_FOLDER/file_$i.las
+done
diff --git a/nibio_postprocessing/las_to_pandas.py b/nibio_postprocessing/las_to_pandas.py
index e4945429b0ccfff2fe7fe03513a7af9337d8d705..a82bd7cca9937e67ecd98c590d3b31c1840bf840 100644
--- a/nibio_postprocessing/las_to_pandas.py
+++ b/nibio_postprocessing/las_to_pandas.py
@@ -4,7 +4,7 @@ import laspy
 
 # works with laspy 2.1.2
 
-def las_to_pandas(las_file_path, csv_file_path, save_csv=True):
+def las_to_pandas(las_file_path, csv_file_path=None):
     """
     Reads a LAS file and converts it to a pandas dataframe, then saves it to a CSV file.
 
@@ -32,7 +32,7 @@ def las_to_pandas(las_file_path, csv_file_path, save_csv=True):
     points_df = pd.DataFrame(all_points, columns=all_columns)
 
     # Save pandas dataframe to csv
-    if save_csv:
+    if csv_file_path is not None:
         points_df.to_csv(csv_file_path, index=False, header=True, sep=',')
 
     return points_df
diff --git a/nibio_postprocessing/modification_pipeline.py b/nibio_postprocessing/modification_pipeline.py
new file mode 100644
index 0000000000000000000000000000000000000000..7dd72f9933761188d1a6fe10fb6576e1f1374c0d
--- /dev/null
+++ b/nibio_postprocessing/modification_pipeline.py
@@ -0,0 +1,61 @@
+import os
+from nibio_postprocessing.ply_to_pandas import ply_to_pandas
+from nibio_postprocessing.pandas_to_las import pandas_to_las
+
+def las_modification_pipeline(input_file_path, output_file_path):
+    # read the input file
+    points_df = ply_to_pandas(input_file_path, csv_file_path=None)
+
+    ### steps to do #########
+
+    # rename column from semantic_seg to label
+    points_df.rename(columns={'semantic_seg': 'label'}, inplace=True)
+
+    # remove all the columns except x, y, z, and label, and treeID
+    all_columns = list(points_df.columns) 
+    columns_to_keep = ['x', 'y', 'z', 'label', 'treeID']
+    columns_to_remove = list(set(all_columns) - set(columns_to_keep))
+    points_df.drop(columns_to_remove, axis=1, inplace=True)
+
+    # for label change rows with value 2 to 1 (low vegetation is mapped to ground)
+    points_df.loc[points_df['label'] == 2, 'label'] = 1
+
+    # remove rows with label 0 (unclassified)
+    points_df = points_df[points_df['label'] != 0]
+
+    # for label change rows with value 4 and 5 change to 2 (map branches and live-branches to vegetation)
+    points_df.loc[points_df['label'] == 4, 'label'] = 2
+    points_df.loc[points_df['label'] == 5, 'label'] = 2
+
+    # for label change rows with value 3 change to 4 (remap trunk)
+    points_df.loc[points_df['label'] == 3, 'label'] = 4
+
+    ### end of steps to do ###
+
+    # save the input file as output file
+    pandas_to_las(points_df, output_file_path)
+
+    return None
+
+if __name__ == "__main__":
+    import argparse
+
+    parser = argparse.ArgumentParser(description='Process ply files and save results as las files.')
+    parser.add_argument('-i', '--input_folder', type=str, help='Path to the input folder containing ply files.')
+    parser.add_argument('-o', '--output_folder', type=str, help='Path to the output folder to save las files.')
+
+    args = parser.parse_args()
+
+    # Ensure output directory exists
+    if not os.path.exists(args.output_folder):
+        os.makedirs(args.output_folder)
+
+    # Loop through each file in the input directory
+    for filename in os.listdir(args.input_folder):
+        if filename.endswith(".ply"):
+            input_file_path = os.path.join(args.input_folder, filename)
+            output_file_name = os.path.splitext(filename)[0] + "_out.las"
+            output_file_path = os.path.join(args.output_folder, output_file_name)
+            
+            # run the pipeline
+            las_modification_pipeline(input_file_path, output_file_path)
diff --git a/nibio_postprocessing/pandas_to_las.py b/nibio_postprocessing/pandas_to_las.py
index 71e7e5ba1193b31b47a011afd7426a800976c10a..c87c3ae74d64ab144c9251abca5e70d132f1328d 100644
--- a/nibio_postprocessing/pandas_to_las.py
+++ b/nibio_postprocessing/pandas_to_las.py
@@ -1,10 +1,11 @@
+import collections
 import laspy
 import pandas as pd
 import numpy as np
 
 # works with laspy 2.1.2
 
-def pandas_to_las(csv, las_file_path, csv_file_provided=True, verbose=False):
+def pandas_to_las(csv, las_file_path, csv_file_provided=False, verbose=False):
     """
     Convert a pandas DataFrame to a .las file.
 
@@ -35,7 +36,17 @@ def pandas_to_las(csv, las_file_path, csv_file_provided=True, verbose=False):
             raise ValueError(f'Column {col} not found in {csv}')
         
     # Create a new .las file
-    las_header = laspy.LasHeader()
+    las_header = laspy.LasHeader(point_format=3, version="1.2")
+
+    standard_columns = list(las_header.point_format.dimension_names)
+
+    # check which columns in the csv file are in the standard columns
+    csv_standard_columns = list(set(standard_columns) & set(df.columns))
+
+    # add them to required columns if they are not already there
+    for col in csv_standard_columns:
+        if col not in required_columns:
+            required_columns.append(col)
 
     # read all the colum names from the csv file
     csv_columns = list(df.columns)
@@ -58,7 +69,11 @@ def pandas_to_las(csv, las_file_path, csv_file_provided=True, verbose=False):
 
     # Assign extra dimensions
     for col in gt_extra_dimensions:
-        outfile[col] = df[col].values
+        # if you are processing col=return_num limit the values to 0-7
+        if col == 'return_num':
+            outfile[col] = df[col].values % 8
+        else:
+            outfile[col] = df[col].values
 
     # Write the file
     outfile.write(las_file_path)
diff --git a/nibio_postprocessing/ply_to_pandas.py b/nibio_postprocessing/ply_to_pandas.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba05d539c97abbb1f9bf408ceaf1da8091d3f17c
--- /dev/null
+++ b/nibio_postprocessing/ply_to_pandas.py
@@ -0,0 +1,52 @@
+import numpy as np
+import pandas as pd
+from plyfile import PlyData
+
+def ply_to_pandas(ply_file_path, csv_file_path=None):
+    """
+    Reads a PLY file and converts its vertex data to a numpy array, then saves it to a CSV file.
+
+    Args:
+        ply_file_path (str): The path to the PLY file to be read.
+        csv_file_path (str, optional): The path to the CSV file to be saved. If not provided, 
+                                       the output CSV will have the same name as the input PLY file.
+
+    Returns:
+        numpy.ndarray: A 2D array containing the vertex data from the PLY file.
+    """
+    # Load the PLY file
+    ply_content = PlyData.read(ply_file_path)
+
+    # Identify available elements in the PLY file
+    available_elements = [elem.name for elem in ply_content.elements]
+    print("Available elements in the PLY file:", available_elements)
+
+    # Determine the element that represents the point cloud data
+    if 'vertex' in available_elements:
+        point_element_name = 'vertex'
+    elif 'point' in available_elements:
+        point_element_name = 'point'
+    else:
+        print("Could not find a suitable element for point cloud data.")
+        return
+
+    # Extract data from the chosen element
+    point_data = ply_content[point_element_name].data
+    property_names = point_data.dtype.names
+    data_arrays = [point_data[prop_name] for prop_name in property_names]
+    all_points = np.vstack(data_arrays).T
+
+    # Save the data to a CSV file
+    if csv_file_path is not None:
+        np.savetxt(csv_file_path, all_points, delimiter=',', header=','.join(property_names), comments='', fmt='%s')
+
+    # put the data into a pandas dataframe
+    points_df = pd.DataFrame(all_points, columns=property_names)
+
+    return points_df
+
+if __name__ == "__main__":
+    ply_path = "/home/nibio/mutable-outside-world/code/gitlab_fsct/instance_segmentation_classic/Binbin_data_paper/TUWIEN_test_test.ply"
+    csv_path = "/home/nibio/mutable-outside-world/code/gitlab_fsct/instance_segmentation_classic/Binbin_data_paper/TUWIEN_test_test.csv"
+
+    ply_to_pandas(ply_path, csv_path)