Ejemplo n.º 1
0
def test_all_parameters_fixed_predict_no_new_data(model_name, fitted_model):
    """Do not predict, sans new data, when all passed parameters were fixed.
    
    This only works when the model object had fit run, and predictions
    can be from the fitted data.
    """
    all_parameters = fitted_model.get_params()
    new_model = utils.load_model(model_name)(parameters=all_parameters)
    with pytest.raises(TypeError):
        new_model.predict()
Ejemplo n.º 2
0
def test_no_nan_in_observations_predict():
    """the observation data.frame, either in fitting or prediction,
    should not have any NA
    
    """
    single_model = utils.load_model('ThermalTime')()

    obs_with_nan = obs.copy(deep=True)
    obs_with_nan['doy'][1] = np.nan

    with pytest.raises(ValueError):
        single_model.fit(obs_with_nan, predictors, optimizer_params='testing')
Ejemplo n.º 3
0
def test_predict_with_nan():
    """model.predict() method should work with nan in obs.doy
    column. see https://github.com/sdtaylor/pyPhenology/issues/105
    """
    single_model = utils.load_model('ThermalTime')()
    single_model.fit(obs, predictors, optimizer_params='testing')

    obs_with_nan = obs.copy(deep=True)
    obs_with_nan['doy'] = np.nan
    p_with_nan = single_model.predict(obs_with_nan, predictors)
    p = single_model.predict(obs, predictors)

    assert np.all(p == p_with_nan)
Ejemplo n.º 4
0
def test_estimate_all_but_one_parameter(model_name, fitted_model):
    """Estimate only a single parameter.
    
    The end result should be the same as what as passed
    """
    all_parameters = fitted_model.get_params()
    fixed_param, fixed_value = all_parameters.popitem()
    new_model = utils.load_model(model_name)(parameters={
        fixed_param: fixed_value
    })
    new_model.fit(obs, predictors, optimizer_params='testing', debug=True)
    new_value = new_model.get_params()[fixed_param]

    assert new_value == fixed_value
Ejemplo n.º 5
0
def test_brute_force(model_name, fitted_model):
    """Test brute force optimization"""

    new_model = utils.load_model(model_name)()
    new_model.fit(obs, predictors, method='BF', optimizer_params='testing')
    assert len(new_model.predict()) == len(obs)
Ejemplo n.º 6
0
def test_do_not_predict_wihout_fit(model_name, fitted_model):
    """Do not predict on unfitted model"""
    model = utils.load_model(model_name)()
    with pytest.raises(RuntimeError):
        model.predict(obs, predictors)
Ejemplo n.º 7
0
def test_error_on_bad_parameter_names(model_name, fitted_model):
    """Expect error when unknown parameter name is used"""
    with pytest.raises(RuntimeError):
        utils.load_model(model_name)(parameters={'not_a_parameter': 0})
Ejemplo n.º 8
0
    'initial_params': {
        'num_bootstraps': 10,
        'core_model': models.ThermalTime
    }
})

# The rest can all be tested the same way
model_names = [
    'Uniforc', 'Unichill', 'ThermalTime', 'Alternating', 'MSB', 'Linear',
    'Sequential'
]

for name in model_names:
    model_test_cases.append({
        'model_name': name,
        'model_func': utils.load_model(name),
        'fit_params': {
            'optimizer_params': 'testing',
            'debug': True
        },
        'initial_params': {}
    })

divider = '#' * 90

print(divider)
print('Model test cases')
print(divider)

for test_case in model_test_cases:
    model_name = test_case['model_name']
Ejemplo n.º 9
0
def test_all_parameters_fixed_fit(model_name, fitted_model):
    """Do not attempt to fit a model when all passed parameters are fixed"""
    all_parameters = fitted_model.get_params()
    new_model = utils.load_model(model_name)(parameters=all_parameters)
    with pytest.raises(RuntimeError):
        new_model.fit(obs, predictors, optimizer_params='testing', debug=True)
Ejemplo n.º 10
0
from pyPhenology import utils
import pytest
import numpy as np

obs, predictors = utils.load_test_data()

core_model_names = [
    'Uniforc', 'Unichill', 'ThermalTime', 'Alternating', 'MSB', 'Linear',
    'Sequential', 'M1', 'Naive', 'FallCooling'
]

# Setup a list of (model_name, fitted_model object)
fitted_models = [
    utils.load_model(model_name)() for model_name in core_model_names
]
[
    model.fit(obs, predictors, optimizer_params='testing')
    for model in fitted_models
]

model_test_cases = list(zip(core_model_names, fitted_models))

#########################################################


@pytest.mark.parametrize('model_name, fitted_model', model_test_cases)
def test_predict_output_length(model_name, fitted_model):
    """Predict output length should equal input length"""

    assert len(fitted_model.predict()) == len(obs)
Ejemplo n.º 11
0
def test_save_and_load_model(model_name, fitted_model):
    """Load a saved model by passing file as parameters arg"""

    fitted_model.save_params('model_params.json', overwrite=True)
    loaded_model = utils.load_model(model_name)(parameters='model_params.json')
    assert fitted_model.get_params() == loaded_model.get_params()
Ejemplo n.º 12
0
from pyPhenology import utils

observations, temp = utils.load_test_data(name='vaccinium')
import pandas as pd
import time

models_to_use = ['ThermalTime', 'Alternating', 'Uniforc', 'MSB', 'Unichill']
methods_to_use = ['DE', 'BF']
sensible_defaults = ['testing', 'practical', 'intensive']

timings = []
for m in models_to_use:
    for optimizer_method in methods_to_use:
        for s_default in sensible_defaults:
            model = utils.load_model(m)()

            start_time = time.time()
            model.fit(observations,
                      temp,
                      method=optimizer_method,
                      optimizer_params=s_default)
            fitting_time = round(time.time() - start_time, 2)

            num_parameters = len(model.get_params())

            timings.append({
                'model': m,
                'num_parameters': num_parameters,
                'method': optimizer_method,
                'sensible_default': s_default,
                'time': fitting_time
Ejemplo n.º 13
0
observations_test = observations[0:10]
observations_train = observations[10:]


# AIC based off mean sum of squares
def aic(obs, pred, n_param):
    return len(obs) * np.log(np.mean((obs - pred)**2)) + 2 * (n_param + 1)


best_aic = np.inf
best_base_model = None
best_base_model_name = None

for model_name in models_to_test:
    Model = utils.load_model(model_name)
    model = Model()
    model.fit(observations_train, predictors, optimizer_params='practical')

    model_aic = aic(obs=observations_test.doy.values,
                    pred=model.predict(observations_test, predictors),
                    n_param=len(model.get_params()))

    if model_aic < best_aic:
        best_model = model
        best_model_name = model_name
        best_aic = model_aic

    print('model {m} got an aic of {a}'.format(m=model_name, a=model_aic))

print('Best model: {m}'.format(m=best_model_name))
Ejemplo n.º 14
0
from pyPhenology import utils, models
import pytest
import numpy as np

obs, predictors = utils.load_test_data()
Model = utils.load_model('ThermalTime')
model = Model()
#####################################################
# Tests for other things besides the core model fitting/prediction


def test_basinhopping_method():
    model.fit(obs, predictors, method='BH', optimizer_params='testing')
    assert len(model.predict()) == len(obs)


def test_bruteforce_method():
    model.fit(obs, predictors, method='BF', optimizer_params='testing')
    assert len(model.predict()) == len(obs)


def test_daylength_util():
    """daylength equation from julian day & latitude.
    
    Numbers confirmed via http://www.solartopo.com/daylength.htm
    """
    d = models.utils.transforms.daylength(np.array([30, 90, 180]),
                                          np.array([20, 30, 40]))
    np
    assert np.all(np.round(d, 1) == np.array([11.1, 12.3, 14.8]))
Ejemplo n.º 15
0
def test_invalid_model_name():
    with pytest.raises(TypeError):
        utils.load_model(123)
Ejemplo n.º 16
0
def test_all_parameters_fixed_predict_new_data(model_name, fitted_model):
    """Predict , with new data, when all passed parameters were fixed"""
    all_parameters = fitted_model.get_params()
    new_model = utils.load_model(model_name)(parameters=all_parameters)
    assert len(new_model.predict(obs, predictors)) == len(obs)
Ejemplo n.º 17
0
def test_unknown_model_name():
    with pytest.raises(ValueError):
        utils.load_model('asdf')
Ejemplo n.º 18
0
def run():
    divider='#'*90
    
    config = tools.load_config()
    
    today = datetime.datetime.today().date()
    
    land_mask = xr.open_dataset(config['mask_file'])
    
    print(divider)
    print('Applying phenocam phenology models - ' + str(today))
    
    doy_0 = np.datetime64('2018-01-01')
    
    current_climate_forecast_files = glob.glob(config['current_forecast_folder']+'*.nc')
    
    print(str(len(current_climate_forecast_files)) + ' current climate forecast files: \n' + str(current_climate_forecast_files))
    
    print(divider)
    
    # Load the climate forecasts
    
    current_climate_forecasts = [xr.open_dataset(f) for f in current_climate_forecast_files]
    
    for i, forecast_info in enumerate(phenocam_models):
        model_nickname = forecast_info['nickname']
        model_parameters = forecast_info['parameters']
        base_model_name = forecast_info['base_model']
        Model = utils.load_model(base_model_name)
        model = Model(parameters=model_parameters)
        
        print('attempting phenocam model ' + model_nickname)
        #TODO: use tools.phenology_tools stuff here
        ensemble = []
        for climate in current_climate_forecasts:
            doy_series =  pd.TimedeltaIndex(climate.time.values - doy_0, freq='D').days.values
            
            ensemble.append(model.predict(to_predict = climate.tmean.values, 
                                                  doy_series=doy_series))
        
        ensemble = np.array(ensemble).astype(np.float)
        # apply nan to non predictions
        ensemble[ensemble==999]=np.nan
        
        prediction = np.mean(ensemble, axis=0)
        prediction_sd = np.std(ensemble, axis=0)
        
        # extend the axis by 1 to match the xarray creation
        prediction = np.expand_dims(prediction, axis=0)
        prediction_sd = np.expand_dims(prediction_sd, axis=0)
        
        forecast = xr.Dataset(data_vars = {'doy_prediction':(('model', 'lat','lon'), prediction),
                                                   'doy_sd':(('model', 'lat','lon'), prediction_sd)},
                                      coords = {'model':[model_nickname],
                                                'lat':land_mask.lat, 'lon':land_mask.lon})
        forecast = forecast.chunk({'lat':50,'lon':50})
    
        if i==0:
            phenocam_forecasts = forecast
        else:
            phenocam_forecasts = xr.merge([phenocam_forecasts,forecast])
    
    print(divider)
    print('phenocam phenology forecast final processing')
    
    current_season = tools.current_growing_season(config)
    
    provenance_note = \
    """Forecasts for plant phenology of select species flowering and/or leaf out
    times for the {s} season. Made on {t} from NOAA CFSv2
    forecasts downscaled using PRISM climate data.
    Phenocam models built by Eli Melaas. 
    """.format(s=current_season, t=today)
    
    phenocam_forecasts.attrs['note']=provenance_note
    phenocam_forecasts.attrs['issue_date']=str(today)
    phenocam_forecasts.attrs['crs']='+init=epsg:4269'
    
    forecast_filename = config['phenology_forecast_folder']+'phenocam_phenology_forecast_'+str(today)+'.nc'
    
    phenocam_forecasts = phenocam_forecasts.chunk({'lat':50,'lon':50})
    phenocam_forecasts.to_netcdf(forecast_filename, encoding={'doy_prediction':{'zlib':True,
                                                                                'complevel':4, 
                                                                                'dtype':'int32', 
                                                                                'scale_factor':0.001,  
                                                                                '_FillValue': -9999},
                                                                      'doy_sd':{'zlib':True,
                                                                                'complevel':4, 
                                                                                'dtype':'int32', 
                                                                                'scale_factor':0.001,  
                                                                                '_FillValue': -9999}})

    # Return filename of final forecast file for use by primary script
    return forecast_filename