Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import pandas as pd | |
| import numpy as np | |
| import seaborn as sns | |
| from google.cloud import bigquery | |
| from google.oauth2 import service_account | |
| import os | |
| import json | |
| import matplotlib.pyplot as plt | |
| from scipy.optimize import curve_fit | |
| json_key_path = "/Users/rianrachmanto/pypro/bigquery/intricate-idiom-379506-1454314d9d25.json" | |
| with open(json_key_path) as f: | |
| credentials_info = json.load(f) | |
| credentials = service_account.Credentials.from_service_account_info(credentials_info) | |
| client = bigquery.Client(credentials=credentials) | |
| QUERY = """ | |
| SELECT | |
| DATEPRD, | |
| NPD_WELL_BORE_NAME, | |
| BORE_OIL_VOL, | |
| BORE_GAS_VOL, | |
| BORE_WAT_VOL | |
| FROM `intricate-idiom-379506.volveprod.volveprod` | |
| WHERE | |
| BORE_OIL_VOL IS NOT NULL | |
| AND BORE_GAS_VOL IS NOT NULL | |
| AND BORE_WAT_VOL IS NOT NULL | |
| ORDER BY | |
| NPD_WELL_BORE_NAME ASC, DATEPRD DESC; | |
| """ | |
| # Run the query using the client | |
| query_job = client.query(QUERY) | |
| st.set_option('deprecation.showPyplotGlobalUse', False) | |
| st.title("DECLINE CURVE ANALYSIS (DCA)") | |
| # Create data handler function | |
| def data_handler(query_job): | |
| results = query_job.result() | |
| df = results.to_dataframe() | |
| st.write(df.head()) | |
| # Ensure df_fil is a copy to avoid SettingWithCopyWarning | |
| df_fil = df[(df['BORE_OIL_VOL'] > 0) & (df['BORE_GAS_VOL'] > 0) & (df['BORE_WAT_VOL'] > 0)].copy() | |
| df_fil.loc[:, 'DATEPRD'] = pd.to_datetime(df_fil['DATEPRD']) | |
| sns.set_theme(style="darkgrid") | |
| st.write(sns.relplot( | |
| data=df_fil, | |
| x="DATEPRD", y="BORE_OIL_VOL", col="NPD_WELL_BORE_NAME", hue="NPD_WELL_BORE_NAME", | |
| kind="line", palette="crest", linewidth=4, zorder=5, | |
| col_wrap=2, height=3, aspect=1.5, legend=False | |
| ).fig) | |
| # Create a dataframe for monthly average | |
| df_monthly = df_fil.groupby(['NPD_WELL_BORE_NAME', pd.Grouper(key='DATEPRD', freq='M')]).mean() | |
| df_monthly = df_monthly.reset_index() | |
| df_monthly_24 = df_monthly[df_monthly['DATEPRD'] >= '2015-01-01'] | |
| st.title("Monthly Average") | |
| sns.set_theme(style="darkgrid") | |
| st.write(sns.relplot( | |
| data=df_monthly_24, | |
| x="DATEPRD", y="BORE_OIL_VOL", col="NPD_WELL_BORE_NAME", hue="NPD_WELL_BORE_NAME", | |
| kind="line", palette="crest", linewidth=4, zorder=5, | |
| col_wrap=2, height=3, aspect=1.5, legend=False | |
| ).fig) | |
| return df_monthly_24 | |
| df_monthly_24 = data_handler(query_job) | |
| # Add a "Forecast" button | |
| if st.button("Forecast"): | |
| # Create an empty dictionary to store dataframes | |
| well_dataframes = {} | |
| # Iterate through unique well names and filter the data | |
| for well_name in df_monthly_24['NPD_WELL_BORE_NAME'].unique(): | |
| well_df = df_monthly_24[df_monthly_24['NPD_WELL_BORE_NAME'] == well_name] | |
| well_dataframes[well_name] = well_df | |
| # Initialize forecast variables | |
| t_forecast_dict = {} | |
| q_forecast_dict = {} | |
| Qp_forecast_dict = {} | |
| # Iterate through unique well names and perform forecasting for each well | |
| for well_name, well_df in well_dataframes.items(): | |
| st.write(f"Forecasting for Well: {well_name}") | |
| # Create a 't' array where t is DATEPRD | |
| t = well_df['DATEPRD'].values | |
| # Create a 'q' array where q is BORE_OIL_VOL | |
| q = well_df['BORE_OIL_VOL'].values | |
| # Subtract one datetime from another for 't' | |
| timedelta_t = [j - i for i, j in zip(t[:-1], t[1:])] | |
| timedelta_t = np.array(timedelta_t) | |
| timedelta_t = timedelta_t / np.timedelta64(1, 'D') # Convert timedelta to days | |
| # Take cumulative sum over timedeltas for 't' | |
| t = np.cumsum(timedelta_t) | |
| t = np.append(0, t) | |
| t = t.astype(float) | |
| # Normalize 't' and 'q' data | |
| t_normalized = t / max(t) | |
| q_normalized = q / max(q) | |
| # Function for exponential decline | |
| def exponential(t, qi, di): | |
| return qi * np.exp(-di * t) | |
| # Fit the exponential decline model to the normalized data | |
| popt, pcov = curve_fit(exponential, t_normalized, q_normalized) | |
| qi, di = popt | |
| # Check if di is <= 0.0, if so, skip this well | |
| if di <= 0.0: | |
| print(f'Skipping well {well_name} due to di <= 0.0') | |
| continue | |
| # De-normalize qi and di | |
| qi = qi * max(q) | |
| di = di / max(t) | |
| # Initialize forecast variables | |
| t_forecast = [] | |
| q_forecast = [] | |
| Qp_forecast = [] | |
| # Initial values | |
| t_current = 0 | |
| q_current = exponential(t_current, qi, di) | |
| # Function to calculate cumulative production | |
| def cumpro(q_forecast, qi, di): | |
| return (qi - q_forecast) / di | |
| Qp_current = cumpro(q_current, qi, di) | |
| # Start forecasting until q_forecast reaches 25 | |
| while q_current >= 25: | |
| t_forecast.append(t_current) | |
| q_forecast.append(q_current) | |
| Qp_forecast.append(Qp_current) | |
| # Increment time step | |
| t_current += 1 | |
| q_current = exponential(t_current, qi, di) | |
| Qp_current = cumpro(q_current, qi, di) | |
| # Convert lists to numpy arrays for convenience | |
| t_forecast = np.array(t_forecast) | |
| q_forecast = np.array(q_forecast) | |
| Qp_forecast = np.array(Qp_forecast) | |
| # Display results in Streamlit | |
| st.write('Final Rate:', np.round(q_forecast[-1], 3), 'BOPD') | |
| st.write('Final Cumulative Production:', np.round(Qp_forecast[-1], 2), 'BBL OIL') | |
| # Plot the results using Matplotlib and display them in Streamlit | |
| plt.figure(figsize=(15, 5)) | |
| plt.subplot(1, 2, 1) | |
| plt.plot(t, q, '.', color='red', label='Production Data') | |
| plt.plot(t_forecast, q_forecast, label='Forecast') | |
| plt.title('Oil Production Rate Result of DCA', size=13, pad=15) | |
| plt.xlabel('Days') | |
| plt.ylabel('Rate (BBL OIL/d)') | |
| plt.xlim(left=0) | |
| plt.ylim(bottom=0) | |
| plt.legend() | |
| plt.subplot(1, 2, 2) | |
| plt.plot(t_forecast, Qp_forecast) | |
| plt.title('OIL Cumulative Production Result of DCA', size=13, pad=15) | |
| plt.xlabel('Days') | |
| plt.ylabel('Production (BBL OIL)') | |
| plt.xlim(left=0) | |
| plt.ylim(bottom=0) | |
| # Display the Matplotlib figure in Streamlit | |
| st.pyplot() | |