All Downloads are FREE. Search and download functionalities are using the official Maven repository.

repicea.simulation.climate.REpiceaClimateChangeTrend Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
/*
 * This file is part of the repicea-simulation library.
 *
 * Copyright (C) 2009-2019 Mathieu Fortin for Rouge-Epicea
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed with 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 Lesser General Public
 * License for more details.
 *
 * Please see the license at http://www.gnu.org/copyleft/lesser.html.
 */
package repicea.simulation.climate;

import java.security.InvalidParameterException;
import java.util.ArrayList;

import repicea.simulation.climate.REpiceaClimateVariableMap.ClimateVariable;

@SuppressWarnings("serial")
public class REpiceaClimateChangeTrend extends ArrayList {

	public void addSegment(int startDateYr, int endDateYr, REpiceaClimateVariableChangeMap changeMap) {
		if (startDateYr >= endDateYr) {
			throw new InvalidParameterException("The start date must be prior to the end date!");
		}
		if (isEmpty() || getEndDateYr() ==  startDateYr) {
			add(new REpiceaClimateChangeTrendSegment(startDateYr, endDateYr, changeMap));
		} else {
			throw new InvalidParameterException("There is a mismatch between the start date and the end date of the previous segment!");
		}
	}

	/**
	 * Returns the last end date of the trend.
	 * @return an integer
	 */
	public int getEndDateYr() {
		if (isEmpty()) {
			return -1;
		} else {
			return get(size()-1).endDateYr;
		}
	}
	
	/**
	 * Returns the start date of the trend.
	 * @return an integer
	 */
	public int getStartDateYr() {
		if (isEmpty()) {
			return -1;
		} else {
			return get(0).startDateYr;
		}
	}
	
	/**
	 * Provide the change in the variable between the start and the end dates.
	 * @param startDateYr the start date
	 * @param endDateYr the end date
	 * @param variable a ClimateVariable enum
	 * @return the change
	 */
	public double getChangeFromTo(int startDateYr, int endDateYr, ClimateVariable variable) {
		double increase = 0d;
		for (REpiceaClimateChangeTrendSegment segment : this) {
			int nbYears = 0;
			if (startDateYr <= segment.startDateYr && endDateYr > segment.startDateYr) { // then this segment in part or in whole should be considered
				nbYears = endDateYr > segment.endDateYr ? segment.endDateYr - segment.startDateYr : endDateYr - segment.startDateYr;
			} else if (startDateYr <= segment.endDateYr && endDateYr > segment.startDateYr) {
				nbYears = endDateYr > segment.endDateYr ? segment.endDateYr - startDateYr : endDateYr - startDateYr;
			}
			if (segment.changeMap.containsKey(variable)) {
				increase += nbYears * segment.changeMap.get(variable);
			}
		}
		return increase;
	}
	
	/**
	 * Provide the average change over a particular time interval with respect to a reference date.
	 * @param referenceDateYr the reference date
	 * @param startDateYr the start date
	 * @param endDateYr the end date
	 * @param variable a ClimateVariable enum
	 * @return the average change
	 */
	public double getAverageChangeOverThisPeriod(int referenceDateYr, int startDateYr, int endDateYr, ClimateVariable variable) {
		if (startDateYr >= endDateYr) {
			throw new InvalidParameterException("The start date must be prior to the end date!");
		}
		double area = 0d;
		for (REpiceaClimateChangeTrendSegment segment : this) {
			int nbYears = 0;
			double h1,h2;
			if (startDateYr <= segment.startDateYr && endDateYr > segment.startDateYr) { // then this segment in part or in whole should be considered
				int endYear = endDateYr > segment.endDateYr ? segment.endDateYr : endDateYr;
				nbYears = endYear - segment.startDateYr;
				h1 = getChangeFromTo(referenceDateYr, segment.startDateYr, variable);
				h2 = h1 + getChangeFromTo(segment.startDateYr, endYear, variable);
				area += (h1 + h2) * .5 * nbYears;
			} else if (startDateYr <= segment.endDateYr && endDateYr > segment.startDateYr) {
				int endYear = endDateYr > segment.endDateYr ? segment.endDateYr : endDateYr;
				nbYears = endYear - startDateYr;
				h1 = getChangeFromTo(referenceDateYr, startDateYr, variable);
				h2 = h1 + getChangeFromTo(startDateYr, endYear, variable);
				area += (h1 + h2) * .5 * nbYears;
			} 
		}
		return area / (endDateYr - startDateYr);
	}
	
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy