diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5b52e112d56e80b2398f6945138897bb80dbc414
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,139 @@
+### Java template
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+### VisualStudioCode template
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+.idea/
+
+ *.iml
+ *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Eclipse template
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# CDT- autotools
+.autotools
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# Annotation Processing
+.apt_generated/
+.apt_generated_test/
+
+# Scala IDE specific (Scala & Java development for Eclipse)
+.cache-main
+.scala_dependencies
+.worksheet
+
+# Uncomment this line if you wish to ignore the project description file.
+# Typically, this file would be tracked if it contains build/dependency configurations:
+#.project
+
diff --git a/README.md b/README.md
index c50eeb46f521ffb44454a9d86e00667cd4d8e436..f9c4162cd1ae6075b34bd3d962ca30662b8e6f71 100644
--- a/README.md
+++ b/README.md
@@ -17,11 +17,11 @@ Jep embeds CPython in Java through JNI.
 Some benefits of embedding CPython in a JVM:
 
    * Using the native Python interpreter may be much faster than alternatives.
-   * Python is mature, well supported, and well documented.
+   * Python is mature, well-supported, and well documented.
    * Access to high quality Python modules, both native CPython extensions and Python-based.
    * Compilers and assorted Python tools are as mature as the language.
    * Python is an interpreted language, enabling scripting of established Java code without requiring recompilation.
-   * Both Java and Python are cross platform, enabling deployment to different operating systems.
+   * Both Java and Python are cross-platform, enabling deployment to different operating systems.
 
 ## Installation instructions
 
@@ -76,4 +76,66 @@ http://icy.bioimageanalysis.org
 Nate Jensen & Ben Steffensmeier
 
 *Plugin conversion*
-Amandine Tournay
\ No newline at end of file
+Amandine Tournay
+
+# Note
+
+Until JEP 4.0.3, for Linux users, you need to set temporarily the environment variable `LD_PRELOAD` to your `libpythonx.xx.so` file.  
+It is due to some difficulties with Java and C projects that dlopen libraries.  
+***It has been fixed for the next version planned for Fall 2022.***
+
+# Utility functions
+
+```java
+import jep.JepConfig;
+import jep.SubInterpreter;
+import plugins.atournay.jep.JepUtils;
+import plugins.atournay.jep.PythonUtils;
+import plugins.atournay.jep.JepPlugin;
+
+public class Test() {
+    public static void main(String[] args) {
+        // Check if a String is a system path
+        JepPlugin.getInstance().isPath("<path>");
+
+        // Get a list of Conda environments with their full path
+        PythonUtils.getInstance().detectCondaEnvironments();
+
+        // Get a list of only conda environment names
+        PythonUtils.getInstance().getCondaEnvNames();
+
+        // Find the Python execution file by the root directory of Python or check the full path if it is given
+        PythonUtils.getInstance().findPythonExecutable("<path>", Boolean.TRUE || Boolean.FALSE);
+
+        // Retrieve the site-packages directory from the selected Python
+        PythonUtils.getInstance().setSitePackagesDirectory("<Python path>");
+
+        // Retrieve the running JEP file from the site-packages directory of the selected Python
+        JepUtils.getInstance().findJepLib("<site-packages path>");
+
+        // Instantiate JEP
+        JepUtils.getInstance().setJepPath("<JEP path>", "<Python root path>");
+
+        // Open a Python instance (to use with a try-catch(JepException)
+        SubInterpreter python = JepUtils.getInstance().openSubPython();
+        // Same but adding a JEP configuration object to manage better the link between Java and Python (see JavaDoc)
+        SubInterpreter python2 = JepUtils.getInstance().openSubPython(new JepConfig());
+
+        // Running some Python code
+        python2.exec("x = 5");
+        python2.runScript("<Python script file path>");
+        // Prints 5
+        System.out.println(python2.getValue("x"));
+        
+        // Send data to Python
+        python2.set("y", 10);
+        // Prints 10 on the Python output stream
+        python2.exec("print(y)");
+        
+        // Close a Python instance
+        JepUtils.getInstance().closeSubPython(python);
+        // Always close an opened instance !
+        JepUtils.getInstance().closeSubPython(python2);
+    }
+}
+```
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 0af994b1a269ed2829c887447a1f958fa898f4a5..232859d8ac27e777638d63a52ffa89b1d6cd7b4a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,7 +39,6 @@
         <developer>
             <id>ndjensen</id>
             <name>Nate Jensen</name>
-            <url>https://mywebpage.net</url>
             <roles>
                 <role>founder</role>
                 <role>lead</role>
@@ -60,6 +59,14 @@
                 <role>support</role>
             </roles>
         </developer>
+        <developer>
+            <id>atournay</id>
+            <name>Amandine Tournay</name>
+            <url>https://research.pasteur.fr/fr/member/amandine-tournay/</url>
+            <roles>
+                <role>contributor</role>
+            </roles>
+        </developer>
     </developers>
 
     <!-- Project properties -->
diff --git a/src/main/java/plugins/atournay/jep/CustomClassEnquirer.java b/src/main/java/plugins/atournay/jep/CustomClassEnquirer.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0f2ef10c96edffc8e8f43310ec24e891d6294d0
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/CustomClassEnquirer.java
@@ -0,0 +1,36 @@
+package plugins.atournay.jep;
+
+import jep.ClassEnquirer;
+import jep.ClassList;
+
+/**
+ * Class to override the management of the default class loader configuration.
+ * Jep scans the Java classpath to be able to import those classes in Python.
+ * But, if a library or a class is available on both sides AND if the path is the same, it will create a conflict.
+ * To prevent this, we can choose which one to load.
+ *
+ * @author Amandine Tournay
+ */
+public class CustomClassEnquirer implements ClassEnquirer {
+    /**
+     * Verification of a scanned package and confirm if it is a package from Java.
+     * In case of conflict, and we want to load only the Python version of it, it is possible to force to return false.
+     *
+     * @param name Name of the package
+     * @return True if it corresponds to a package from Java
+     */
+    @Override
+    public boolean isJavaPackage(String name) {
+        return !(name.equals("tensorflow")) && ClassList.getInstance().isJavaPackage(name);
+    }
+
+    @Override
+    public String[] getClassNames(String packageName) {
+        return ClassList.getInstance().getClassNames(packageName);
+    }
+
+    @Override
+    public String[] getSubPackages(String packageName) {
+        return ClassList.getInstance().getSubPackages(packageName);
+    }
+}
diff --git a/src/main/java/plugins/atournay/jep/JepPlugin.java b/src/main/java/plugins/atournay/jep/JepPlugin.java
index 7ff14128c19580c121bf456113338b561943b3a9..143506fedfead7b6f6f2080c0bec47cbc34b528c 100644
--- a/src/main/java/plugins/atournay/jep/JepPlugin.java
+++ b/src/main/java/plugins/atournay/jep/JepPlugin.java
@@ -1,7 +1,38 @@
 package plugins.atournay.jep;
 
+import com.drew.lang.annotations.NotNull;
 import icy.plugin.abstract_.Plugin;
 import icy.plugin.interface_.PluginLibrary;
 
+import java.util.regex.Pattern;
+
 public class JepPlugin extends Plugin implements PluginLibrary {
+    private static JepPlugin instance;
+
+
+    private JepPlugin() {
+    }
+
+    public static JepPlugin getInstance() {
+        if (instance == null) {
+            instance = new JepPlugin();
+        }
+
+        return instance;
+    }
+
+    /**
+     * @param path The path to test
+     * @return The result if the String is really a path (compatible Windows, MacOS &amp; Linux)
+     */
+    public boolean isPath(@NotNull String path) {
+        if (Pattern.compile("([A-Za-z]:|[/\\\\])+.(\\w)+.*").matcher(path).find()) {
+            return true;
+        }
+        else {
+            System.err.println("The input does not correspond to a System path. Please retry.");
+            System.out.println();
+            return false;
+        }
+    }
 }
diff --git a/src/main/java/plugins/atournay/jep/JepUtils.java b/src/main/java/plugins/atournay/jep/JepUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..7cb443b6c4c2055bbbe3c7dba4d40183ee0327e6
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/JepUtils.java
@@ -0,0 +1,139 @@
+package plugins.atournay.jep;
+
+import com.drew.lang.annotations.NotNull;
+import jep.*;
+
+import java.io.File;
+
+/**
+ * Utility functions to configure JEP
+ *
+ * @author Amandine Tournay
+ */
+public class JepUtils {
+    private static JepUtils instance;
+    private JepConfig jepConfig;
+    private Interpreter jepInterpreter;
+
+    private JepUtils() {
+    }
+
+    public static JepUtils getInstance() {
+        if (instance == null) {
+            instance = new JepUtils();
+        }
+
+        return instance;
+    }
+
+    /**
+     * @param sitePackagesPath Path to the site-packages directory
+     * @return Path to JEP
+     */
+    public String findJepLib(@NotNull String sitePackagesPath) {
+        String jetPath = "";
+        File jepDir = new File(sitePackagesPath, "jep");
+
+        if (!jepDir.isDirectory()) {
+            System.err.println("JEP could not be found. Please check if you have installed JEP before.");
+            System.out.println();
+            return null;
+        }
+        else {
+            String[] libFiles = {"libjep.so", "libjep.jnilib", "jep.ddl"};
+
+            for (String libFile : libFiles) {
+                File lib = new File(jepDir, libFile);
+
+                if (lib.isFile()) jetPath = lib.getAbsolutePath();
+            }
+        }
+
+        return jetPath;
+    }
+
+    /**
+     * Set the path of the JEP library either the OS
+     *
+     * @param jepPath    Path the JEP execution file (libjep.(so|jnilib|ddl))
+     * @param pythonRoot Path to the Python root directory
+     */
+    public void setJepPath(@NotNull String jepPath, @NotNull String pythonRoot) throws JepException {
+        setJepConfig(new JepConfig());
+
+        getJepConfig().setClassEnquirer(new CustomClassEnquirer());
+
+        if (jepPath.matches(".*conda.*|.*venv")) {
+            PyConfig pyConfig = new PyConfig();
+            pyConfig.setPythonHome(pythonRoot);
+
+            MainInterpreter.setInitParams(pyConfig);
+        }
+
+        SharedInterpreter.setConfig(getJepConfig());
+        MainInterpreter.setJepLibraryPath(jepPath);
+    }
+
+    /**
+     * Open global Python instance (<b>ONLY ONE PER JVM !!!</b>)
+     * <b>THIS FUNCTION IS NOT RECOMMENDED</b>
+     */
+    public void openPython() {
+        setJepInterpreter(new SharedInterpreter());
+    }
+
+    /**
+     * Close global Python instance
+     * <b>THIS FUNCTION IS NOT RECOMMENDED AS IT IS FOR THE GLOBAL INTERPRETER</b>
+     * {@see plugins.atournay.jep.JepUtils#closePython()}
+     */
+    public void closePython() {
+        getJepInterpreter().close();
+    }
+
+    /**
+     * Create a new Python instance
+     *
+     * @return Python interpreter to execute some Python commands, retrieve values, etc...
+     */
+    public SubInterpreter openSubPython() {
+        return openSubPython(new JepConfig());
+    }
+
+    /**
+     * Create a new Python instance
+     *
+     * @param jepConfig JEP configurations {@see jep.JepConfig} and example at {@see plugins.atournay.jep.CustomClassEnquirer}
+     * @return Python interpreter to execute some Python commands, retrieve values, etc...
+     */
+    public SubInterpreter openSubPython(@NotNull JepConfig jepConfig) {
+        return new SubInterpreter(jepConfig);
+    }
+
+    /**
+     * Close a running Python sub interpreter
+     *
+     * @param subInterpreter Running Python instance
+     */
+    public void closeSubPython(SubInterpreter subInterpreter) {
+        subInterpreter.close();
+    }
+
+    // GETTERS - SETTERS
+
+    public JepConfig getJepConfig() {
+        return jepConfig;
+    }
+
+    private void setJepConfig(@NotNull JepConfig newJepConfig) {
+        this.jepConfig = newJepConfig;
+    }
+
+    public Interpreter getJepInterpreter() {
+        return jepInterpreter;
+    }
+
+    private void setJepInterpreter(@NotNull Interpreter jepInterpreter) {
+        this.jepInterpreter = jepInterpreter;
+    }
+}
diff --git a/src/main/java/plugins/atournay/jep/PythonUtils.java b/src/main/java/plugins/atournay/jep/PythonUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..b355c017561ffe47b47bd644a869629382b3f3b5
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/PythonUtils.java
@@ -0,0 +1,150 @@
+package plugins.atournay.jep;
+
+import com.drew.lang.annotations.NotNull;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class PythonUtils {
+    private static PythonUtils instance;
+
+    private PythonUtils() {
+    }
+
+    public static PythonUtils getInstance() {
+        if (instance == null) {
+            instance = new PythonUtils();
+        }
+
+        return instance;
+    }
+
+    /**
+     * List all Conda environments available on the computers
+     *
+     * @return List of conda environments (Key = Name of environment; Value = Path of the environment)
+     */
+    public HashMap<String, String> detectCondaEnvironments() {
+        HashMap<String, String> condaEnvs = new HashMap<>();
+        String[] cmd = new String[]{"conda", "env", "list"};
+
+        try {
+            Process process = new ProcessBuilder(cmd).start();
+
+            BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+            Pattern pattern = Pattern.compile("#|([^.A-z]conda)|(environments:)|\\*| ");
+
+            List<String> stdOutStr = stdOut.lines().flatMap(pattern::splitAsStream)
+                    .collect(Collectors.toList())
+                    .stream().filter(e -> !e.equals("")).collect(Collectors.toList());
+
+            for (int i = 0; i < stdOutStr.size(); i += 2) {
+                condaEnvs.put(stdOutStr.get(i), stdOutStr.get(i + 1));
+            }
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return condaEnvs;
+    }
+
+    /**
+     * Get Conda environment names available on the computer
+     *
+     * @return List of all Conda environment names
+     */
+    public Set<String> getCondaEnvNames() {
+        return detectCondaEnvironments().keySet();
+    }
+
+    /**
+     * The Python executable file in Windows is python.exe and in Unix systems /python (which can be linked to a specific version file)
+     *
+     * @param path The path to a directory where the Python executable must be found
+     * @param isDirectory Set if the path is ending by a directory (true) or a file (false)
+     * @return The full path of the Python execution file
+     */
+    public String findPythonExecutable(@NotNull String path, @NotNull boolean isDirectory) {
+        if (isDirectory) {
+            File[] pythonFiles = new File(path).listFiles((file, name) -> name.equals("bin") && file.isDirectory());
+
+            if (pythonFiles != null) {
+                for (File binDirectory : pythonFiles) {
+                    File[] binFiles = binDirectory.listFiles((file, name) -> name.matches("python?(?:\\.exe|$)"));
+
+                    if (binFiles != null) {
+                        return Arrays.stream(binFiles).findFirst().map(File::getAbsolutePath).orElse(null);
+                    }
+                }
+            }
+
+            return null;
+        }
+        else {
+            if (Files.exists(Paths.get(path))) {
+                return path;
+            }
+            else {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * @param pythonExecutionPath Path to the Python home directory
+     * @return The path to the site-packages directory
+     */
+    public String setSitePackagesDirectory(@NotNull String pythonExecutionPath) {
+        String terminalLine;
+        String[] command = new String[]{pythonExecutionPath, "-c", "import sys; print([p for p in sys.path if p.endswith(\"site-packages\")])"};
+        String sitePackagesPath = "";
+
+        try {
+            // Execute terminal command to find the site-packages directory
+            Process process = Runtime.getRuntime().exec(command);
+
+            BufferedReader streamInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            BufferedReader streamError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+
+            // Execution result stream output
+            while ((terminalLine = streamInput.readLine()) != null) {
+                String[] spList = terminalLine.replaceAll("[\\[\\]' ]", "").split(",");
+
+                /*
+                    With classical Python interpreter (non-isolated environment like Venv and Conda with its consorts), there can be multiple site-packages folder.
+                    So, we must find which one has JEP inside
+                 */
+                for (String spPath : spList) {
+                    String isThereJEP = JepUtils.getInstance().findJepLib(spPath);
+
+                    if (isThereJEP != null) {
+                        sitePackagesPath = spPath;
+                        break;
+                    }
+                }
+            }
+
+            // Error stream output
+            while ((terminalLine = streamError.readLine()) != null) {
+                System.err.println(terminalLine);
+            }
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return sitePackagesPath;
+    }
+}