function [ ModelSpec, DataSpec, PriorParams ] = setupmodel( parametersFile, SpikeTrainsData, PositionData )
    % Setup all structures to do with specifying the model, and initialise
    % parameter structures.
    %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % DETAILS
    %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % CHANGELOG
    % 01.10.2014 - copied from old version.
    %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    if nargin < 1,
        error('No parameters file supplied!')
    end
    if nargin > 1,
        if nargin < 3,
            error('Insufficient parameters!');
        end
        haveData = true;
    else
        haveData = false;
    end
    if exist(parametersFile, 'file') ~= 2,
        error('You must supply the filename of a parameters file (.m file) on the search path!')
    end
    
    % Load script containing parameter values.
    % Chop off any '.m' ending.
    if strcmp(parametersFile((end - 1):end) , '.m'),
        parametersFile = parametersFile(1:(end - 2));
    end
    eval(sprintf('%s;', parametersFile));

    if (~haveData) && (~simulateData),
        error('Insufficient arguments! Have you run setupdata yet?')
    end

    % Set default values where we can.
    if ~exist('modelIndicator', 'var'),
        modelIndicator = 2;
    end
    if ~exist('maxNStates', 'var'),
        maxNStates = 10;
    end
    if ~exist('estimateNStates', 'var'),
        estimateNStates = true;
    end
    if ~exist('useAugStateModel', 'var'),
        useAugStateModel = true;
    end
    if estimateNStates && ~useAugStateModel,
        error('In order to estimate the number of states we must use the augmented state model!')
    end
    if ~exist('stateDimPriorIndicator', 'var'),
        stateDimPriorIndicator = 1;
    end
    if ~exist('initialStateModelIndicator', 'var'),
        initialStateModelIndicator = 3;
    end
    if ~exist('dominatingRateScalingFactor', 'var'),
        dominatingRateScalingFactor = 2;
    end
    if ~exist('spikeTrainModelIndicator', 'var'),
        spikeTrainModelIndicator = 1;
    end
    if ~exist('positionModelIndicator', 'var'),
        positionModelIndicator = 1;
    end
    if ~exist('positionJitterModelIndicator', 'var'),
        positionJitterModelIndicator = 2;
    end
    if ~exist('initialStateDistPriorIndicator', 'var'),
        initialStateDistPriorIndicator = 1;
    end
    if ~exist('jumpRatePriorIndicator', 'var'),
        jumpRatePriorIndicator = 2;
    end
    if ~exist('jumpRateGammaHyperparams', 'var'),
        jumpRateGammaHyperparams = [];
    end
    if ~exist('spikeRatePriorIndicator', 'var'),
        spikeRatePriorIndicator = 2;
    end
    if ~exist('stateFieldSizeAsProportionOfShortestMazeDim', 'var'),
        stateFieldSizeAsProportionOfShortestMazeDim = 1 / 2;
    end
    if ~exist('nPriorObservationsForPositionModel', 'var'),
        nPriorObservationsForPositionModel = 2;
    end
    if ~exist('priorSpatialCorrelationCoef', 'var'),
        priorSpatialCorrelationCoef = 0;
    end
    if ~exist('positionObsErrorPriorIndicator', 'var'),
        positionObsErrorPriorIndicator = 3;
    end
    if ~exist('positionObsErrorTolerance', 'var'),
        positionObsErrorTolerance = 0.01;
    end
    if ~exist('jitterPriorIndicator', 'var'),
        jitterPriorIndicator = 3;
    end
    if ~exist('jitterGammaHyperparams', 'var'),
        jitterGammaHyperparams = [1, 1];
    end
    if ~exist('randomWalkState', 'var'),
        randomWalkState = true;
    end
    if ~exist('driftRatePriorLowerBound', 'var'),
        driftRatePriorLowerBound = 0;
    end
    if ~exist('driftRatePriorUpperBound', 'var'),
        driftRatePriorUpperBound = 1;
    end
    if (positionModelIndicator == 1) && (positionJitterModelIndicator == 3),
        error('Cannot use dependent jitter model in cts space model!')
    end
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    ModelSpec.modelIndicator = modelIndicator;
    ModelSpec.maxNStates = maxNStates;
    ModelSpec.estimateNStates = estimateNStates;
    ModelSpec.useAugStateModel = useAugStateModel;
    ModelSpec.initialStateModelIndicator = initialStateModelIndicator;
    ModelSpec.dominatingRateScalingFactor = dominatingRateScalingFactor;
    ModelSpec.stateDimPriorIndicator = stateDimPriorIndicator;
    ModelSpec.initialStateDistPriorIndicator = initialStateDistPriorIndicator;
    ModelSpec.jumpRatePriorIndicator = jumpRatePriorIndicator;
    ModelSpec.jumpRateGammaHyperparams = jumpRateGammaHyperparams;
    ModelSpec.spikeTrainModelIndicator = spikeTrainModelIndicator;
    ModelSpec.nParticles = nParticles;
    if PositionData.havePositionData,
        ModelSpec.positionModelIndicator = positionModelIndicator;
    else
        ModelSpec.positionModelIndicator = 0;
    end
    if ModelSpec.spikeTrainModelIndicator > 0,
        ModelSpec.spikeRatePriorIndicator = spikeRatePriorIndicator;
    end
    if ModelSpec.positionModelIndicator > 0,
%         if ModelSpec.modelIndicator == 2,
            ModelSpec.positionJitterModelIndicator = positionJitterModelIndicator;
            ModelSpec.positionObsErrorPriorIndicator = positionObsErrorPriorIndicator;
            ModelSpec.positionObsErrorTolerance = positionObsErrorTolerance;
            ModelSpec.jitterPriorIndicator = jitterPriorIndicator;
            ModelSpec.jitterGammaHyperparams = jitterGammaHyperparams;
            ModelSpec.driftRatePriorLowerBound = driftRatePriorLowerBound;
            ModelSpec.driftRatePriorUpperBound = driftRatePriorUpperBound;
%         end
        ModelSpec.stateFieldSizeAsProportionOfShortestMazeDim = stateFieldSizeAsProportionOfShortestMazeDim;
        ModelSpec.nPriorObservationsForPositionModel = nPriorObservationsForPositionModel;
        ModelSpec.priorSpatialCorrelationCoef = priorSpatialCorrelationCoef;
    end
    ModelSpec.randomWalkState = randomWalkState;
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    if haveData,
        DataSpec.haveSpikeTrainsData = SpikeTrainsData.haveSpikeTrainsData;
        if DataSpec.haveSpikeTrainsData,
            DataSpec.nSpikeTrains = SpikeTrainsData.nSpikeTrains;
            DataSpec.analysisInterval = SpikeTrainsData.analysisInterval;
            DataSpec.startTime = SpikeTrainsData.startTime;
            DataSpec.endTime = SpikeTrainsData.endTime;
            if ModelSpec.modelIndicator == 1,
                DataSpec.updateStepInterval = SpikeTrainsData.updateStepInterval;
                DataSpec.nUpdateSteps = SpikeTrainsData.nUpdateSteps;
            end
        end
        DataSpec.havePositionData = PositionData.havePositionData;
        if DataSpec.havePositionData,
            if ~DataSpec.haveSpikeTrainsData,
                DataSpec.analysisInterval = PositionData.analysisInterval;
                DataSpec.startTime = PositionData.startTime;
                DataSpec.endTime = PositionData.endTime;
                if ModelSpec.modelIndicator == 1,
                    DataSpec.updateStepInterval = PositionData.updateStepInterval;
                    DataSpec.nUpdateSteps = PositionData.nUpdateSteps;
                end
            end
            DataSpec.maxSpatialDimensionSize = PositionData.maxSpatialDimensionSize;
            DataSpec.discreteYDim = PositionData.discreteYDim;
            DataSpec.discreteXDim = PositionData.discreteXDim;
            DataSpec.nValidDiscretePositions = PositionData.nValidDiscretePositions;
            DataSpec.spatialBinWidth = PositionData.spatialBinWidth;
            DataSpec.posObsInterval = PositionData.posObsInterval;
        end
    else
        DataSpec.analysisInterval = simAnalysisInterval;
        DataSpec.startTime = simAnalysisInterval(1);
        DataSpec.endTime = simAnalysisInterval(2);
        DataSpec.haveSpikeTrainsData = simulateSpikeTrains;
        if DataSpec.haveSpikeTrainsData,
            DataSpec.nSpikeTrains = nSimSpikeTrains;
        end
        DataSpec.havePositionData = simulatePosition;
        if DataSpec.havePositionData,
            load(positionDataFilename);
            DataSpec.maxSpatialDimensionSize = eval([positionDataStructName, '.maxSpatialDimensionSize']);
            DataSpec.discreteYDim = eval([positionDataStructName, '.discreteYDim']);
            DataSpec.discreteXDim = eval([positionDataStructName, '.discreteXDim']);
            DataSpec.nValidDiscretePositions = eval([positionDataStructName, '.nValidDiscretePositions']);
            DataSpec.spatialBinWidth = eval([positionDataStructName, '.spatialBinWidth']);
            DataSpec.posObsInterval = eval([positionDataStructName, '.posObsInterval']);
        end
    end
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    if ModelSpec.useAugStateModel,
        ModelSpec.maxNAugStates = ModelSpec.maxNStates * (ModelSpec.maxNStates + 1) / 2;
        ModelSpec.augStateComponents = formaugmentedstatecomponents( ModelSpec.maxNStates );
        ModelSpec.stateSpaceTransformation = formstatespacedimensiontransformation( ModelSpec.maxNStates );
        ModelSpec = setupaugmentedstateindices( ModelSpec );
    end
    PriorParams = initialisepriordistributions(ModelSpec, DataSpec);
    
end