diff --git a/README.md b/README.md
index f9c4162cd1ae6075b34bd3d962ca30662b8e6f71..da6405618f113e288abc612d0319b3afef3853ee 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@ http://icy.bioimageanalysis.org
 Nate Jensen & Ben Steffensmeier
 
 *Plugin conversion*
-Amandine Tournay
+Amandine Tournay & Carlos Garcia Lopez de Haro
 
 # Note
 
@@ -84,58 +84,66 @@ Until JEP 4.0.3, for Linux users, you need to set temporarily the environment va
 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.***
 
+# Usage
+
+To enable this plugin in Icy, you need to configure the path to your selected Python.
+Go in the search bar and search for Python3Preferences.
+
+![Search JEP](src/main/resources/readMePictures/Python%20-%20search.png)
+
+<!-- TODO: Add capture of JEP Button in the tool tab of Icy -->
+
+If you are a user of Conda, you select one of the environments available:
+![JEP settings - Conda](src/main/resources/readMePictures/Python%20-%20set%20with%20Conda.png)
+
+Or if you are a user of a classical Python installation or if you are using a Virtual environment, you can select the home directory 
+of your Python:
+![JEP settings - Custom Python](src/main/resources/readMePictures/Python%20-%20set%20with%20custom%20path.png)
+
+**There you are !**
+Click on apply or save, and you are ready to use Python in Icy !
+
 # Utility functions
 
+**Reminder**: When you open a new Python instance, do NOT FORGET to close when you are done ! :D
+
 ```java
+import icy.system.IcyExceptionHandler;
 import jep.JepConfig;
+import jep.JepException;
 import jep.SubInterpreter;
-import plugins.atournay.jep.JepUtils;
-import plugins.atournay.jep.PythonUtils;
+import plugins.atournay.jep.exec.PythonExec;
+import plugins.atournay.jep.utils.JepUtils;
+import plugins.atournay.jep.utils.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);
+        try {
+            // Open a Python instance
+            SubInterpreter python = new PythonExec().getInterpreter();
+            // Same but adding a JEP configuration object to manage better the link between Java and Python (see JavaDoc)
+            SubInterpreter python2 = new PythonExec(new JepConfig()).getInterpreter();
+
+            // 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
+            python.close();
+            // Always close an opened instance !
+            python2.close();
+        }
+        catch (JepException e) {
+            IcyExceptionHandler.showErrorMessage(new JepException(e), true, true);
+        }
     }
 }
 ```
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 7a162b52b01af2eab463f96b270b2faa13b603c6..4d4c165fd3850ed4eab70a4bd1ef5af50e5f07bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,10 +6,10 @@
 
     <!-- Inherited Icy Parent POM -->
     <parent>
-		<artifactId>pom-icy</artifactId>
+        <artifactId>pom-icy</artifactId>
         <groupId>org.bioimageanalysis.icy</groupId>
-        <version>2.0.0</version>
-	</parent>
+        <version>2.1.0</version>
+    </parent>
 
     <!-- Project Information -->
     <artifactId>icy-jep</artifactId>
@@ -17,7 +17,7 @@
 
     <packaging>jar</packaging>
 
-    <name>JEP - Java Embedded Python fot Icy</name>
+    <name>JEP - Java Embedded Python for Icy</name>
     <description>Jep embeds CPython in Java through JNI. Fork to include the library in Icy.</description>
     <url>https://icy.bioimageanalysis.org/plugin/jep-java-embedded-python/</url>
     <inceptionYear>2022</inceptionYear>
@@ -74,15 +74,6 @@
         <artifact-to-include>jep</artifact-to-include>
     </properties>
 
-    <profiles>
-        <profile>
-            <id>icy-plugin-extract-library</id>
-            <activation>
-                <activeByDefault>true</activeByDefault>
-            </activation>
-        </profile>
-    </profiles>
-
     <!-- List of project's dependencies -->
     <dependencies>
         <dependency>
diff --git a/src/main/java/plugins/atournay/jep/JepPlugin.java b/src/main/java/plugins/atournay/jep/JepPlugin.java
index e4e08f4e60bf8a71d2dbb7ebe0d3556cce174d3a..afce2fce7eee66489a9cecba39a7b0ba68c3dac9 100644
--- a/src/main/java/plugins/atournay/jep/JepPlugin.java
+++ b/src/main/java/plugins/atournay/jep/JepPlugin.java
@@ -1,15 +1,16 @@
 package plugins.atournay.jep;
 
 import icy.plugin.abstract_.Plugin;
+import icy.plugin.interface_.PluginDaemon;
 import icy.plugin.interface_.PluginLibrary;
+import plugins.atournay.jep.prefs.JepPreferences;
+import plugins.atournay.jep.utils.JepUtils;
 
-import java.util.regex.Pattern;
-
-public class JepPlugin extends Plugin implements PluginLibrary {
+public class JepPlugin extends Plugin implements PluginLibrary, PluginDaemon {
     private static JepPlugin instance;
 
 
-    private JepPlugin() {
+    public JepPlugin() {
     }
 
     public static JepPlugin getInstance() {
@@ -20,18 +21,18 @@ public class JepPlugin extends Plugin implements PluginLibrary {
         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(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;
+    @Override
+    public void init() {
+        if (!JepPreferences.getInstance().getJepPath().isEmpty()) {
+            JepUtils.getInstance().setJepPath(JepPreferences.getInstance().getJepPath(), JepPreferences.getInstance().getPythonRoot());
         }
     }
+
+    @Override
+    public void run() {
+    }
+
+    @Override
+    public void stop() {
+    }
 }
diff --git a/src/main/java/plugins/atournay/jep/PythonUtils.java b/src/main/java/plugins/atournay/jep/PythonUtils.java
deleted file mode 100644
index 476a1493211fe398a578b01b7938b6d82709857e..0000000000000000000000000000000000000000
--- a/src/main/java/plugins/atournay/jep/PythonUtils.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package plugins.atournay.jep;
-
-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(String path, 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(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;
-    }
-}
diff --git a/src/main/java/plugins/atournay/jep/CustomClassEnquirer.java b/src/main/java/plugins/atournay/jep/exec/DefaultClassEnquirer.java
similarity index 92%
rename from src/main/java/plugins/atournay/jep/CustomClassEnquirer.java
rename to src/main/java/plugins/atournay/jep/exec/DefaultClassEnquirer.java
index b0f2ef10c96edffc8e8f43310ec24e891d6294d0..aeecf80f1637d304d0a28d1615f01a01f2dd39d3 100644
--- a/src/main/java/plugins/atournay/jep/CustomClassEnquirer.java
+++ b/src/main/java/plugins/atournay/jep/exec/DefaultClassEnquirer.java
@@ -1,4 +1,4 @@
-package plugins.atournay.jep;
+package plugins.atournay.jep.exec;
 
 import jep.ClassEnquirer;
 import jep.ClassList;
@@ -11,7 +11,7 @@ import jep.ClassList;
  *
  * @author Amandine Tournay
  */
-public class CustomClassEnquirer implements ClassEnquirer {
+public class DefaultClassEnquirer 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.
diff --git a/src/main/java/plugins/atournay/jep/exec/PythonExec.java b/src/main/java/plugins/atournay/jep/exec/PythonExec.java
new file mode 100644
index 0000000000000000000000000000000000000000..c359815baf5364a797ec6695153de3043a0c17b1
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/exec/PythonExec.java
@@ -0,0 +1,80 @@
+package plugins.atournay.jep.exec;
+
+import icy.system.IcyExceptionHandler;
+import jep.JepConfig;
+import jep.JepException;
+import jep.SubInterpreter;
+
+import java.io.Closeable;
+
+/**
+ * Class that wraps a Python JEP {@see jep.SubInterpreter} instance. An object of this class returns the interpreter that can be used to call Python code.
+ * This class also contains some methods that call Python code to carry out different tasks such as installing modules from Python
+ *
+ * @author Carlos Garcia Lopez de Haro
+ * @author Amandine Tournay
+ */
+public class PythonExec implements Closeable {
+    private SubInterpreter interpreter;
+    private JepConfig config;
+
+    /**
+     * Open a new instance of JEP to consume Python code or scripts
+     */
+    public PythonExec() {
+        config = new JepConfig();
+        config.setClassEnquirer(new DefaultClassEnquirer());
+
+        try {
+            interpreter = new SubInterpreter(config);
+        }
+        catch (JepException e) {
+            IcyExceptionHandler.showErrorMessage(new JepException(e), true, true);
+        }
+    }
+
+    /**
+     * Opens a new instance of JEP to consume Python code or scripts with a custom configuration
+     * @param customConfig Override JEP configuration
+     */
+    public PythonExec(JepConfig customConfig) {
+        config = customConfig;
+        interpreter = new SubInterpreter(config);
+    }
+
+    /**
+     * Installation of Python packages with the <code>pip install</code> command through Python
+     *
+     * @param packages Name of the packages to install through pip.
+     *                 It can be either the package name (i.e. numpy) or a specific version of a package (i.e. numpy==1.23.1) separated by a space
+     * @see plugins.atournay.jep.utils.PythonUtils#installPythonPackage(String) to install packages through the terminal
+     */
+    public void installPythonPackage(String packages) {
+        String command = "try:" + System.lineSeparator();
+        command += "\tfrom pip import main as pipmain" + System.lineSeparator();
+        command += "except:" + System.lineSeparator();
+        command += "\tfrom pip._internal.main import main as pipmain" + System.lineSeparator();
+        command += "pipmain(['install', '" + packages + "'])" + System.lineSeparator();
+
+        interpreter.exec(command);
+    }
+
+    public SubInterpreter getInterpreter() {
+        return interpreter;
+    }
+
+    public JepConfig getConfig() {
+        return config;
+    }
+
+    /**
+     * Close the current running instance of Python
+     * <b>To reopen a new one, instantiate a new PythonExec class</b>
+     */
+    @Override
+    public void close() {
+        if (interpreter != null) {
+            interpreter.close();
+        }
+    }
+}
diff --git a/src/main/java/plugins/atournay/jep/prefs/JepPreferences.java b/src/main/java/plugins/atournay/jep/prefs/JepPreferences.java
new file mode 100644
index 0000000000000000000000000000000000000000..6cae41188f8701eec03a0df484a87a6f7e06d990
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/prefs/JepPreferences.java
@@ -0,0 +1,96 @@
+package plugins.atournay.jep.prefs;
+
+import icy.preferences.PluginPreferences;
+import icy.preferences.XMLPreferences;
+import plugins.atournay.jep.ui.Python3Preferences;
+
+/**
+ * Class managing all Python preferences for Icy
+ * @see Python3Preferences for UI
+ * @author Amandine Tournay
+ */
+public class JepPreferences {
+    private static JepPreferences instance;
+    private static final String PREF_ID = "python3";
+    private static final String PYTHON_ROOT = "pythonRoot";
+    private static final String PYTHON_EXEC = "pythonExec";
+    private static final String JEP_PATH = "jepPath";
+
+    /*
+     * Preference Node to encapsulate Python 3 settings
+     */
+    private static XMLPreferences prefPython;
+
+    private JepPreferences() {
+        load();
+    }
+
+    public static JepPreferences getInstance() {
+        if (instance == null) {
+            instance = new JepPreferences();
+        }
+
+        return instance;
+    }
+
+    /**
+     * Load preferences for Python 3 in Icy settings
+     */
+    public void load() {
+        prefPython = PluginPreferences.getPreferences().node(PREF_ID);
+    }
+
+    /**
+     * Retrieve all preferences related to Python
+     * @return Preferences from Python Node
+     */
+    public XMLPreferences getPythonPreferences() {
+        return prefPython;
+    }
+
+    /**
+     * Retrieve from Python Node preferences the Python root path
+     * @return Full path to Python home directory
+     */
+    public String getPythonRoot() {
+        return getPythonPreferences().get(PYTHON_ROOT, "");
+    }
+    /**
+     * Set to the Python Node preferences the path to Python
+     * @param path Full path to the Python home directory
+     */
+    public void setPythonRoot(String path) {
+        getPythonPreferences().put(PYTHON_ROOT, path);
+    }
+
+    /**
+     * Retrieve from Python Node preferences the path to the Python executable file
+     * @return Full path to Python executable file
+     */
+    public String getPythonExecPath() {
+        return getPythonPreferences().get(PYTHON_EXEC, "");
+    }
+
+    /**
+     * Set to the Python Node preferences the path to the Python executable file
+     * @param path Full path to the Python executable file
+     */
+    public void setPythonExecPath(String path) {
+        getPythonPreferences().put(PYTHON_EXEC, path);
+    }
+
+    /**
+     * Retrieve from Python Node preferences the path to the JEP file (libjep)
+     * @return Full path to JEP library file
+     */
+    public String getJepPath() {
+        return getPythonPreferences().get(JEP_PATH, "");
+    }
+    /**
+     * Set to the Python Node preferences the path to the JEP file
+     * @param path Full path to JEP library file (libjep)
+     */
+    public void setJepPath(String path) {
+        getPythonPreferences().put(JEP_PATH, path);
+    }
+}
diff --git a/src/main/java/plugins/atournay/jep/ui/JepPreferencesWindow.java b/src/main/java/plugins/atournay/jep/ui/JepPreferencesWindow.java
new file mode 100644
index 0000000000000000000000000000000000000000..8456cb713366b0c836123de3dd6cc622ec2a1801
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/ui/JepPreferencesWindow.java
@@ -0,0 +1,351 @@
+package plugins.atournay.jep.ui;
+
+import icy.gui.component.IcyTextField;
+import icy.gui.dialog.MessageDialog;
+import icy.gui.frame.IcyFrame;
+import plugins.atournay.jep.prefs.JepPreferences;
+import plugins.atournay.jep.utils.JepUtils;
+import plugins.atournay.jep.utils.PythonUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Class to create a new window in Icy to set JEP
+ *
+ * @author Amandine Tournay
+ */
+public class JepPreferencesWindow extends IcyFrame implements ActionListener {
+    IcyFrame frame = IcyFrame.findIcyFrame(getInternalFrame());
+    private JButton customPythonBrowseButton, applyButton, saveButton, cancelButton;
+    private JComboBox<String> condaEnvCombo;
+    private JRadioButton condaRadioButton, customPythonRadioButton;
+    private IcyTextField customPythonPathText;
+    private Set<String> condaEnvList;
+
+    public JepPreferencesWindow() {
+        super("JEP configuration", true, true, true, true);
+
+        // UI
+        initialize();
+
+        // Listeners
+        condaRadioButton.addActionListener(this);
+        customPythonRadioButton.addActionListener(this);
+        customPythonBrowseButton.addActionListener(this);
+        applyButton.addActionListener(this);
+        saveButton.addActionListener(this);
+        cancelButton.addActionListener(this);
+
+        // Update UI with saved settings
+        validate();
+        load();
+    }
+
+    private void initialize() {
+        JPanel mainPanel = new JPanel(createGridLayout());
+        mainPanel.setLayout(createGridLayout());
+
+        condaEnvList = PythonUtils.getInstance().getCondaEnvNames();
+
+        GridBagConstraints condaCons = createConstraints(0, 2, 2., GridBagConstraints.FIRST_LINE_START, new int[]{15, 0, 8, 5});
+
+        // First choice -> use a Conda environment
+        condaRadioButton = createRadioButton("Use a Conda (Anaconda, Miniconda, Mamba, etc...) environment");
+        mainPanel.add(condaRadioButton, condaCons);
+
+        if (condaEnvList != null) {
+            condaEnvCombo = createComboBox(condaEnvList.toArray(new String[0]));
+        }
+        else {
+            condaRadioButton.setEnabled(false);
+            condaEnvCombo = createComboBox(new String[]{});
+        }
+
+        condaEnvCombo.setEnabled(false);
+        condaCons.gridx = 2;
+        condaCons.weightx = 0.;
+        condaCons.gridwidth = 1;
+        condaCons.fill = GridBagConstraints.NONE;
+        condaCons.insets = new Insets(15, 0, 0, 0);
+        mainPanel.add(condaEnvCombo, condaCons);
+
+        // Second choice -> use another Python installed
+        customPythonRadioButton = createRadioButton("Set manually the path to the Python home directory");
+        mainPanel.add(customPythonRadioButton, createConstraints(1, 1, 1., GridBagConstraints.FIRST_LINE_START, new int[]{0, 0, 8, 0}));
+
+        GridBagConstraints customPythonConstraints = createConstraints(2, 2, 2., GridBagConstraints.FIRST_LINE_START, new int[]{0, 0, 0, 5});
+
+        customPythonPathText = createTextInput();
+        customPythonPathText.setEnabled(false);
+        mainPanel.add(customPythonPathText, customPythonConstraints);
+
+        customPythonBrowseButton = createButton("Browse");
+        customPythonBrowseButton.setEnabled(false);
+        customPythonConstraints.gridx = 2;
+        customPythonConstraints.gridwidth = 1;
+        customPythonConstraints.weightx = 1.;
+        customPythonConstraints.weighty = 1.;
+        customPythonConstraints.fill = GridBagConstraints.NONE;
+        mainPanel.add(customPythonBrowseButton, customPythonConstraints);
+
+        // Group radio buttons for selection
+        ButtonGroup radioGroup = createRadioGroup();
+        radioGroup.add(condaRadioButton);
+        radioGroup.add(customPythonRadioButton);
+
+        if (condaEnvList == null) {
+            JLabel condaNotInstalled = new JLabel("Conda is currently not installed");
+            condaNotInstalled.setFont(new Font(condaNotInstalled.getFont().getName(), Font.ITALIC, condaNotInstalled.getFont().getSize()));
+
+            mainPanel.add(condaNotInstalled, createConstraints(3, 2, 1., GridBagConstraints.CENTER, new int[]{0, 0, 0, 0}));
+        }
+
+        // State buttons
+        Box buttonsBox = Box.createHorizontalBox();
+        GridBagConstraints buttonsConstraints = createConstraints(condaEnvList != null ? 3 : 4, 1, 0., GridBagConstraints.LAST_LINE_END, new int[]{0, 5, 5, 5});
+        buttonsConstraints.fill = GridBagConstraints.NONE;
+
+        applyButton = createButton("Apply");
+        buttonsBox.add(applyButton);
+
+        buttonsBox.add(Box.createHorizontalStrut(5));
+
+        saveButton = createButton("Ok");
+        buttonsConstraints.gridx++;
+        buttonsBox.add(saveButton);
+
+        buttonsBox.add(Box.createHorizontalStrut(5));
+
+        cancelButton = createButton("Cancel");
+        buttonsConstraints.gridx++;
+        buttonsBox.add(cancelButton);
+
+        mainPanel.add(buttonsBox, buttonsConstraints);
+
+        setContentPane(mainPanel);
+    }
+
+    private void load() {
+        String pythonHomePath = JepPreferences.getInstance().getPythonRoot();
+
+        if (!pythonHomePath.isEmpty()) {
+            if (pythonHomePath.contains("conda")) {
+                condaRadioButton.setSelected(true);
+                condaEnvCombo.setEnabled(true);
+
+                for (String envName : PythonUtils.getInstance().getCondaEnvNames()) {
+                    Pattern pattern = Pattern.compile(envName);
+                    Matcher matcher = pattern.matcher(pythonHomePath);
+
+                    if (matcher.find()) {
+                        condaEnvCombo.setSelectedItem(envName);
+                    }
+                }
+            }
+            else {
+                customPythonRadioButton.setSelected(true);
+                customPythonPathText.setEnabled(true);
+                customPythonPathText.setText(pythonHomePath);
+                customPythonBrowseButton.setEnabled(true);
+            }
+        }
+    }
+
+    private boolean apply() {
+        String pythonHomePath = "";
+
+        if (condaRadioButton.isSelected()) {
+            pythonHomePath = PythonUtils.getInstance().detectCondaEnvironments().get((String) condaEnvCombo.getSelectedItem());
+        }
+        if (customPythonRadioButton.isSelected()) {
+            pythonHomePath = customPythonPathText.getText();
+        }
+
+        String pythonExecutablePath = PythonUtils.getInstance().findPythonExecutable(pythonHomePath, true);
+
+        if (pythonExecutablePath != null) {
+            JepPreferences.getInstance().setPythonRoot(pythonHomePath);
+            JepPreferences.getInstance().setPythonExecPath(pythonExecutablePath);
+
+            String sitePackageDirectory = PythonUtils.getInstance().setSitePackagesDirectory();
+            String jepPath = JepUtils.getInstance().findJepLib(sitePackageDirectory);
+
+            if (jepPath == null) {
+                PythonUtils.getInstance().installPythonPackage("wheel numpy jep");
+                jepPath = JepUtils.getInstance().findJepLib(sitePackageDirectory);
+            }
+
+            JepPreferences.getInstance().setJepPath(jepPath);
+        }
+        else {
+            MessageDialog.showDialog("Error while finding Python", "Python could not be found. Please select an other directory.", MessageDialog.ERROR_MESSAGE);
+
+            return false;
+        }
+
+        MessageDialog.showDialog("JEP configuration saved", "JEP settings has been successfully saved", MessageDialog.INFORMATION_MESSAGE);
+
+        return true;
+    }
+
+    private void save() {
+        if (apply()) {
+            frame.dispose();
+        }
+    }
+
+    private void cancel() {
+        frame.dispose();
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent actionEvent) {
+        if (actionEvent.getSource().equals(condaRadioButton)) {
+            if (condaEnvList != null) {
+                condaEnvCombo.setEnabled(condaRadioButton.isSelected());
+            }
+            else {
+                condaEnvCombo.setEnabled(false);
+            }
+
+            customPythonPathText.setEnabled(false);
+            customPythonBrowseButton.setEnabled(false);
+        }
+        else if (actionEvent.getSource().equals(customPythonRadioButton)) {
+            if (customPythonRadioButton.isSelected()) {
+                condaEnvCombo.setEnabled(false);
+                customPythonPathText.setEnabled(true);
+                customPythonBrowseButton.setEnabled(true);
+            }
+            else {
+                condaEnvCombo.setEnabled(false);
+                customPythonPathText.setEnabled(false);
+                customPythonBrowseButton.setEnabled(false);
+            }
+        }
+        else if (actionEvent.getSource().equals(customPythonBrowseButton)) {
+            createDirectorySelection();
+        }
+        else if (actionEvent.getSource().equals(applyButton)) {
+            apply();
+        }
+        else if (actionEvent.getSource().equals(saveButton)) {
+            save();
+        }
+        else if (actionEvent.getSource().equals(cancelButton)) {
+            cancel();
+        }
+    }
+
+    /**
+     * Delegate function to create a GridBagLayout
+     *
+     * @return New instance of GridBagLayout
+     */
+    private GridBagLayout createGridLayout() {
+        return new GridBagLayout();
+    }
+
+    /**
+     * Delegate function to add constraints for a grid cell
+     *
+     * @param y      Position in vertical axis of the grid
+     * @param width  Width of the cell in the grid
+     * @param anchor Position the cell in a specific location of the grid
+     * @param insets Add margins to the cell with Insets class (top, left, bottom right)
+     * @return New instance of GridBagConstraints
+     */
+    private GridBagConstraints createConstraints(int y, int width, double weightX, int anchor, int[] insets) {
+        GridBagConstraints constraints = new GridBagConstraints();
+        constraints.gridx = 0;
+        constraints.gridy = y;
+        constraints.gridwidth = width;
+        constraints.gridheight = 1;
+        constraints.fill = GridBagConstraints.HORIZONTAL;
+        constraints.anchor = anchor;
+        constraints.insets = new Insets(insets[0], insets[1], insets[2], insets[3]);
+        constraints.weightx = weightX;
+        constraints.weighty = 0.0;
+
+        return constraints;
+    }
+
+    /**
+     * Delegate function to add a ButtonGroup
+     *
+     * @return New instance of ButtonGroup
+     */
+    private ButtonGroup createRadioGroup() {
+        return new ButtonGroup();
+    }
+
+    /**
+     * Delegate function to create a JRadioButton
+     *
+     * @param text Text to add in radio button
+     * @return New instance of JRadioButton
+     */
+    private JRadioButton createRadioButton(String text) {
+        return new JRadioButton(text);
+    }
+
+    /**
+     * Delegate function to create a new JRadioButton
+     *
+     * @return New instance of JButton
+     */
+    private JButton createButton(String text) {
+        return new JButton(text);
+    }
+
+    /**
+     * Delegate function to create a new JComboBox with different kind of data
+     *
+     * @param content Array of element to list
+     * @param <T>     Generic type
+     * @return New instance of JComboBox
+     */
+    private <T> JComboBox<T> createComboBox(T[] content) {
+        return new JComboBox<>(content);
+    }
+
+    /**
+     * Delegate function to create a new IcyTextField (JTextField)
+     *
+     * @return New instance of IcyTextField
+     */
+    private IcyTextField createTextInput() {
+        return new IcyTextField("");
+    }
+
+    /**
+     * Delegate function to manage JFileChooser
+     */
+    private void createDirectorySelection() {
+        String pythonPathInput = customPythonPathText.getText();
+
+        JFileChooser selectPythonDirectoryDiag = new JFileChooser();
+        selectPythonDirectoryDiag.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        selectPythonDirectoryDiag.setAcceptAllFileFilterUsed(false);
+        selectPythonDirectoryDiag.setDialogTitle("Set Python home directory");
+
+        if (!pythonPathInput.isEmpty()) {
+            Path pythonHomePath = Paths.get(pythonPathInput);
+            boolean isDirectory = pythonHomePath.toFile().isDirectory();
+
+            selectPythonDirectoryDiag.setCurrentDirectory(isDirectory ? pythonHomePath.toFile() : pythonHomePath.getParent().toFile());
+        }
+
+        if (selectPythonDirectoryDiag.showOpenDialog(customPythonBrowseButton) == JFileChooser.APPROVE_OPTION) {
+            customPythonPathText.setText(selectPythonDirectoryDiag.getSelectedFile().getAbsolutePath());
+        }
+    }
+}
diff --git a/src/main/java/plugins/atournay/jep/ui/Python3Preferences.java b/src/main/java/plugins/atournay/jep/ui/Python3Preferences.java
new file mode 100644
index 0000000000000000000000000000000000000000..63379f662bc2161162f1aa3a8a45f6af79a108dd
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/ui/Python3Preferences.java
@@ -0,0 +1,31 @@
+package plugins.atournay.jep.ui;
+
+import icy.gui.frame.IcyFrameAdapter;
+import icy.gui.frame.IcyFrameEvent;
+import icy.plugin.abstract_.PluginActionable;
+import icy.plugin.interface_.PluginBundled;
+import plugins.atournay.jep.JepPlugin;
+
+public class Python3Preferences extends PluginActionable implements PluginBundled {
+    @Override
+    public void run() {
+        final JepPreferencesWindow frameWindow = new JepPreferencesWindow();
+        frameWindow.setSize(700, 180);
+        frameWindow.setResizable(false);
+        frameWindow.setVisible(true);
+        frameWindow.addToDesktopPane();
+        frameWindow.requestFocus();
+
+        frameWindow.addFrameListener(new IcyFrameAdapter() {
+            @Override
+            public void icyFrameClosed(IcyFrameEvent icyFrameEvent) {
+                frameWindow.removeFrameListener(this);
+            }
+        });
+    }
+
+    @Override
+    public String getMainPluginClassName() {
+        return JepPlugin.class.getName();
+    }
+}
diff --git a/src/main/java/plugins/atournay/jep/JepUtils.java b/src/main/java/plugins/atournay/jep/utils/JepUtils.java
similarity index 72%
rename from src/main/java/plugins/atournay/jep/JepUtils.java
rename to src/main/java/plugins/atournay/jep/utils/JepUtils.java
index b68bcf9c0561e69438b6316b94019d34ec5c644f..ff28e489dcb7d7c3206fd88ced17d1b5c42fcf18 100644
--- a/src/main/java/plugins/atournay/jep/JepUtils.java
+++ b/src/main/java/plugins/atournay/jep/utils/JepUtils.java
@@ -1,6 +1,7 @@
-package plugins.atournay.jep;
+package plugins.atournay.jep.utils;
 
 import jep.*;
+import plugins.atournay.jep.exec.DefaultClassEnquirer;
 
 import java.io.File;
 
@@ -12,7 +13,6 @@ import java.io.File;
 public class JepUtils {
     private static JepUtils instance;
     private JepConfig jepConfig;
-    private Interpreter jepInterpreter;
 
     private JepUtils() {
     }
@@ -34,8 +34,6 @@ public class JepUtils {
         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 {
@@ -60,7 +58,7 @@ public class JepUtils {
     public void setJepPath(String jepPath, String pythonRoot) throws JepException {
         setJepConfig(new JepConfig());
 
-        getJepConfig().setClassEnquirer(new CustomClassEnquirer());
+        getJepConfig().setClassEnquirer(new DefaultClassEnquirer());
 
         if (jepPath.matches(".*conda.*|.*venv")) {
             PyConfig pyConfig = new PyConfig();
@@ -73,23 +71,6 @@ public class JepUtils {
         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>
-     * {@link JepUtils#openPython()}
-     */
-    public void closePython() {
-        getJepInterpreter().close();
-    }
-
     /**
      * Create a new Python instance
      *
@@ -102,7 +83,7 @@ public class JepUtils {
     /**
      * Create a new Python instance
      *
-     * @param jepConfig JEP configurations {@link  jep.JepConfig} and example at {@link plugins.atournay.jep.CustomClassEnquirer}
+     * @param jepConfig JEP configurations {@link  jep.JepConfig} and example at {@link DefaultClassEnquirer}
      * @return Python interpreter to execute some Python commands, retrieve values, etc...
      */
     public SubInterpreter openSubPython(JepConfig jepConfig) {
@@ -127,12 +108,4 @@ public class JepUtils {
     private void setJepConfig(JepConfig newJepConfig) {
         this.jepConfig = newJepConfig;
     }
-
-    public Interpreter getJepInterpreter() {
-        return jepInterpreter;
-    }
-
-    private void setJepInterpreter(Interpreter jepInterpreter) {
-        this.jepInterpreter = jepInterpreter;
-    }
 }
diff --git a/src/main/java/plugins/atournay/jep/utils/PythonUtils.java b/src/main/java/plugins/atournay/jep/utils/PythonUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..70baf2cb6f5e905ce1e5b587a9b354a6c84498af
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/utils/PythonUtils.java
@@ -0,0 +1,249 @@
+package plugins.atournay.jep.utils;
+
+import icy.gui.dialog.MessageDialog;
+import icy.gui.frame.IcyFrame;
+import icy.system.IcyExceptionHandler;
+import icy.system.thread.ThreadUtil;
+import plugins.atournay.jep.prefs.JepPreferences;
+
+import javax.swing.*;
+import java.awt.*;
+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.List;
+import java.util.*;
+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) {
+            return null;
+        }
+
+        return condaEnvs;
+    }
+
+    /**
+     * Get Conda environment names available on the computer
+     *
+     * @return List of all Conda environment names
+     */
+    public Set<String> getCondaEnvNames() {
+        return detectCondaEnvironments() != null ? detectCondaEnvironments().keySet() : null;
+    }
+
+    /**
+     * 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(String path, boolean isDirectory) {
+        if (isDirectory) {
+            File pathToTest = new File(path);
+            File[] pythonFiles = Utils.getInstance().isWindows() ? pathToTest.listFiles(File::isFile) : pathToTest.listFiles((file, name) -> name.equals("bin") && file.isDirectory());
+
+            if (pythonFiles != null) {
+                if (Utils.getInstance().isWindows()) {
+                    File foundPython = Arrays.stream(pythonFiles)
+                            .filter(x -> Pattern.compile("python?3?(?:\\.exe|$)").matcher(x.getAbsolutePath()).find())
+                            .findFirst().orElse(null);
+
+                    return foundPython != null ? foundPython.getAbsolutePath() : null;
+                }
+                else {
+                    for (File binDirectory : pythonFiles) {
+                        File[] binFiles = binDirectory.listFiles((file, name) -> name.matches("python?3?(?:\\.exe|$)"));
+
+                        if (binFiles != null) {
+                            return Arrays.stream(binFiles).findFirst().map(File::getAbsolutePath).orElse(null);
+                        }
+                    }
+                }
+            }
+        }
+        else {
+            if (Files.exists(Paths.get(path))) {
+                return path;
+            }
+            else {
+                return null;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @return The path to the site-packages directory
+     */
+    public String setSitePackagesDirectory() {
+        String terminalLine;
+        String[] command = new String[]{JepPreferences.getInstance().getPythonExecPath(), "-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(",");
+
+                for (String spPath : spList) {
+                    System.out.println(spPath);
+                    if (spPath.contains("site-packages")) {
+                        sitePackagesPath = spPath;
+                        break;
+                    }
+                }
+            }
+
+            // Error stream output
+            while ((terminalLine = streamError.readLine()) != null) {
+                System.err.println(terminalLine);
+            }
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return sitePackagesPath;
+    }
+
+    /**
+     * Install Python packages through pip via the terminal of the computer
+     * @see plugins.atournay.jep.exec.PythonExec#installPythonPackage(String) to install a Python package through Python
+     *
+     * @param packageNames Name of the packages to install through pip.
+     *                     It can be either the package name (i.e. numpy) or a specific version of a package (i.e. numpy==1.23.1) separated by a space
+     */
+    public void installPythonPackage(String packageNames) {
+        // Create command to execute (i.e. /path/to/python -m pip install package1 package2 ...)
+        String pythonExec = Utils.getInstance().isWindows() ? JepPreferences.getInstance().getPythonExecPath().replace("\\", "\\\\") : JepPreferences.getInstance().getPythonExecPath();
+        ArrayList<String> packageList = Arrays.stream(packageNames.trim().split(" ")).filter(s -> !s.equals("")).map(String::trim).collect(Collectors.toCollection(ArrayList::new));
+        ArrayList<String> commandLine = new ArrayList<>();
+        commandLine.add(pythonExec);
+        commandLine.add("-m");
+        commandLine.add("pip");
+        commandLine.add("install");
+        commandLine.addAll(packageList);
+
+        // Create window to get output console
+        final IcyFrame[] installFrame = new IcyFrame[1];
+        JTextArea outputArea = new JTextArea();
+
+        ThreadUtil.invokeNow(() -> {
+            installFrame[0] = new IcyFrame("Installing Python packages " + packageNames, false, false);
+            installFrame[0].getContentPane().setLayout(new GridLayout());
+            installFrame[0].setSize(1000, 300);
+            installFrame[0].setVisible(true);
+            installFrame[0].addToDesktopPane();
+            installFrame[0].requestFocus();
+
+            installFrame[0].getContentPane().add(outputArea);
+        });
+
+        ThreadUtil.bgRun(() -> {
+            // Execute installation with pip
+            ProcessBuilder command = new ProcessBuilder(commandLine);
+
+            // Retrieve output
+            Process sysProc;
+            BufferedReader bufferedReader;
+            BufferedReader bufferedErrReader;
+            try {
+                sysProc = command.start();
+                bufferedReader = new BufferedReader(new InputStreamReader(sysProc.getInputStream()));
+                bufferedErrReader = new BufferedReader(new InputStreamReader(sysProc.getErrorStream()));
+            }
+            catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+
+            try {
+                String line, lineError;
+
+                // Update window with new output element
+                while ((line = bufferedReader.readLine()) != null) {
+                    System.out.println(line);
+
+                    String finalLine = line;
+                    ThreadUtil.invokeLater(() -> {
+                        outputArea.append(finalLine);
+                        outputArea.append("\n");
+                        installFrame[0].validate();
+                    });
+                }
+
+                while ((lineError = bufferedErrReader.readLine()) != null) {
+                    System.out.println(lineError);
+
+                    String finalLineError = lineError;
+                    ThreadUtil.invokeLater(() -> {
+                        outputArea.append(finalLineError);
+                        outputArea.append("");
+                        installFrame[0].validate();
+                    });
+                }
+
+                sysProc.waitFor();
+
+                Thread.sleep(2000);
+
+                // Close window
+                ThreadUtil.invokeLater(() -> installFrame[0].dispose());
+            }
+            catch (IOException | InterruptedException e) {
+                MessageDialog.showDialog("Error while trying to install " + packageNames, e.toString(), MessageDialog.ERROR_MESSAGE);
+
+                IcyExceptionHandler.showErrorMessage(new RuntimeException(e), true);
+            }
+        });
+    }
+}
diff --git a/src/main/java/plugins/atournay/jep/utils/Utils.java b/src/main/java/plugins/atournay/jep/utils/Utils.java
new file mode 100644
index 0000000000000000000000000000000000000000..2bdfd3c7c0d84d36f4c99c87266b7d0072666847
--- /dev/null
+++ b/src/main/java/plugins/atournay/jep/utils/Utils.java
@@ -0,0 +1,48 @@
+package plugins.atournay.jep.utils;
+
+import java.util.regex.Pattern;
+
+public class Utils {
+    private static Utils instance;
+
+    private Utils() {}
+
+    public static Utils getInstance() {
+        if (instance == null) {
+            instance = new Utils();
+        }
+
+        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(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;
+        }
+    }
+
+    public String getOS() {
+        return System.getProperty("os.name").toLowerCase();
+    }
+
+    public boolean isWindows() {
+        return getOS().contains("win");
+    }
+
+    public boolean isMacOS() {
+        return getOS().startsWith("mac");
+    }
+
+    public boolean isLinux() {
+        return getOS().startsWith("nix") || getOS().contains("nux") || getOS().contains("aix");
+    }
+}
diff --git a/src/main/resources/readMePictures/Python - search.png b/src/main/resources/readMePictures/Python - search.png
new file mode 100644
index 0000000000000000000000000000000000000000..45cca8852383946d7e1c46acf138356576785cd7
Binary files /dev/null and b/src/main/resources/readMePictures/Python - search.png differ
diff --git a/src/main/resources/readMePictures/Python - set with Conda.png b/src/main/resources/readMePictures/Python - set with Conda.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e0c047d17aacf5cb0b5bd089d3f2c9ba56cdd7c
Binary files /dev/null and b/src/main/resources/readMePictures/Python - set with Conda.png differ
diff --git a/src/main/resources/readMePictures/Python - set with custom path.png b/src/main/resources/readMePictures/Python - set with custom path.png
new file mode 100644
index 0000000000000000000000000000000000000000..e79ceebfa0bf13ab363175e28ac14842384ee498
Binary files /dev/null and b/src/main/resources/readMePictures/Python - set with custom path.png differ