diff --git a/gga_get_data.py b/gga_get_data.py
index 6bfc9b13b0a4bdb5cfc4dedbf43a7e362696d843..5724b9b42c5a9073011831929c4dbdab4e08ac5f 100644
--- a/gga_get_data.py
+++ b/gga_get_data.py
@@ -53,70 +53,70 @@ class GetData(speciesData.SpeciesData):
         return 1
 
 
-    def batch_modify_fasta_headers(self):
-        """
-        Change the fasta headers before integration, so that the indexing tool in galaxy interprets the headers
-        correctly and doesn't throw an error
-
-        The function will use the class attribute "source_datasets", pointing to files in the galaxy
-        library to find the fasta files that need their headers formatted
-
-        :return:
-        """
-
-        proteins_file = None
-        proteins_outfile = None
-        annotation_dir = None
-        organism_annotation_dir = os.path.abspath("./src_data/annotation/{0}/OGS{1}".format(self.species_folder_name, self.ogs_version))
-
-        self.goto_species_dir()
-
-        for d in [i[0] for i in os.walk(os.getcwd() + "/src_data")]:
-            if "annotation" in d and self.species_folder_name in d and self.ogs_version in d:
-                for f in os.listdir(d):
-                    if "proteins" in f:
-                        proteins_file = os.path.join(d, f)
-                        proteins_outfile = os.path.join(d, "outfile_proteins.fa")
-                        annotation_dir = os.path.abspath(d)
-        # Formatting the headers
-        if proteins_file is not None:
-            self.format_fasta_headers(infile=proteins_file,
-                                      outfile=proteins_outfile,
-                                      pattern="^>mRNA",
-                                      repl=">protein")
-            if os.path.exists(annotation_dir + "/outfile_proteins.fa"):
-                subprocess.call(["mv", annotation_dir + "/outfile_proteins.fa", proteins_file],
-                               stdout=subprocess.PIPE,
-                               stderr=subprocess.PIPE,
-                               cwd=annotation_dir)
-                subprocess.call(["rm", annotation_dir + "/outfile_proteins.fa"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=annotation_dir)
-
-        else:
-            logging.warning("Skipping proteins fasta headers formatting (FileNotFound)")
-
-    @staticmethod
-    def format_fasta_headers(infile, outfile, pattern, repl):
-        """
-        Format the fasta headers of a given file, given a matching pattern and a replacement string
-
-        :param infile:
-        :param outfile:
-        :param pattern:
-        :param repl:
-        :return:
-        """
-
-        infile = open(infile, 'r')
-        outfile = open(outfile, 'w')
-
-        lines = infile.readlines()
-
-        for line in lines:
-            line_out = re.sub(pattern, repl, line)
-            outfile.write(line_out)
-
-        infile.close()
-        outfile.close()
+    # def batch_modify_fasta_headers(self):
+    #     """
+    #     Change the fasta headers before integration, so that the indexing tool in galaxy interprets the headers
+    #     correctly and doesn't throw an error
+
+    #     The function will use the class attribute "source_datasets", pointing to files in the galaxy
+    #     library to find the fasta files that need their headers formatted
+
+    #     :return:
+    #     """
+
+    #     proteins_file = None
+    #     proteins_outfile = None
+    #     annotation_dir = None
+    #     organism_annotation_dir = os.path.abspath("./src_data/annotation/{0}/OGS{1}".format(self.species_folder_name, self.ogs_version))
+
+    #     self.goto_species_dir()
+
+    #     for d in [i[0] for i in os.walk(os.getcwd() + "/src_data")]:
+    #         if "annotation" in d and self.species_folder_name in d and self.ogs_version in d:
+    #             for f in os.listdir(d):
+    #                 if "proteins" in f:
+    #                     proteins_file = os.path.join(d, f)
+    #                     proteins_outfile = os.path.join(d, "outfile_proteins.fa")
+    #                     annotation_dir = os.path.abspath(d)
+    #     # Formatting the headers
+    #     if proteins_file is not None:
+    #         self.format_fasta_headers(infile=proteins_file,
+    #                                   outfile=proteins_outfile,
+    #                                   pattern="^>mRNA",
+    #                                   repl=">protein")
+    #         if os.path.exists(annotation_dir + "/outfile_proteins.fa"):
+    #             subprocess.call(["mv", annotation_dir + "/outfile_proteins.fa", proteins_file],
+    #                            stdout=subprocess.PIPE,
+    #                            stderr=subprocess.PIPE,
+    #                            cwd=annotation_dir)
+    #             subprocess.call(["rm", annotation_dir + "/outfile_proteins.fa"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=annotation_dir)
+
+    #     else:
+    #         logging.warning("Skipping proteins fasta headers formatting (FileNotFound)")
+
+    # @staticmethod
+    # def format_fasta_headers(infile, outfile, pattern, repl):
+    #     """
+    #     Format the fasta headers of a given file, given a matching pattern and a replacement string
+
+    #     :param infile:
+    #     :param outfile:
+    #     :param pattern:
+    #     :param repl:
+    #     :return:
+    #     """
+
+    #     infile = open(infile, 'r')
+    #     outfile = open(outfile, 'w')
+
+    #     lines = infile.readlines()
+
+    #     for line in lines:
+    #         line_out = re.sub(pattern, repl, line)
+    #         outfile.write(line_out)
+
+    #     infile.close()
+    #     outfile.close()
 
     def get_source_data_files_from_path(self):
         """
@@ -297,8 +297,8 @@ if __name__ == "__main__":
         logging.info("Sucessfully copied datasets for %s" % get_data_for_current_species.full_name)
         
         # Format fasta headers (proteins)
-        logging.info("Formatting fasta files headers %s " % get_data_for_current_species.full_name)
-        get_data_for_current_species.batch_modify_fasta_headers()
-        logging.info("Successfully formatted files headers %s " % get_data_for_current_species.full_name)
+        # logging.info("Formatting fasta files headers %s " % get_data_for_current_species.full_name)
+        # get_data_for_current_species.batch_modify_fasta_headers()
+        # logging.info("Successfully formatted files headers %s " % get_data_for_current_species.full_name)
 
         logging.info("Data successfully loaded and imported for %s" % get_data_for_current_species.full_name)
diff --git a/gga_init.py b/gga_init.py
index 605e43c8dd9485d95bbace75abc660cde26ccc32..b0b743610662dc4626092f5a6adc0fc254347067 100644
--- a/gga_init.py
+++ b/gga_init.py
@@ -21,6 +21,11 @@ gga_init.py
 
 Usage: $ python3 gga_init.py -i input_example.yml --config config.yml [OPTIONS]
 
+
+TODO
+- Exclude traefik dir tree creation and file writing from the loop (make make_dirs() an external func and write a func similar to make_compose_files()
+  for traefik and authelia as an external func)
+
 """
 
 
@@ -82,11 +87,15 @@ class DeploySpeciesStack(speciesData.SpeciesData):
         try:
             os.mkdir("./src_data")
         except FileExistsError:
-            logging.debug("src_data folder already exist for %s" % self.full_name)
+            logging.debug("'src_data' directory already exist for %s" % self.full_name)
         except PermissionError as exc:
             logging.critical("Insufficient permission to create src_data directory tree")
             sys.exit(exc)
 
+
+        print(self.strain)
+        print(self.species_folder_name)
+
         # List of all the directories to create in src_data
         src_data_dirs_li = ["./src_data", "./src_data/annotation", "./src_data/genome", "./src_data/tracks",
                             "./src_data/annotation/%s" % self.species_folder_name,
@@ -160,12 +169,32 @@ class DeploySpeciesStack(speciesData.SpeciesData):
         # Create the volumes (directory) of the species docker-compose file
         self.create_mounts(working_dir=".")
 
+        # Return to main directory
+        os.chdir(self.main_dir)
+
+    def make_traefik_compose_files(self):
+        """
+        Create or update the traefik docker-compose file and authelia conf files
+        Will only write new authelia conf files if the argument "--overwrite-all" is specified or
+        the authelia directory doesn't contain conf files
+
+        :return:
+        """
+
         # Proceed to the traefik and authelia directories
         os.chdir(self.main_dir)
+
+        # Create directory tree
         self.make_dirs(["./traefik", "./traefik/authelia"])
+
         # Render and try to write the traefik docker-compose file
         # This new docker-compose file will not overwrite the one already present in the traefik dir
         # unless the argument "--overwrite-all" is specified
+
+        # Jinja2 templating, handled using the python "jinja2" module
+        file_loader = FileSystemLoader(self.script_dir + "/templates")
+        env = Environment(loader=file_loader)
+
         if not os.path.isfile("./traefik/docker-compose.yml") or force:
             traefik_compose_template = env.get_template("traefik_compose_template.yml.j2")
             traefik_compose_output = traefik_compose_template.render(render_vars)
@@ -199,6 +228,7 @@ class DeploySpeciesStack(speciesData.SpeciesData):
         # Return to main directory
         os.chdir(self.main_dir)
 
+
     def create_mounts(self, working_dir):
         """
         Create the folders (volumes) required by a container (to see required volumes, check their compose file)
@@ -249,41 +279,59 @@ class DeploySpeciesStack(speciesData.SpeciesData):
             logging.critical("Cannot access %s, exiting" % self.main_dir)
             sys.exit(exc)
 
-    def deploy_stack(self, input_list):
-        """
-        Call the script "deploy.sh" used to initiliaze the swarm cluster if needed and
-        launch/update the current organism's stack
-
-        This script first try to deploy the traefik stack, then deploy the organism stack, then update the traefik stack
-        The stacks are updated if already deployed
-
-        :return:
-        """
-
 
-        to_deploy_species_li = []
+def deploy_stacks(input_list, main_dir):
+    """
+    This function first deploys/redeploys the traefik stack, then deploys/redeploys the organism stack, then redeploys the traefik stack
+    This function is executed outside the "main" loop of input species
 
-        # # Create our swarm cluster if it doesn't exist
-        # subprocess.Popen(["docker", "swarm", "init"],
-        #                  stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.main_dir)
-        #
-        # # Deploy/update the stack for the current species
-        # subprocess.Popen(["docker", "stack", "deploy", "-c", "./docker-compose.yml", "{0}_{1}".format(self.genus_lowercase, self.species)],
-        #                  stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.main_dir)
+    :return:
+    """
 
-        # Launch and update docker stacks
-        # noinspection PyArgumentList
-        # deploy_stacks_popen = subprocess.Popen(["sh", self.script_dir + "/deploy.sh", self.genus_species,
-        #                                         self.main_dir + "/traefik"],
-        #                                        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
-        #                                        universal_newlines=True)
-        #
-        # for stdout_line in iter(deploy_stacks_popen.stdout.readline, ""):
-        #     if "daemon" in stdout_line:  # Ignore swarm init error output
-        #         pass
-        #     else:
-        #         logging.info("\t%s" % stdout_line.strip())
-        # deploy_stacks_popen.stdout.close()
+    main_dir = os.path.abspath(main_dir)
+    os.chdir(main_dir)
+
+    # Get species for which to deploy the stacks
+    to_deploy_species_li = utilities.get_species_to_deploy(sp_dict_list=input_list)
+
+    # Create the swarm cluster if needed
+    subprocess.call(["docker", "swarm", "init"],
+                    stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=main_dir)
+    
+    # Deploy traefik stack
+    os.chdir("./traefik")
+    subprocess.call(["docker", "stack", "deploy", "-c", "./docker-compose.yml", "traefik"],
+                                            stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=".")
+    os.chdir(main_dir)
+
+    # Deploy individual species stacks
+    for sp in to_deploy_species_li:
+        os.chdir(sp)
+        subprocess.call(["docker", "stack", "deploy", "-c", "./docker-compose.yml", "{0}_{1}".format(sp.split("_")[0], sp.split("_")[1])],
+                                           stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=".")
+        logging.info("Deployed %s stack" % sp)
+        os.chdir(main_dir)
+
+    # Update traefik stack
+    os.chdir("./traefik")
+    subprocess.call(["docker", "stack", "deploy", "-c", "./docker-compose.yml", "traefik"],
+                                            stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=".")
+    os.chdir(main_dir)
+
+    # # Using deploy.sh script (obsolete)
+    # Launch and update docker stacks
+    # noinspection PyArgumentList
+    # deploy_stacks_popen = subprocess.Popen(["sh", self.script_dir + "/deploy.sh", self.genus_species,
+    #                                         self.main_dir + "/traefik"],
+    #                                        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+    #                                        universal_newlines=True)
+    #
+    # for stdout_line in iter(deploy_stacks_popen.stdout.readline, ""):
+    #     if "daemon" in stdout_line:  # Ignore swarm init error output
+    #         pass
+    #     else:
+    #         logging.info("\t%s" % stdout_line.strip())
+    # deploy_stacks_popen.stdout.close()
 
 
 if __name__ == "__main__":
@@ -332,9 +380,6 @@ if __name__ == "__main__":
         main_dir = os.path.abspath(args.main_directory)
 
     sp_dict_list = utilities.parse_input(os.path.abspath(args.input))
-    print(sp_dict_list)
-
-    utilities.get_species_to_deploy(sp_dict_list=sp_dict_list)
 
     logging.info("Deploying stacks for organisms in input file %s" % args.input)
     for sp_dict in sp_dict_list:
@@ -375,14 +420,6 @@ if __name__ == "__main__":
         deploy_stack_for_current_organism.make_compose_files(force=args.overwrite_all)
         logging.info("Successfully generated the docker-compose files for %s" % deploy_stack_for_current_organism.full_name)
 
-        # Deploy the stack
-        logging.info("Deploying stack for %s..." % deploy_stack_for_current_organism.full_name)
-        # deploy_stack_for_current_organism.deploy_stack()
-        logging.info("Successfully deployed stack for %s" % deploy_stack_for_current_organism.full_name)
-
-        logging.info("Stack deployed for %s" % deploy_stack_for_current_organism.full_name)
-
-        # TODO: if GENUS°1 == GENUS°2 AND SP°1 == SP°2 --> skip init, continue to next item and only deploy once the loop is done
-
-    # TODO: reload traefik outside loop
+    logging.info("Deploying stacks")
+    deploy_stacks(input_list=sp_dict_list, main_dir=main_dir)
     logging.info("All stacks deployed for organisms in input file %s" % args.input)
diff --git a/run_workflow_phaeoexplorer.py b/run_workflow_phaeoexplorer.py
index 97b10aa308aae777a84337aa0838e19acf96dec3..a67b7e70bb914eb26d6bf2d7e590a24819473a1d 100644
--- a/run_workflow_phaeoexplorer.py
+++ b/run_workflow_phaeoexplorer.py
@@ -183,11 +183,34 @@ class RunWorkflow(speciesData.SpeciesData):
                          "sourcename": "Genoscope",
                          "date_executed": self.date})
 
+        # Add Interpro analysis to chado 
+        self.instance.tools.run_tool(
+            tool_id="toolshed.g2.bx.psu.edu/repos/gga/chado_analysis_add_analysis/analysis_add_analysis/2.3.3",
+            history_id=self.history_id,
+            tool_inputs={"name": "InterproScan on OGS%s" % self.ogs_version,
+                         "program": "InterproScan",
+                         "programversion": "OGS%s" % self.ogs_version,
+                         "sourcename": "Genoscope",
+                         "date_executed": self.date})
+
+
+        # Add Blastp (diamond) analysis to chado 
+        self.instance.tools.run_tool(
+            tool_id="toolshed.g2.bx.psu.edu/repos/gga/chado_analysis_add_analysis/analysis_add_analysis/2.3.3",
+            history_id=self.history_id,
+            tool_inputs={"name": "Diamond on OGS%s" % self.ogs_version,
+                         "program": "Diamond",
+                         "programversion": "OGS%s" % self.ogs_version,
+                         "sourcename": "Genoscope",
+                         "date_executed": self.date})
+
+
         # Also get the organism and analyses IDs
         self.get_organism_and_analyses_ids()
 
         logging.info("Finished initializing instance")
 
+
     def run_workflow(self, workflow_path, workflow_parameters, workflow_name, datamap):
         """
         Run a workflow in galaxy
@@ -641,6 +664,23 @@ if __name__ == "__main__":
                                                                datamap=run_workflow_for_current_organism.datamap,
                                                                workflow_name="Jbrowse")
 
+            elif "Interpro" in str(workflow):
+
+                logging.info("Executing workflow 'Interproscan")
+
+                run_workflow_for_current_organism.connect_to_instance()
+                run_workflow_for_current_organism.set_get_history()
+                # run_workflow_for_current_organism.get_species_history_id()
+
+                # Get the attributes of the instance and project data files
+                run_workflow_for_current_organism.get_instance_attributes()
+                run_workflow_for_current_organism.get_organism_and_analyses_ids()
+
+                # Import datasets into history and retrieve their hda IDs
+                run_workflow_for_current_organism.import_datasets_into_history()
+                run_workflow_for_current_organism.get_datasets_hda_ids()
+
+
         else:
             logging.critical("The galaxy container for %s is not ready yet!" % run_workflow_for_current_organism.full_name)
             sys.exit()
diff --git a/speciesData.py b/speciesData.py
index 2539179ddc91bc7fab2a924a4842c28aef05fc97..db78196a11efa6080f192ade6c0ca42611841189 100644
--- a/speciesData.py
+++ b/speciesData.py
@@ -82,5 +82,3 @@ class SpeciesData:
         self.species_folder_name = "_".join(utilities.filter_empty_not_empty_items([self.genus_lowercase, self.species, self.strain, self.sex])["not_empty"])
         self.existing_folders_cache = {}
         self.bam_metadata_cache = {}
-        # self.do_update = False  # Update the instance (in histories corresponding to the input) instead of creating a new one
-        # self.species_name_regex_litteral = "(?=\w*V)(?=\w*A)(?=\w*R)(?=\w*I)(?=\w*A)(?=\w*B)(?=\w*L)(?=\w*E)\w+"  # Placeholder regex for file matching
diff --git a/utils/phaeoexplorer_ec32_orthologs_transfer.py b/utils/phaeoexplorer_ec32_orthologs_transfer.py
new file mode 100644
index 0000000000000000000000000000000000000000..20e6750c64fb27bfdfc1a27bcc3cd2985d4d1888
--- /dev/null
+++ b/utils/phaeoexplorer_ec32_orthologs_transfer.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+import argparse
+import pickle
+import logging
+
+def orthologs_transfer(manual_annotation_file, orthofinder_file, gff_file, outdir):
+    """
+    Transfer of description between a manual annotation file and a gff file, using an orthofinder output file
+    to find the corresponding IDs between the two files
+
+    :param manual_annotation_file:
+    :param orthofinder_file:
+    :param gff_file:
+    :param outdir:
+    :return:
+    """
+
+    manual_annotations_dict, orthofinder_dict, gff_dict = {}, {}, {}
+    species_filename = ""
+
+    with open(orthofinder_file, 'r') as orthofinder:
+        next(orthofinder)  # Skip header
+        # Mapping orthofinder's IDs to manual annotation's description  
+        logging.info("Mapping Orthofinder's IDs to manual annotation's IDs...")
+        for orthofiner_line in orthofinder:
+            orthofiner_line_split = orthofiner_line.rstrip().split("\t")
+            orthofinder_dict[orthofiner_line_split[1].split(" ")[0]] = orthofiner_line_split[2].split(" ")[0]
+    
+
+        with open(manual_annotation_file, 'r') as manual_annotation:
+            # Mapping orthofinder's IDs to manual annotation's description
+            logging.info("Mapping Orthofinder's IDs to descriptions...")
+            next(manual_annotation)  # Skip header
+            for manual_annotation_line in manual_annotation:
+                manual_annotation_line_split = manual_annotation_line.rstrip().split("\t")
+                manual_annotations_dict[manual_annotation_line_split[0]] = ";".join([manual_annotation_line_split[0], manual_annotation_line_split[6]])
+
+    # Opening GFF, appending manual annotation's description to matching IDs
+    logging.info("Transferring manual descriptions to the GFF file...")
+    output_filename = str(os.path.join(os.path.abspath(outdir), os.path.basename(gff_file).split(".")[0]) + "_TRANSFERED.gff")
+
+    with open(output_filename, 'a') as output_file:
+        output_file.truncate(0)  # Erase previous file content
+        with open(gff_file, 'r') as gff:
+            for gff_line in gff:
+                if "ID=mRNA" in gff_line:  # Look for mRNA items
+                    gff_line_id = gff_line.split("\t")[8].split("=")[1].split(";")[0]  # GFF file ID (matches manual annotation IDs)
+                    if gff_line_id in orthofinder_dict.keys():  # The gff ID is supposed to match a unique ID (key) in the orthofinder file
+                        try:
+                            manual_annotation_value = orthofinder_dict[gff_line_id]  # Find the corresponding manual annotation to transfer
+                            gff_line = "{0};ec32_ortholog={1};ec32_ortholog_description={2}\n".format(gff_line.strip(), orthofinder_dict[gff_line_id], manual_annotation_value)
+                        except KeyError:  # Just in case some values are missing in the manual annotation file (optional, can be removed, it will then exit instead)
+                            continue
+                output_file.write(gff_line)
+            logging.info("Finished transferring descriptions for %s" % str(os.path.basename(gff_file)))
+
+
+if __name__ == "__main__":
+
+    parser = argparse.ArgumentParser(description="Orthologs_transfer between a reference manual annotation and Orthofinder outputs. \
+                                                  \n\nRun example: python3 ec32_orthologs_transfer.py -d /path/to/desired/dir/ -o orthofinder_file.tsv \
+                                                  -g gff_file.gff -m manual_annotation_file.txt")
+    parser.add_argument("-o", "--orthofinder",
+                        help="Orthofinder output (tabulated)")
+    parser.add_argument("-m", "--manual-annotation",
+                        help="Manual annotation file (tabulated) or pickle file containing the dicionary (automatically generated when you input a new manual annotation file)")
+    parser.add_argument("-g", "--gff",
+                        help="GFF input file (tabulated)")
+    parser.add_argument("-d", "--out-dir",
+                        help="Output directory")
+    args = parser.parse_args()
+
+    # WARNING for shell use case:  
+    # The script doesn't check if the inout files are valid. 
+    # Files must be put in this order: $1=orthofinder file, $2=manual annotation file, $3=GFF file, $4=optional output directory)
+
+    if not args.manual_annotation:
+        logging.info("Please input a manual annotation file or a pickled manual annotation dictionary")
+        sys.exit()
+    if not args.orthofinder:
+        logging.info("Please input an orthofinder output file")
+        sys.exit()
+    if not args.gff:
+        logging.info("Please input a gff file")
+        sys.exit()
+    if not args.out_dir:
+        args.out = "."
+
+    orthologs_transfer(manual_annotation_file=args.manual_annotation,
+                       orthofinder_file=args.orthofinder,
+                       gff_file=args.gff,
+                       outdir=args.out_dir)
diff --git a/utils/phaeoexplorer_hectar_transfer.py b/utils/phaeoexplorer_hectar_transfer.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec9a62d90cf602420ceb1e0610229d7d97bf859f
--- /dev/null
+++ b/utils/phaeoexplorer_hectar_transfer.py
@@ -0,0 +1,95 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+import argparse
+import logging
+
+def hectar_transfer(hectar_file, orthofinder_file, gff_file, outdir):
+    """
+    Transfer of description between a manual annotation file and a gff file, using an orthofinder output file
+    to find the corresponding IDs between the two files
+
+    :param hectar_file:
+    :param orthofinder_file:
+    :param gff_file:
+    :param outdir:
+    :return:
+    """
+
+    manual_annotations_dict, orthofinder_dict, gff_dict = {}, {}, {}
+    species_filename = ""
+
+    with open(orthofinder_file, 'r') as orthofinder:
+        next(orthofinder)  # Skip header
+        # Mapping orthofinder's IDs to hectar IDs  
+        logging.info("Mapping Orthofinder's IDs to hectar IDs...")
+        for orthofiner_line in orthofinder:
+            orthofiner_line_split = orthofiner_line.rstrip().split("\t")
+            orthofinder_dict[orthofiner_line_split[1].split(" ")[0]] = orthofiner_line_split[2].split(" ")[0]
+        
+        hectar_dict = {}
+        with open(hectar_file, 'r') as hectar:
+            # Mapping orthofinder's IDs to hectar description
+            logging.info("Mapping Orthofinder's IDs to descriptions...")
+            next(hectar)  # Skip header
+            for hectar_line in hectar:
+                hectar_line_split = hectar_line.rstrip().split("\t")
+                hectar_dict[hectar_line_split[0].split(" ")[0]] = hectar_line_split[1]
+
+    # Opening GFF, appending hectar description to matching IDs
+    logging.info("Transferring manual descriptions to the GFF file...")
+    output_filename = str(os.path.join(os.path.abspath(outdir), os.path.basename(gff_file).split(".")[0]) + "_TRANSFERED_HECTAR.gff")
+
+    with open(output_filename, 'a') as output_file:
+        output_file.truncate(0)  # Erase previous file content
+        with open(gff_file, 'r') as gff:
+            for gff_line in gff:
+                if "ID=mRNA" in gff_line:  # Look for mRNA items
+                    gff_line_id = gff_line.split("\t")[8].split("=")[1].split(";")[0]  # GFF file ID (matches hectar IDs)
+                    if gff_line_id in hectar_dict.keys():  # The gff ID is supposed to match a unique ID (key) in the orthofinder file
+                        try:
+                            hectar_value = hectar_dict[gff_line_id]  # Find the corresponding manual annotation to transfer
+                            gff_line = "{0};HECTAR_predicted_targeting_category={1}\n".format(gff_line.strip(), hectar_value)
+                        except KeyError:  # Just in case some values are missing in the hectar file (If removed it will then exit instead)
+                            continue
+                output_file.write(gff_line)
+            logging.info("Finished transferring descriptions for %s" % str(os.path.basename(gff_file)))
+
+
+if __name__ == "__main__":
+
+    parser = argparse.ArgumentParser(description="Orthologs_transfer between a reference manual annotation and Orthofinder outputs. \
+                                                  \n\nRun example: python3 ec32_orthologs_transfer.py -d /path/to/desired/dir/ -h hectar_file.tsv \
+                                                  -g gff_file.gff -m manual_annotation_file.txt")
+    parser.add_argument("-i", "--hectar",
+                        help="Hectar output (tabulated)")
+    parser.add_argument("-o", "--orthofinder",
+                        help="Manual annotation file (tabulated) or pickle file containing the dicionary (automatically generated when you input a new manual annotation file)")
+    parser.add_argument("-g", "--gff",
+                        help="GFF input file (tabulated)")
+    parser.add_argument("-d", "--out-dir",
+                        help="Output directory")
+    args = parser.parse_args()
+
+    # WARNING for shell use case:  
+    # The script doesn't check if the inout files are valid. 
+    # Files must be put in this order: $1=orthofinder file, $2=manual annotation file, $3=GFF file, $4=optional output directory)
+
+    if not args.hectar:
+        logging.info("Please input a hectar file")
+        sys.exit()
+    if not args.orthofinder:
+        logging.info("Please input a hectar output file")
+        sys.exit()
+    if not args.gff:
+        logging.info("Please input a gff file")
+        sys.exit()
+    if not args.out_dir:
+        args.out = "."
+
+    hectar_transfer(hectar_file=args.hectar,
+                       orthofinder_file=args.orthofinder,
+                       gff_file=args.gff,
+                       outdir=args.out_dir)