def stretched_exponential(w=8, l=10, save=False): field = 'WELTON' prod = get_production('UK')[field].dropna() fit_parms = get_fit_parms('UK', '2013-02-01').ix[field] tau, beta, y0 = fit_parms['tau'], fit_parms['beta'], fit_parms['y0'] x, y = prepare_xy(prod) yfit = y0 * exp(-(x/abs(tau))**beta) fit = Series(yfit, index=prod.index) lower_cutoff = '1996-08-01' fig = plt.figure(figsize=(w, l)) ax = fig.gca() prod.plot(ax=ax, marker='x', ls='') l1 = ax.get_lines()[0] l2, = ax.plot(fit[lower_cutoff:].index, fit[lower_cutoff:], '-k') ax.legend([l1, l2], [field.lower().capitalize() + ' (UK)', r'$y = y0 + exp(-(\frac{t}{\tau})^\beta)$']) ax.set_xlabel('Time') ax.set_ylabel('Prodction [barrels/day]') fig.tight_layout() if save: os.chdir('article') fig.savefig('stretched_exponential.pdf') os.chdir('..') else: plt.show()
def extend_production(oil_field, fit_parms, fit_style='stretched exponential'): """Extend the production of a given oil field into the future, given the fit_parms and the fit_style. """ start = oil_field.index[-1] + MonthBegin() if fit_style == 'stretched exponential': tau, beta, yo = fit_parms lifetime = abs(tau) * (-log(MIN_PROD/yo)) ** (1./beta) try: end = oil_field.dropna().index[0] + lifetime * Day() except: lifetime = 200 * 365 if lifetime > 200 * 365 else lifetime end = oil_field.dropna().index[0] + lifetime * Day() end = MonthBegin().rollback(end) + DateOffset(months=1) future = date_range(start, end, freq='MS') nfuture = len(future) if nfuture == 0: return oil_field oil_field = concat((oil_field, Series(len(future) * [1], index=future, name=oil_field.name))) x, y = prepare_xy(oil_field) if fit_style == 'stretched exponential': y = yo * exp(sign(tau) * (x[-nfuture:] / abs(tau))**beta) oil_field[-nfuture:] = y return oil_field
def perturb_fit_parms(fields=GOOD_FITS, fit_style='stretched exponential', xmin='custom', perturbation=0.1, step=0.01): """We perturb the parameters of the fit and look how flat the cost_function is. We will see how much perturbation the parameters can take for a fixed difference in the value of the cost function (ex: 10%). Or the reverse: fix the parms and look how the cost function varies. """ (fit_parms, oil_fields) = get_fit_parms(fields=fields, fit_style=fit_style, xmin=xmin) def get_xmin(field, MAXES): return MAXES[field] if field in MAXES.keys() else 'max' res = {} for field_name in fit_parms.keys(): tau, beta, yo = fit_parms[field_name] changes = arange(1.-perturbation, 1+perturbation+step, step) taus = changes * tau betas = changes * beta xs, ys, zs = [], [], [] for tau in taus: for beta in betas: xs.append(tau) ys.append(beta) _x, _y = oil_fields[field_name], None x_, y_ = prepare_xy(_x, _y) xmin = xmin2xmin(get_xmin(field_name, MAXES), x_, y_, _x, _y) x, y = chop_xy(x_, y_, xmin, 'None') zs.append(cost_function((tau, beta, yo), x, y)) res[field_name] = (xs, ys, zs) return res
def _extend_production(_prod, fit_parm, fit_style='stretched exponential'): """Extend the production of a given oil field into the future, given the fit_parms and the fit_style. Args: _prod -> Series. The time series of production of a given field. fit_parm -> tuple. The fit parameters for the particular field. Ex: (tau, beta, y0) fit_style -> str. The string representing the fit style. Return: _extended_prod -> Series. The time series of the extended production (past + future) of the field. """ #_prod is a time series of production i.e. the production of an individual #field extension_start = _prod.index[-1] + MonthBegin() extraction_start = _prod.dropna().index[0] if fit_style == 'stretched exponential': tau, beta, yo = fit_parm #The number of days until the production reaches MIN_PROD since the #beginning of the extraction. lifetime = abs(tau) * (-log(MIN_PROD/yo)) ** (1./beta) #Timestamp don't extend beyond 2262-04-11 max_lifetime = (MAX_DATE - extraction_start).days lifetime = min(lifetime, max_lifetime) elif fit_style == 'power-law': print 'power-law not implemented yet for extend_production()' 1/0 extension_end = extraction_start + lifetime * Day() #we round end down to the beginning of the month (so that we stay for sure #with end < 2262-04-11 extension_end = MonthBegin().rollback(extension_end) future = date_range(extension_start, extension_end, freq='MS') nfuture = len(future) #Are we already very close (or below) MIN_PROD? if nfuture == 0: return _prod #subtlety: I need to initialize _extended_prod with something for the #extended part (in this case 42). Else, the whole extended part will be #dropped in prepare_xy. _extended_prod = concat((_prod, Series(nfuture*[42], index=future, name=_prod.name))) x, y = prepare_xy(_extended_prod) if fit_style == 'stretched exponential': #overwriting the placeholder (nfuture*[42]) y = yo * exp(sign(tau) * (x[-nfuture:] / abs(tau))**beta) _extended_prod[-nfuture:] = y return _extended_prod
def extend_productions(fields=GOOD_FITS, fit_parms='None', fit_style='stretched exponential', xmin='custom', freq='M'): """Extends the production of the different oil fields into the future, given the fit style. """ if fit_parms == 'None': fit_parms, oil_fields = get_fit_parms(fields=fields, fit_style=fit_style, xmin=xmin) else: fit_parms, oil_fields = fit_parms extensions = [] for field in fields: oil_field = oil_fields[field] oil_field = extend_production(oil_field, fit_parms[field], 'stretched exponential') start = oil_field.index[-1] + MonthBegin() tau, beta, yo = fit_parms[field] lifetime = abs(tau) * (-log(MIN_PROD/yo)) ** (1./beta) try: end = oil_field.dropna().index[0] + lifetime * Day() except: end = Timestamp('01-01-2260') end = MonthBegin().rollback(end) + DateOffset(months=1) future = date_range(start, end, freq='MS') nfuture = len(future) if nfuture == 0: extensions.append(oil_field) continue oil_field = concat((oil_field, Series(len(future) * [1], index=future, name=oil_field.name))) x, y = prepare_xy(oil_field) #from erpy.ipshell import ipshell #ipshell('') if fit_style == 'stretched exponential': y = yo * exp(sign(tau) * (x[-nfuture:] / abs(tau))**beta) oil_field[-nfuture:] = y extensions.append(oil_field) return concat(extensions, axis=1)