@Override
    protected void runImpl() throws ExecutionFailedException {
        List<List<Long>> features = new ArrayList<List<Long>>();

        for (File featuresFile : featuresFiles.get()) {
            try {
                features.add(readVector(featuresFile));
            } catch (IOException e) {
                throw new ExecutionFailedException("Failed to read features from " + featuresFile);
            }
        }

        int cnt = features.size();
        double[][] distMatrix = new double[cnt][cnt];

        for (int i = 0; i < cnt; i++) {
            for (int j = i + 1; j < cnt; j++) {
                distMatrix[i][j] = brayCurtisDistance(features.get(i), features.get(j));
                distMatrix[j][i] = distMatrix[i][j];
            }
        }

        String matrixPath = matrixFile.get().getPath().replace("$DT", startTimestamp);
        String[] names = null;
        if (!withoutNames.get()) {
            names = new String[featuresFiles.get().length];
            for (int i = 0; i < names.length; i++) {
                names[i] = featuresFiles.get()[i].getName();
                names[i] = FileUtils.removeExtension(names[i], "vec");
            }
        }

        try {
            printMatrix(distMatrix, matrixPath, names, null, outputFormat.get());
            info("Distance matrix printed to " + matrixPath);
        } catch (FileNotFoundException e) {
            throw new ExecutionFailedException("Failed to print matrix to " + matrixPath);
        }
        matrixFile.set(new File(matrixPath));
    }