public Visualization(String datasetTitle, int width, int height,
			LearningData fileData, LearningData labelledData, int inputs, int maxIterations, int k) {

		this.datasetTitle = datasetTitle;
		this.width = width;
		this.height = height;
		this.fileData = fileData;
		this.labelledData = labelledData;
		this.inputs = inputs;

		int g = 11;

		// Creates a Matrix Topology with width columns and height rows
		MatrixTopology topology = new MatrixTopology(width, height);
		
		// Set radius
		topology.setRadius(3);
		
		// Defines max value of neuron weights
		double[] maxWeight = new double[inputs];
		
		for (int i = 0; i < maxWeight.length; i++){
			maxWeight[i] = 10;
		}

		// Creates a network with a # of inputs, max weight of neurons and a
		// topology
		DefaultNetwork network = new DefaultNetwork(inputs, maxWeight, topology);

		// Create LearningFactorFunctionalModel
		LinearFunctionalFactor linearFunctionalFactor = new LinearFunctionalFactor(
				0.8, maxIterations);

		// Set the Gauss Neighborhood Function radius to 3
		GaussNeighbourhoodFunction gaussFunction = new GaussNeighbourhoodFunction(3);

		// Set learning Function - Winner Take Most Function
		WTMLearningFunction learning = new WTMLearningFunction(network,
				maxIterations, new EuclidesMetric(), fileData,
				linearFunctionalFactor, gaussFunction);

		// Start learning process
		learning.learn();
		
		
		// Create EuclidesMetric
		EuclidesMetric metric = new EuclidesMetric();

		// Store all labels of instances
		int[] labels = storeInstanceLabels(fileData, labelledData);
		
		int[] label = new int[width * height];
		double[] lowestValues = new double[g];

		// Loop for each neuron
		for (int currentNeuronIdx = 0; currentNeuronIdx < network.getNumbersOfNeurons(); currentNeuronIdx++) {

			// Initialize containers
			double[] distances = new double[fileData.getDataSize()];
			Stack<Integer> indexes = new Stack<Integer>();
			double[] weightOfCurrentNeuron = network
					.getNeuron(currentNeuronIdx).getWeight();
			Arrays.fill(lowestValues, Integer.MAX_VALUE);

			distances = getEuclideanDistances(distances, fileData, metric, weightOfCurrentNeuron);
			lowestValues = getLowestValues(lowestValues, fileData, distances, indexes, g);
			int[] cl = getLabels(indexes, g, labels);
			HashMap<Integer, Integer> frequencyCount = getFrequencyCount(cl);
			label[currentNeuronIdx] = getMostFrequent(frequencyCount);
		}
		
		Instances instances = new NeuronsToInstance().convert(network, "Dataset", inputs);
        Kmeans kmeans = new Kmeans(instances, k);
        int[] clusters = kmeans.getAssignments();
        
        ArrayList<ClusterAndLabel> visualization = new ArrayList<Visualization.ClusterAndLabel>();
        for (int i = 0; i < clusters.length; i++){
        	ClusterAndLabel clusterAndLabelInstance = new ClusterAndLabel(clusters[i], labels[i]);
        	visualization.add(clusterAndLabelInstance);
        }
        
        
        Collections.sort(visualization, new Comparator<ClusterAndLabel>() {
            @Override
            public int compare(ClusterAndLabel a, ClusterAndLabel b)
            {
            	if (a.cluster < b.cluster) return -1;
            	if (a.cluster == b.cluster) {
            		if (a.label < b.label) return -1;
            		if (a.label == b.label) return 0;
            		if (a.label > b.label) return 1;
            	}
            	if (a.cluster > b.cluster) return 1;
                return 0;
            }
        });
        
        
        produceHTMLvisualization(clusters, labels, datasetTitle, width, height, maxIterations);
  	}