diff --git a/src/main/java/plugins/fab/trackmanager/TrackManager.java b/src/main/java/plugins/fab/trackmanager/TrackManager.java
index 8679f64056e00015057645ac9f9017e570ab7595..c4b7814350a38f72eaefd6b1fb3125003d634114 100644
--- a/src/main/java/plugins/fab/trackmanager/TrackManager.java
+++ b/src/main/java/plugins/fab/trackmanager/TrackManager.java
@@ -766,7 +766,6 @@ public class TrackManager extends PluginActionable
 
     private void loadTracks()
     {
-
         JFileChooser chooser = new JFileChooser();
         chooser.setDialogTitle("Select track.xml file.");
 
@@ -784,102 +783,102 @@ public class TrackManager extends PluginActionable
 
         preferences.put("path", chooser.getCurrentDirectory().getAbsolutePath());
 
-        File file = chooser.getSelectedFile();
+        try
+        {
+            final List<TrackGroup> groups = loadTracks(chooser.getSelectedFile().getAbsolutePath());
 
-        Document document = XMLUtil.loadDocument(file);
+            // add group to swimming pool
+            for (TrackGroup group : groups)
+            {
+                SwimmingObject so = new SwimmingObject(group);
+                Icy.getMainInterface().getSwimmingPool().add(so);
+            }
 
-        if (document == null)
-        {
-            MessageDialog.showDialog("Invalid track file: no document to open", MessageDialog.ERROR_MESSAGE);
-            return;
+            trackPool.fireTrackEditorProcessorChange();
         }
-
-        Element versionElement = XMLUtil.getElement(document.getDocumentElement(), "trackfile");
-        if (versionElement == null)
+        catch (IllegalArgumentException ex)
         {
-            MessageDialog.showDialog("Invalid track file: the tag trackfile is missing.", MessageDialog.ERROR_MESSAGE);
+            MessageDialog.showDialog(ex.getMessage(), MessageDialog.ERROR_MESSAGE);
             return;
         }
+    }
 
-        ArrayList<Element> trackGroupElementList = XMLUtil.getElements(document.getDocumentElement(), "trackgroup");
+    public static List<TrackGroup> loadTracks(String path) throws IllegalArgumentException
+    {
+        final Document document = XMLUtil.loadDocument(path, false);
+        return loadTracks(document);
+    }
 
-        for (Element trackGroupElement : trackGroupElementList)
-        {
+    public static List<TrackGroup> loadTracks(Document document) throws IllegalArgumentException
+    {
+        if (document == null)
+            throw new IllegalArgumentException("Invalid track file !");
+
+        final Element rootElement = document.getDocumentElement();
+
+        if (XMLUtil.getElement(rootElement, "trackfile") == null)
+            throw new IllegalArgumentException("Invalid track file: the tag trackfile is missing.");
 
-            ArrayList<Element> trackSegmentElementList = XMLUtil.getElements(trackGroupElement);
-            TrackGroup trackGroup = new TrackGroup(null);
-            String groupDescription = XMLUtil.getAttributeValue(trackGroupElement, "description", "no description");
-            trackGroup.setDescription(groupDescription);
+        final List<TrackGroup> result = new ArrayList<>();
+
+        for (Element trackGroupElement : XMLUtil.getElements(rootElement, "trackgroup"))
+        {
+            // create track group
+            final TrackGroup trackGroup = new TrackGroup(null);
+            trackGroup.setDescription(XMLUtil.getAttributeValue(trackGroupElement, "description", "no description"));
 
-            for (Element trackSegmentElement : trackSegmentElementList)
+            for (Element trackSegmentElement : XMLUtil.getElements(trackGroupElement))
             {
+                // create track segment
+                final TrackSegment trackSegment = new TrackSegment();
+                final int id = XMLUtil.getAttributeIntValue(trackSegmentElement, "id", -1);
 
-                TrackSegment trackSegment = new TrackSegment();
-                int id = XMLUtil.getAttributeIntValue(trackSegmentElement, "id", -1);
                 if (id == -1)
                     trackSegment.generateId();
                 else
                     trackSegment.setId(id);
-                // trackSegment.setId( Integer.parseInt( trackSegmentElement.getAttribute("id") ) );
 
-                ArrayList<Element> detectionElementList = XMLUtil.getElements(trackSegmentElement);
-
-                for (Element detectionElement : detectionElementList)
+                for (Element detectionElement : XMLUtil.getElements(trackSegmentElement))
                 {
+                    // create detection
+                    final Detection detection = Detection.createDetection(XMLUtil.getAttributeValue(detectionElement,
+                            "classname", "plugins.nchenouard.spot.Detection"));
 
-                    String className = XMLUtil.getAttributeValue(detectionElement, "classname",
-                            "plugins.nchenouard.spot.Detection");
-
-                    Detection detection = Detection.createDetection(className);
-
+                    // load it
                     detection.loadFromXML(detectionElement);
-
+                    // add to track segement
                     trackSegment.addDetection(detection);
                 }
 
+                // add track segment to track group
                 trackGroup.addTrackSegment(trackSegment);
             }
-
-            SwimmingObject so = new SwimmingObject(trackGroup);
-            Icy.getMainInterface().getSwimmingPool().add(so);
-
+            
+            // add track group to result
+            result.add(trackGroup);
         }
 
-        // load links.
-
-        ArrayList<Element> linkList = XMLUtil.getElements(document.getDocumentElement(), "linklist");
+        // get links
+        for (Element linkListElement : XMLUtil.getElements(rootElement, "linklist"))
         {
-            for (Element linkListElement : linkList)
+            for (Element link : XMLUtil.getElements(linkListElement))
             {
-                ArrayList<Element> trackSegmentElementList = XMLUtil.getElements(linkListElement);
-                for (Element link : trackSegmentElementList)
-                {
-                    int idFrom = XMLUtil.getAttributeIntValue(link, "from", -1);
-                    int idTo = XMLUtil.getAttributeIntValue(link, "to", -1);
-
-                    TrackSegment from = TrackSegment.getTrackSegmentById(idFrom);
-                    TrackSegment to = TrackSegment.getTrackSegmentById(idTo);
-
-                    // System.out.println( "track from: " + idFrom + " "+ from );
-                    // System.out.println( "track to: " + idTo + " "+ to );
+                final int idFrom = XMLUtil.getAttributeIntValue(link, "from", -1);
+                final int idTo = XMLUtil.getAttributeIntValue(link, "to", -1);
 
-                    // System.out.println( "Checking null... ");
+                final TrackSegment from = TrackSegment.getTrackSegmentById(idFrom);
+                final TrackSegment to = TrackSegment.getTrackSegmentById(idTo);
 
-                    if (from != null && to != null)
-                    {
-                        // System.out.println("TrackManager : from : " + from + " to " + to );
-                        trackPool.createLink(from, to);
-                    }
-                }
+                if (from != null && to != null)
+                    TrackPool.createLink(result, from, to);
             }
         }
 
-        trackPool.fireTrackEditorProcessorChange();
+        return result;
     }
 
     private void loadTracksFromTrackMate()
     {
-
         JFileChooser chooser = new JFileChooser();
         chooser.setDialogTitle("Import TrackMate xml track file.");
 
@@ -897,81 +896,86 @@ public class TrackManager extends PluginActionable
 
         preferences.put("path", chooser.getCurrentDirectory().getAbsolutePath());
 
-        File file = chooser.getSelectedFile();
+        try
+        {
+            final List<TrackGroup> groups = loadTracksFromTrackMate(chooser.getSelectedFile().getAbsolutePath());
 
-        Document document = XMLUtil.loadDocument(file);
+            // add group to swimming pool
+            for (TrackGroup group : groups)
+            {
+                SwimmingObject so = new SwimmingObject(group);
+                Icy.getMainInterface().getSwimmingPool().add(so);
+            }
 
-        if (document == null)
+            trackPool.fireTrackEditorProcessorChange();
+        }
+        catch (IllegalArgumentException ex)
         {
-            MessageDialog.showDialog("Invalid track file: no document to open", MessageDialog.ERROR_MESSAGE);
+            MessageDialog.showDialog(ex.getMessage(), MessageDialog.ERROR_MESSAGE);
             return;
         }
+    }
+
+    public static List<TrackGroup> loadTracksFromTrackMate(String path)
+    {
+        final Document document = XMLUtil.loadDocument(path, false);
+        return loadTracksFromTrackMate(document);
+    }
+
+    public static List<TrackGroup> loadTracksFromTrackMate(Document document) throws IllegalArgumentException
+    {
+        if (document == null)
+            throw new IllegalArgumentException("Invalid track file !");
 
         final Element trackNode = XMLUtil.getElement(document.getDocumentElement().getParentNode(), "Tracks");
         if (trackNode == null)
-        {
-            MessageDialog.showDialog(
-                    "Unsupported version of TrackMate XML file !\nTry to use the Icy XML export in TrackMate instead and directly load it with 'TrackManager-->File->Load...' command.",
-                    MessageDialog.ERROR_MESSAGE);
-            return;
-        }
+            throw new IllegalArgumentException(
+                    "Unsupported version of TrackMate XML file !\nTry to use the Icy XML export in TrackMate instead and directly load it with 'TrackManager-->File->Load...' command.");
 
-        String unit = XMLUtil.getAttributeValue(trackNode, "spaceUnits", "pixel");
+        final List<TrackGroup> result = new ArrayList<>();
+        final String unit = XMLUtil.getAttributeValue(trackNode, "spaceUnits", "pixel");
 
         double unitMultiplicator = 1;
         if (unit == "micron")
             unitMultiplicator = 0.000001d;
 
-        ArrayList<Element> trackElementList = XMLUtil.getElements(document.getDocumentElement().getParentNode(),
-                "Tracks");
-
-        // XMLUtil.getAttribute( trackElementList , attribute)
-        // trackElementList
-
-        for (Element trackElement : trackElementList)
+        for (Element trackElement : XMLUtil.getElements(document.getDocumentElement().getParentNode(), "Tracks"))
         {
+            // create track group
+            final TrackGroup trackGroup = new TrackGroup(null);
+            trackGroup.setDescription(XMLUtil.getAttributeValue(trackElement, "description", "no description"));
 
-            ArrayList<Element> trackSegmentElementList = XMLUtil.getElements(trackElement);
-            TrackGroup trackGroup = new TrackGroup(null);
-            String groupDescription = XMLUtil.getAttributeValue(trackElement, "description", "no description");
-            trackGroup.setDescription(groupDescription);
-
-            for (Element trackSegmentElement : trackSegmentElementList) // particle tag
+            for (Element trackSegmentElement : XMLUtil.getElements(trackElement))
             {
+                // create track segment
+                final TrackSegment trackSegment = new TrackSegment();
 
-                TrackSegment trackSegment = new TrackSegment();
-                int id = XMLUtil.getAttributeIntValue(trackSegmentElement, "id", -1);
+                final int id = XMLUtil.getAttributeIntValue(trackSegmentElement, "id", -1);
                 if (id == -1)
-                {
                     trackSegment.generateId();
-                }
                 else
-                {
                     trackSegment.setId(id);
-                }
-
-                ArrayList<Element> detectionElementList = XMLUtil.getElements(trackSegmentElement);
 
-                for (Element detectionElement : detectionElementList)
+                for (Element detectionElement : XMLUtil.getElements(trackSegmentElement))
                 {
+                    // create detection
+                    final Detection detection = Detection.createDetection("plugins.nchenouard.spot.Detection");
 
-                    Detection detection = Detection.createDetection("plugins.nchenouard.spot.Detection");
-
+                    // load it
                     detection.loadFromXML(detectionElement);
-
+                    // add to track segment
                     trackSegment.addDetection(detection);
-
                 }
 
+                // add track segment to group
                 trackGroup.addTrackSegment(trackSegment);
             }
-
-            SwimmingObject so = new SwimmingObject(trackGroup);
-            Icy.getMainInterface().getSwimmingPool().add(so);
-
+            
+            // add track group to result
+            result.add(trackGroup);
         }
 
-        trackPool.fireTrackEditorProcessorChange();
+        return result;
     }
 
     private void debug()
@@ -991,7 +995,6 @@ public class TrackManager extends PluginActionable
 
     private void saveTracks()
     {
-
         JFileChooser chooser = new JFileChooser();
         chooser.setDialogTitle("Select track.xml file.");
         chooser.setFileFilter(new FileNameExtensionFilter("XML track file", "xml"));
@@ -1008,30 +1011,41 @@ public class TrackManager extends PluginActionable
 
         preferences.put("path", chooser.getCurrentDirectory().getAbsolutePath());
 
-        File file = chooser.getSelectedFile();
+        saveTracks(chooser.getSelectedFile().getAbsolutePath(), trackPool.getTrackGroupList());
+    }
 
-        file = new File(FileUtil.setExtension(file.getAbsolutePath(), ".xml"));
+    public static void saveTracks(String path, List<TrackGroup> groups)
+    {
+        // get file
+        final File file = new File(FileUtil.setExtension(path, ".xml"));
+        // generate document
+        final Document document = saveTracks(groups);
+        // save it
+        XMLUtil.saveDocument(document, file);
+    }
 
-        Document document = XMLUtil.createDocument(true);
+    public static Document saveTracks(List<TrackGroup> groups)
+    {
+        final Document result = XMLUtil.createDocument(true);
+        final Element rootElement = result.getDocumentElement();
 
-        Element versionElement = XMLUtil.addElement(document.getDocumentElement(), "trackfile");
+        final Element versionElement = XMLUtil.addElement(rootElement, "trackfile");
         versionElement.setAttribute("version", "1");
 
-        for (TrackGroup trackGroup : trackPool.getTrackGroupList())
+        for (TrackGroup trackGroup : groups)
         {
-            Element trackGroupElement = XMLUtil.addElement(document.getDocumentElement(), "trackgroup");
+            final Element trackGroupElement = XMLUtil.addElement(rootElement, "trackgroup");
             trackGroupElement.setAttribute("description", trackGroup.getDescription());
 
             for (TrackSegment trackSegment : trackGroup.getTrackSegmentList())
             {
-                Element trackElement = XMLUtil.addElement(trackGroupElement, "track");
+                final Element trackElement = XMLUtil.addElement(trackGroupElement, "track");
                 trackElement.setAttribute("id", "" + trackSegment.getId());
 
-                // System.out.println("Saving track : id : " + trackSegment.getId() );
-
                 for (Detection detection : trackSegment.getDetectionList())
                 {
-                    Element detectionElement = XMLUtil.addElement(trackElement, "detection");
+                    final Element detectionElement = XMLUtil.addElement(trackElement, "detection");
+
                     detectionElement.setAttribute("classname", detection.getClass().getName());
                     // detectionElement.setAttribute( "x", ""+detection.x );
                     // detectionElement.setAttribute( "y", ""+detection.y );
@@ -1039,27 +1053,20 @@ public class TrackManager extends PluginActionable
                     // detectionElement.setAttribute( "t", ""+detection.t );
                     detection.saveToXML(detectionElement);
                 }
-
             }
-
         }
 
         // save links
-
-        Element linklistElement = XMLUtil.addElement(document.getDocumentElement(), "linklist");
-        for (Link link : trackPool.getLinks())
+        final Element linklistElement = XMLUtil.addElement(rootElement, "linklist");
+        for (Link link : TrackPool.getLinks(groups))
         {
-            Element trackElement = XMLUtil.addElement(linklistElement, "link");
+            final Element trackElement = XMLUtil.addElement(linklistElement, "link");
 
             trackElement.setAttribute("from", "" + link.getStartSegment().getId());
             trackElement.setAttribute("to", "" + link.getEndSegment().getId());
-            // System.out.println("saving link.");
-            // System.out.println("from Id: " + link.getStartSegment().getId() );
-            // System.out.println("to Id: " + link.getEndSegment().getId() );
         }
 
-        XMLUtil.saveDocument(document, file);
-
+        return result;
     }
 
     /**
diff --git a/src/main/java/plugins/fab/trackmanager/TrackPool.java b/src/main/java/plugins/fab/trackmanager/TrackPool.java
index 09c319a8f20d1dac15f255f37380637b889248e9..5df0025e7412a8d36c90a22c0e9d8e908b1dd8ae 100644
--- a/src/main/java/plugins/fab/trackmanager/TrackPool.java
+++ b/src/main/java/plugins/fab/trackmanager/TrackPool.java
@@ -86,26 +86,39 @@ public class TrackPool
         fireTrackEditorProcessorChange();
     }
 
+    public static boolean linkExists(List<Link> links, TrackSegment start, TrackSegment end)
+    {
+        // check if the link already exists
+        for (Link link : links)
+            if ((link.start == start) && (link.end == end))
+                return true;
+
+        return false;
+    }
+
+    public static boolean isLinkExists(List<TrackGroup> groups, TrackSegment start, TrackSegment end)
+    {
+        return linkExists(getLinks(groups), start, end);
+    }
+
     public boolean isLinkExists(TrackSegment start, TrackSegment end)
     {
-        for (Link link : getLinks()) // check if the link already exists.
+        return linkExists(getLinks(), start, end);
+    }
+
+    public static void createLink(List<TrackGroup> groups, TrackSegment start, TrackSegment end)
+    {
+        if (!isLinkExists(groups, start, end))
         {
-            if (link.start == start && link.end == end)
-            {
-                return true;
-            }
+            start.nextList.add(end);
+            end.previousList.add(start);
         }
-        return false;
     }
 
     public void createLink(TrackSegment start, TrackSegment end)
     {
-        boolean alreadyExist = false;
-        alreadyExist = isLinkExists(start, end);
-
-        if (!alreadyExist)
+        if (!isLinkExists(start, end))
         {
-            // System.out.println("create a new link.");
             start.nextList.add(end);
             end.previousList.add(start);
         }
@@ -539,6 +552,18 @@ public class TrackPool
         return linkarray;
     }
 
+    public static List<Link> getLinks(List<TrackGroup> groups)
+    {
+        final List<Link> result = new ArrayList<Link>();
+        final List<TrackSegment> segments = getTrackSegmentList(groups);
+
+        for (TrackSegment segment : segments)
+            for (int i = 0; i < segment.nextList.size(); i++)
+                result.add(new Link(segment, segment.nextList.get(i)));
+
+        return result;
+    }
+
     // FIXME: put a WeakReference in here
     private Sequence displaySequence = null;
 
@@ -597,6 +622,19 @@ public class TrackPool
         return tePainter;
     }
 
+    /**
+     * @return the pool of tracksegment of all the trackgroup
+     */
+    public static List<TrackSegment> getTrackSegmentList(List<TrackGroup> groups)
+    {
+        final List<TrackSegment> result = new ArrayList<TrackSegment>();
+
+        for (TrackGroup group : groups)
+            result.addAll(group.getTrackSegmentList());
+
+        return result;
+    }
+
     /**
      * @return the pool of tracksegment of all the trackgroup
      */
@@ -876,14 +914,12 @@ public class TrackPool
 
         if (result.getObject() instanceof TrackGroup)
         {
-            // remove track id stored in tracksemgent.idhashmap
-            TrackGroup tg = (TrackGroup) result.getObject();
+            final TrackGroup tg = (TrackGroup) result.getObject();
+
+            // remove track segment from hash map
             for (TrackSegment ts : tg.getTrackSegmentList())
-            {
-                TrackSegment.idHashMapList.remove(ts);
-            }
+                ts.removeId();
         }
-
     }
 
     /**
diff --git a/src/main/java/plugins/fab/trackmanager/TrackSegment.java b/src/main/java/plugins/fab/trackmanager/TrackSegment.java
index 7c44bffb7c8af7e749f094ae447795ec9927909a..72ca4e2c13c1c332ba32a0998b8db43a6cc84af3 100644
--- a/src/main/java/plugins/fab/trackmanager/TrackSegment.java
+++ b/src/main/java/plugins/fab/trackmanager/TrackSegment.java
@@ -18,6 +18,8 @@
  */
 package plugins.fab.trackmanager;
 
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -35,8 +37,8 @@ import plugins.nchenouard.spot.Detection;
 
 public class TrackSegment implements Cloneable
 {
-    protected static Map<TrackSegment, Integer> idHashMapList = new HashMap<TrackSegment, Integer>(); // 1-1 hashmap.
-    protected static Map<Integer, TrackSegment> idKeyHashMapList = new HashMap<Integer, TrackSegment>(); // 1-1 hashmap.
+    // better to use weak reference in the map 
+    protected static Map<Integer, Reference<TrackSegment>> idKeyHashMapList = new HashMap<Integer, Reference<TrackSegment>>(); // 1-1 hashmap.
 
     List<Detection> detectionList = new ArrayList<Detection>();
     List<TrackSegment> previousList = new ArrayList<TrackSegment>();
@@ -46,9 +48,19 @@ public class TrackSegment implements Cloneable
 
     public static TrackSegment getTrackSegmentById(int id)
     {
+        final Integer iid = Integer.valueOf(id);
+
         synchronized (idKeyHashMapList)
         {
-            return idKeyHashMapList.get(Integer.valueOf(id));
+            final Reference<TrackSegment> ref = idKeyHashMapList.get(iid);
+
+            // null ? --> can remove it from the hashmap
+            if (ref.get() == null)
+            {
+                idKeyHashMapList.remove(iid);
+            }
+
+            return ref.get();
         }
     }
 
@@ -104,11 +116,7 @@ public class TrackSegment implements Cloneable
     {
         synchronized (idKeyHashMapList)
         {
-            synchronized (idHashMapList)
-            {
-                idKeyHashMapList.remove(Integer.valueOf(id));
-                idHashMapList.remove(this);
-            }
+            idKeyHashMapList.remove(Integer.valueOf(id));
         }
     }
 
@@ -124,22 +132,17 @@ public class TrackSegment implements Cloneable
 
         synchronized (idKeyHashMapList)
         {
-            synchronized (idHashMapList)
+            while (true)
             {
-                while (true)
-                {
-                    final Integer key = Integer.valueOf(Random.nextInt());
-
-                    // available ?
-                    if (idKeyHashMapList.get(key) == null)
-                    {
-                        idHashMapList.put(this, key);
-                        idKeyHashMapList.put(key, this);
+                final Integer key = Integer.valueOf(Random.nextInt());
 
-                        this.id = key.intValue();
+                // available ?
+                if (idKeyHashMapList.get(key) == null)
+                {
+                    idKeyHashMapList.put(key, new WeakReference<TrackSegment>(this));
+                    id = key.intValue();
 
-                        return;
-                    }
+                    return;
                 }
             }
         }
@@ -151,19 +154,14 @@ public class TrackSegment implements Cloneable
 
         synchronized (idKeyHashMapList)
         {
-            synchronized (idHashMapList)
+            // available ?
+            if (idKeyHashMapList.get(key) == null)
             {
-                // available ?
-                if (idKeyHashMapList.get(key) == null)
-                {
-                    idHashMapList.put(this, key);
-                    idKeyHashMapList.put(key, this);
-
-                    this.id = key.intValue();
-                }
-                else
-                    System.out.println("track id already loaded");
+                idKeyHashMapList.put(key, new WeakReference<TrackSegment>(this));
+                this.id = key.intValue();
             }
+            else
+                System.out.println("track id already loaded");
         }
     }
 
diff --git a/src/main/java/plugins/fab/trackmanager/blocks/LoadTracksFromXML.java b/src/main/java/plugins/fab/trackmanager/blocks/LoadTracksFromXML.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b30ee1078540ec2ddf43618c8f945e0e8dd3e46
--- /dev/null
+++ b/src/main/java/plugins/fab/trackmanager/blocks/LoadTracksFromXML.java
@@ -0,0 +1,74 @@
+package plugins.fab.trackmanager.blocks;
+
+import java.io.File;
+import java.util.List;
+
+import icy.plugin.abstract_.Plugin;
+import icy.plugin.interface_.PluginBundled;
+import icy.plugin.interface_.PluginLibrary;
+import plugins.adufour.blocks.tools.roi.ROIBlock;
+import plugins.adufour.blocks.util.VarList;
+import plugins.adufour.vars.lang.Var;
+import plugins.adufour.vars.lang.VarInteger;
+import plugins.adufour.vars.lang.VarMutable;
+import plugins.fab.trackmanager.TrackGroup;
+import plugins.fab.trackmanager.TrackManager;
+
+/**
+ * Block to load a set of ROI from a file
+ * 
+ * @author Stephane
+ */
+public class LoadTracksFromXML extends Plugin implements ROIBlock, PluginLibrary, PluginBundled
+{
+    final VarMutable file = new VarMutable("XML file", null)
+    {
+        @Override
+        public boolean isAssignableFrom(@SuppressWarnings("rawtypes") Var source)
+        {
+            return (String.class == source.getType()) || (File.class == source.getType());
+        }
+    };
+    final VarInteger groupIndex = new VarInteger("Group index", 0);
+    final Var<TrackGroup> tracks = new Var<TrackGroup>("Track group", new TrackGroup(null));
+
+    @Override
+    public void run()
+    {
+        final Object obj = file.getValue();
+        if (obj == null)
+            return;
+
+        final File f;
+
+        if (obj instanceof String)
+            f = new File((String) obj);
+        else
+            f = (File) obj;
+
+        // load track groups from file
+        final List<TrackGroup> groups = TrackManager.loadTracks(f.getAbsolutePath());
+        // set result
+        tracks.setValue(groups.get(groupIndex.getValue().intValue()));
+    }
+
+    @Override
+    public void declareInput(VarList inputMap)
+    {
+        inputMap.add("file", file);
+        inputMap.add("groupIndex", groupIndex);
+    }
+
+    @Override
+    public void declareOutput(VarList outputMap)
+    {
+        outputMap.add("tracks", tracks);
+
+    }
+
+    @Override
+    public String getMainPluginClassName()
+    {
+        return TrackManager.class.getName();
+    }
+}
diff --git a/src/main/java/plugins/fab/trackmanager/blocks/SaveTracksToXML.java b/src/main/java/plugins/fab/trackmanager/blocks/SaveTracksToXML.java
new file mode 100644
index 0000000000000000000000000000000000000000..c35bb0a76544a344c43633fd59db856824af7d7e
--- /dev/null
+++ b/src/main/java/plugins/fab/trackmanager/blocks/SaveTracksToXML.java
@@ -0,0 +1,74 @@
+package plugins.fab.trackmanager.blocks;
+
+import java.io.File;
+
+import icy.plugin.abstract_.Plugin;
+import icy.plugin.interface_.PluginBundled;
+import icy.plugin.interface_.PluginLibrary;
+import icy.type.collection.CollectionUtil;
+import plugins.adufour.blocks.tools.roi.ROIBlock;
+import plugins.adufour.blocks.util.VarList;
+import plugins.adufour.vars.lang.Var;
+import plugins.adufour.vars.lang.VarMutable;
+import plugins.fab.trackmanager.TrackGroup;
+import plugins.fab.trackmanager.TrackManager;
+
+/**
+ * Block to save a set of ROI to a file
+ * 
+ * @author Stephane
+ */
+public class SaveTracksToXML extends Plugin implements ROIBlock, PluginLibrary, PluginBundled
+{
+    final Var<TrackGroup> tracks = new Var<TrackGroup>("Track group", new TrackGroup(null));
+    final VarMutable file = new VarMutable("XML file", null)
+    {
+        @Override
+        public boolean isAssignableFrom(@SuppressWarnings("rawtypes") Var source)
+        {
+            return (String.class == source.getType()) || (File.class == source.getType());
+        }
+    };
+
+    @Override
+    public void run()
+    {
+        final TrackGroup group = tracks.getValue();
+        // nothing to do
+        if (group == null)
+            return;
+
+        final Object obj = file.getValue();
+        if (obj == null)
+            return;
+
+        final File f;
+
+        if (obj instanceof String)
+            f = new File((String) obj);
+        else
+            f = (File) obj;
+
+        // save tracks into file
+        TrackManager.saveTracks(f.getAbsolutePath(), CollectionUtil.createArrayList(group));
+    }
+
+    @Override
+    public void declareInput(VarList inputMap)
+    {
+        inputMap.add("tracks", tracks);
+        inputMap.add("file", file);
+    }
+
+    @Override
+    public void declareOutput(VarList outputMap)
+    {
+        //
+    }
+
+    @Override
+    public String getMainPluginClassName()
+    {
+        return TrackManager.class.getName();
+    }
+}