diff --git a/src/main/java/fr/irstea/associatione/model/Model.java b/src/main/java/fr/irstea/associatione/model/Model.java
index bbb0760b206f8199164af625cbb06c022a5e3f95..191c0a7242bfc3d18f6f8351a8f871eb4dbb983a 100644
--- a/src/main/java/fr/irstea/associatione/model/Model.java
+++ b/src/main/java/fr/irstea/associatione/model/Model.java
@@ -115,6 +115,21 @@ public class Model {
         }
         return data;
     }
+    
+    public double[] getSubjectiveNorm() {
+        double[] opinionsMeanOnSubjects = getOpinionsMeanOnSubjects();
+        double[] data = new double[individuals.length];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = 0;
+            for (int j = 0; j < data.length; j++) {
+                if (i!=j) {
+                    data[i] += opinionsMeanOnSubjects[j] * individuals[i].getOpinionOnIndividual(j);
+                }
+            }
+            data[i] = data[i] / (data.length - 1);
+        }
+        return data;
+    }
 
     public static void main(String[] args) throws ProcessingException, IllegalArgumentException, IllegalAccessException {
         Parameters parameters = new Parameters(0, 50, 1, new DistorsionFromOpinions(), 1, 0.3);
diff --git a/src/main/java/fr/irstea/associatione/model/ReflectUtils.java b/src/main/java/fr/irstea/associatione/model/ReflectUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..2f6b0e1a0ce0746a70b5107cebdf524230f4f498
--- /dev/null
+++ b/src/main/java/fr/irstea/associatione/model/ReflectUtils.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 dumoulin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package fr.irstea.associatione.model;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author dumoulin
+ */
+public class ReflectUtils {
+
+    private static final Logger LOGGER = Logger.getLogger(ReflectUtils.class.getName());
+
+    /**
+     *
+     * @param type
+     * @param name
+     * @return null if the method wasn't found
+     */
+    public static Method getMethod(Class type, String name) throws NoSuchFieldException {
+        Class current = type;
+        while (current != null) {
+            for (Method m : current.getDeclaredMethods()) {
+                if (m.getName().equals(name)) {
+                    return m;
+                }
+            }
+            current = current.getSuperclass();
+        }
+        throw new NoSuchFieldException("The method " + name + " hasn't been found in the class " + type.getName());
+    }
+
+    /**
+     *
+     * @param method
+     * @param instance
+     * @return null if a problem has occured during the introspection.
+     */
+    public static Object invokeMethod(Method method, Object instance) {
+        boolean old = method.isAccessible();
+        method.setAccessible(true);
+        Object value = null;
+        try {
+            boolean accessible = method.isAccessible();
+            method.setAccessible(true);
+            value = method.invoke(instance);
+            method.setAccessible(accessible);
+        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+            LOGGER.log(Level.SEVERE, "Error during method invocation " + method, ex);
+        }
+        method.setAccessible(old);
+        return value;
+    }
+
+    /**
+     *
+     * @param methodname
+     * @param instance
+     * @return null if a problem has occured during the introspection.
+     */
+    public static Object invokeMethod(String methodname, Object instance) throws NoSuchFieldException {
+        Object value = null;
+        Method method = getMethod(instance.getClass(), methodname);
+        if (method != null) {
+            value = ReflectUtils.invokeMethod(method, instance);
+        }
+        return value;
+    }
+
+    /**
+     *
+     * @param instance
+     * @param path The path of the method to retrieve from the class of the
+     * instance given. The path must contain a dot "." for accessing nested
+     * methods. The element of a list can be accessed by its index. For example
+     * : <tt>elements.2.aMethod</tt>
+     * @return
+     * @throws NoSuchFieldException
+     */
+    public static MethodOnInstance getMethodOnInstance(Object instance, String path) throws NoSuchFieldException {
+        if (path.contains(".")) {
+            String[] nodes = path.split("\\.");
+            for (int i = 0; i < nodes.length - 1; i++) {
+                if (nodes[i].matches("[0-9]*")) {
+                    instance = ((List) instance).get(Integer.parseInt(nodes[i]));
+                } else {
+                    instance = ReflectUtils.invokeMethod(nodes[i], instance);
+                }
+            }
+            path = nodes[nodes.length - 1];
+        }
+        return new MethodOnInstance(instance, getMethod(instance.getClass(), path));
+    }
+
+    public static void invokeMethodFromPath(Object instance, String path) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
+        getMethodOnInstance(instance, path).invoke();
+    }
+
+    /**
+     * Class that wraps a method with an instance that can be invoked.
+     */
+    public static class MethodOnInstance {
+
+        private final Object instance;
+        private final Method method;
+
+        public MethodOnInstance(Object instance, Method field) {
+            this.instance = instance;
+            this.method = field;
+        }
+
+        public Method getMethod() {
+            return method;
+        }
+
+        public Object getInstance() {
+            return instance;
+        }
+
+        public Object invoke() throws IllegalAccessException {
+            return ReflectUtils.invokeMethod(method, instance);
+        }
+    }
+}
diff --git a/src/main/java/fr/irstea/associatione/model/gui/GUI.java b/src/main/java/fr/irstea/associatione/model/gui/GUI.java
index 7103ad99fe8c42d4910de2b5d511744340a66886..2245d0ddfba112cf930a83df0474efdbdfe214cd 100644
--- a/src/main/java/fr/irstea/associatione/model/gui/GUI.java
+++ b/src/main/java/fr/irstea/associatione/model/gui/GUI.java
@@ -20,21 +20,7 @@ import fr.irstea.associatione.model.Model;
 import fr.irstea.associatione.model.Parameters;
 import fr.irstea.associatione.model.ProcessingException;
 import fr.irstea.associatione.model.distorsion.DistorsionFromOpinions;
-import java.awt.GridLayout;
-import java.util.Arrays;
 import javax.swing.JFrame;
-import javax.swing.JPanel;
-import org.jfree.chart.ChartFactory;
-import org.jfree.chart.ChartPanel;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.plot.PlotOrientation;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.xy.StandardXYBarPainter;
-import org.jfree.chart.renderer.xy.XYBarRenderer;
-import org.jfree.data.statistics.HistogramDataset;
-import org.jfree.data.statistics.HistogramType;
-import org.jfree.data.xy.XYSeries;
-import org.jfree.data.xy.XYSeriesCollection;
 
 /**
  *
@@ -43,27 +29,20 @@ import org.jfree.data.xy.XYSeriesCollection;
 public class GUI {
 
     private final JFrame frame;
-    private final JPanel chartsPanel;
+    private final TimeSerieChart timeSerieChart;
     private Model model;
-    private ChartPanel credibilityChartPanel;
-    private final XYSeriesCollection opinionsMeanOnSubjects;
 
     public GUI() {
         frame = new JFrame("test");
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-        this.chartsPanel = new JPanel(new GridLayout(0, 2));
-        frame.setContentPane(chartsPanel);
-        opinionsMeanOnSubjects = new XYSeriesCollection();
+        timeSerieChart = new TimeSerieChart();
+        frame.setContentPane(timeSerieChart.getDisplay());
     }
 
-    public void initCharts() {
-        for (int i = 0; i < model.getParameters().getPopSize(); i++) {
-            opinionsMeanOnSubjects.addSeries(new XYSeries(i));
-        }
-        chartsPanel.removeAll();
-        credibilityChartPanel = new ChartPanel(createHistogram("Credibility", model.getCredibility()));
-        chartsPanel.add(credibilityChartPanel);
-        chartsPanel.add(new ChartPanel(ChartFactory.createXYLineChart("Opinions means on subjects", "timesteps", "opinions", opinionsMeanOnSubjects, PlotOrientation.VERTICAL, false, true, false)));
+    public void initCharts() throws ProcessingException {
+        timeSerieChart.addTimeSerie(model, "getOpinionsMeanOnSubjects", "Opinions", true, true);
+        timeSerieChart.addTimeSerie(model, "getSubjectiveNorm", "Subjective norm", true, true);
+        timeSerieChart.addTimeSerie(model, "getCredibility", "Credibility", true, false);
     }
 
     public void init(Parameters parameters) throws ProcessingException, IllegalArgumentException, IllegalAccessException {
@@ -72,53 +51,15 @@ public class GUI {
         initCharts();
         frame.pack();
         frame.setVisible(true);
-        updatePlots(model.getTimestep());
+        timeSerieChart.updateCharts();
         for (int i = 0; i < 50; i++) {
             model.iter();
-            updatePlots(model.getTimestep());
+            timeSerieChart.updateCharts();
         }
     }
 
-    public void test() {
-        double[] data = new double[]{0.3, 0.3, 0.5, 0.6, 0.65};
-        JFrame f = new JFrame("test");
-        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-        f.setContentPane(new ChartPanel(createHistogram("Credibility", data)));
-        f.pack();
-        f.setVisible(true);
-    }
-
-    public void updatePlots(int timestep) {
-        credibilityChartPanel.setChart(createHistogram("Credibility", model.getCredibility()));
-        double[] data = model.getOpinionsMeanOnSubjects();
-        for (int i = 0; i < data.length; i++) {
-            opinionsMeanOnSubjects.getSeries(i).add(timestep, data[i]);
-        }
-    }
-
-    public static JFreeChart createHistogram(String title, double[] data) {
-        HistogramDataset dataset = new HistogramDataset();
-        dataset.setType(HistogramType.SCALE_AREA_TO_1);
-        dataset.addSeries(title, data, 30);
-        String plotTitle = title;
-        String xaxis = "opinions";
-        String yaxis = "amount";
-        PlotOrientation orientation = PlotOrientation.VERTICAL;
-        boolean show = false;
-        boolean toolTips = false;
-        boolean urls = false;
-        JFreeChart chart = ChartFactory.createHistogram(plotTitle, xaxis, yaxis,
-                dataset, orientation, show, toolTips, urls);
-        XYPlot plot = (XYPlot) chart.getPlot();
-        XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer();
-        renderer.setBarPainter(new StandardXYBarPainter());
-        renderer.setShadowVisible(false);
-        return chart;
-    }
-
     public static void main(String[] args) throws Exception {
         GUI gui = new GUI();
         gui.init(new Parameters(0, 50, 1, new DistorsionFromOpinions(), 1, 0.3));
-
     }
 }
diff --git a/src/main/java/fr/irstea/associatione/model/gui/TimeSerieChart.java b/src/main/java/fr/irstea/associatione/model/gui/TimeSerieChart.java
new file mode 100644
index 0000000000000000000000000000000000000000..b353aed5aa45939ec7285647e85837a33fb678c9
--- /dev/null
+++ b/src/main/java/fr/irstea/associatione/model/gui/TimeSerieChart.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2016 Irstea
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package fr.irstea.associatione.model.gui;
+
+import fr.irstea.associatione.model.Model;
+import fr.irstea.associatione.model.ProcessingException;
+import fr.irstea.associatione.model.ReflectUtils;
+import java.awt.GridLayout;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JPanel;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.StandardXYBarPainter;
+import org.jfree.chart.renderer.xy.XYBarRenderer;
+import org.jfree.data.statistics.HistogramDataset;
+import org.jfree.data.statistics.HistogramType;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+/**
+ *
+ * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr>
+ */
+public class TimeSerieChart {
+
+    private JPanel display;
+    private List<Timeserie> timeseries;
+
+    public static class Timeserie {
+
+        private final String name;
+        private final boolean histogram, series;
+        private final ReflectUtils.MethodOnInstance methodOnInstance;
+        private final List<double[]> timeserie;
+        private final ChartPanel histogramPanel;
+        private final XYSeriesCollection xySeries;
+
+        public Timeserie(Model model, String fetcherPath, String name, boolean histogram, boolean series) throws ProcessingException {
+            this.name = name;
+            this.histogram = histogram;
+            this.series = series;
+            try {
+                this.methodOnInstance = ReflectUtils.getMethodOnInstance(model, fetcherPath);
+                this.timeserie = new ArrayList<>();
+                xySeries = new XYSeriesCollection();
+                histogramPanel = new ChartPanel(createHistogram(name, (double[]) methodOnInstance.invoke()));
+            } catch (NoSuchFieldException | IllegalAccessException ex) {
+                throw new ProcessingException("Error during method retrieval", ex);
+            }
+        }
+
+        private JPanel getHistogram() {
+            return histogramPanel;
+        }
+
+        private JPanel getSeries() {
+            return new ChartPanel(ChartFactory.createXYLineChart(name, "timesteps", name, xySeries, PlotOrientation.VERTICAL, false, true, false));
+        }
+
+        public void add(double[] data) {
+            timeserie.add(data);
+        }
+
+        public void update() throws IllegalAccessException {
+            final double[] data = (double[]) methodOnInstance.invoke();
+            histogramPanel.setChart(createHistogram(name, data));
+            timeserie.add(data);
+            if (xySeries.getSeriesCount() == 0) {
+                for (int i = 0; i < data.length; i++) {
+                    xySeries.addSeries(new XYSeries(i));
+                }
+            }
+            for (int i = 0; i < data.length; i++) {
+                xySeries.getSeries(i).add(timeserie.size() - 1, data[i]);
+            }
+        }
+
+    }
+
+    public TimeSerieChart() {
+        display = new JPanel(new GridLayout(0, 2));
+        timeseries = new ArrayList<>();
+    }
+
+    public JPanel getDisplay() {
+        return display;
+    }
+
+    public void addTimeSerie(Model model, String fetcherPath, String name, boolean histogram, boolean series) throws ProcessingException {
+        final Timeserie timeserie = new Timeserie(model, fetcherPath, name, histogram, series);
+        timeseries.add(timeserie);
+        if (histogram) {
+            display.add(timeserie.getHistogram());
+        }
+        if (series) {
+            display.add(timeserie.getSeries());
+        }
+    }
+
+    public void updateCharts() {
+        for (Timeserie timeserie : timeseries) {
+            try {
+                timeserie.update();
+            } catch (IllegalAccessException ex) {
+                Logger.getLogger(TimeSerieChart.class.getName()).log(Level.SEVERE, null, ex);
+            }
+
+        }
+    }
+
+    public static JFreeChart createHistogram(String title, double[] data) {
+        HistogramDataset dataset = new HistogramDataset();
+        dataset.setType(HistogramType.SCALE_AREA_TO_1);
+        dataset.addSeries(title, data, 30);
+        String plotTitle = title;
+        String xaxis = "opinions";
+        String yaxis = "amount";
+        PlotOrientation orientation = PlotOrientation.VERTICAL;
+        boolean show = false;
+        boolean toolTips = false;
+        boolean urls = false;
+        JFreeChart chart = ChartFactory.createHistogram(plotTitle, xaxis, yaxis,
+                dataset, orientation, show, toolTips, urls);
+        XYPlot plot = (XYPlot) chart.getPlot();
+        XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer();
+        renderer.setBarPainter(new StandardXYBarPainter());
+        renderer.setShadowVisible(false);
+        return chart;
+    }
+
+}