diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..e513b55 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,14 @@ +image: python:3.9 + +pages: + stage: deploy + script: + - python setup.py install + - pip install -U sphinx + - pip install -U sphinx-rtd-theme + - sphinx-build -b html ./docs public + artifacts: + paths: + - public + only: + - master diff --git a/docs/_static/0/basecase/Visualize_and_Export.html b/docs/_static/0/basecase/Visualize_and_Export.html index 160e6fe..428a7a7 100644 --- a/docs/_static/0/basecase/Visualize_and_Export.html +++ b/docs/_static/0/basecase/Visualize_and_Export.html @@ -15030,7 +15030,8 @@

Playing with data fr
In [27]:
-
df[['distance']].iplot()
+
fig_dist = px.line(df, y="distance", title="distance")
+fig_dist.show()
 
diff --git a/docs/requirements.readthedocs.txt b/docs/requirements.readthedocs.txt index 6e7022a..b4663ec 100644 --- a/docs/requirements.readthedocs.txt +++ b/docs/requirements.readthedocs.txt @@ -1,6 +1,5 @@ appdirs plotly -cufflinks zenodo-get pyyaml pandas diff --git a/emobpy/availability.py b/emobpy/availability.py index c401303..879d864 100644 --- a/emobpy/availability.py +++ b/emobpy/availability.py @@ -49,6 +49,49 @@ logger = get_logger(__name__) +@jit(nopython=True) +def _charging_cap_numba(state_is_driving, consumption, charging_cap, t, battery_capacity): + """ + Berechnet die angepasste charging_cap-Spalte (0 wo keine Lademöglichkeit). + state_is_driving[i] == 1 bedeutet state == 'driving'. + """ + n = consumption.shape[0] + out_cap = np.empty_like(charging_cap) + for i in range(n): + out_cap[i] = charging_cap[i] + flag = False + cumcons = 0.0 + cumchrg = 0.0 + for i in range(n): + if flag: + if state_is_driving[i]: + if cumcons != 0 and cumchrg == 0: + cumcons += consumption[i] + if cumcons < battery_capacity * 0.50: + out_cap[i] = 0.0 + cumchrg = 0.0 + else: + cumchrg += charging_cap[i] * t + cumcons = 0.0 + else: + cumchrg += charging_cap[i] * t + if cumchrg > battery_capacity * 0.5: + cumchrg = 0.0 + cumcons = 0.001 + else: + flag = False + elif state_is_driving[i]: + flag = True + cumcons = consumption[i] + if cumcons < battery_capacity * 0.65: + out_cap[i] = 0.0 + cumchrg = 0.0 + else: + cumchrg = charging_cap[i] * t + cumcons = 0.0 + return out_cap + + ################################################################ # These functions are for grid availability profile creation ### ################################################################ @@ -439,20 +482,19 @@ def _fill_rows(self): self.dt = pd.DataFrame(columns=self.db.columns) self.dt.loc[:, "hh"] = np.arange(0, self.hours, self.t) - # Start New version, which works for 1s-based profiles: - temp_timeseries = [round(num*3600) for num in self.dt["hh"]] - temp_db = [round(num*3600) for num in self.db["hr"]] - temp_intersection_list = list(set(temp_timeseries).intersection(temp_db)) - - self.idx = [] - for i in temp_intersection_list: - self.idx.append(temp_timeseries.index(i)) - self.idx = np.sort(self.idx).tolist() - # End new version + # Vektorisiert (wie in mobility._fill_rows): Index-Suche mit NumPy + temp_ts = np.round(self.dt["hh"].values * 3600).astype(np.int64) + temp_db = np.round(self.db["hr"].values * 3600).astype(np.int64) + order = np.argsort(temp_ts) + sorted_ts = temp_ts[order] + pos = np.searchsorted(sorted_ts, temp_db) + idx = order[pos] + sorted_by_idx = np.argsort(idx) + self.idx = idx[sorted_by_idx].tolist() self.mixed = self.repeats_str + self.repeats_float + self.fixed + self.copied for r in self.mixed: - self.val = self.db[r].values.tolist() + self.val = self.db[r].values[sorted_by_idx] self.dt.loc[self.idx, r] = self.val self.dt.loc[self.totalrows - 1, "state"] = self.db["state"].iloc[-1] self.dt.loc[self.totalrows - 1, "hr"] = self.dt["hh"][self.totalrows - 1] @@ -464,7 +506,7 @@ def _fill_rows(self): for sm in self.same: self.dt.loc[:, sm] = self.db[sm].values.tolist()[0] for cal in self.calc: - self.dt.loc[:, cal] = self.dt["hh"].apply(lambda x: x % 24) + self.dt.loc[:, cal] = self.dt["hh"].values % 24 self.dt.loc[:, "count"] = self.dt.groupby(["hr", "state"])[ "consumption" ].transform("count") @@ -474,40 +516,15 @@ def _fill_rows(self): self.dt.loc[:, "distance"] = ( self.dt.loc[:, "distance"] / self.dt.loc[:, "count"] ) - # convert this section to numba - flag = False - for i, row in self.dt.iterrows(): - if flag: - if row["state"] == "driving": - flag = True - if self.cumcons != 0 and self.cumchrg == 0: - self.cumcons += row["consumption"] - if self.cumcons < self.battery_capacity * 0.50: - self.dt.loc[i, "charging_cap"] = 0 - self.dt.loc[i, "charging_point"] = "none" - self.cumchrg = 0 - else: - self.cumchrg += row["charging_cap"] * self.t - self.cumcons = 0 - else: - self.cumchrg += row["charging_cap"] * self.t - if self.cumchrg > self.battery_capacity * 0.5: - self.cumchrg = 0 - self.cumcons += 0.001 - else: - pass - else: - flag = False - elif row["state"] == "driving": - flag = True - self.cumcons = row["consumption"] - if self.cumcons < self.battery_capacity * 0.65: - self.dt.loc[i, "charging_cap"] = 0 - self.dt.loc[i, "charging_point"] = "none" - self.cumchrg = 0 - else: - self.cumchrg = row["charging_cap"] * self.t - self.cumcons = 0 + state_is_driving = (self.dt["state"] == "driving").values.astype(np.float64) + consumption_arr = self.dt["consumption"].values.astype(np.float64) + charging_cap_arr = self.dt["charging_cap"].values.astype(np.float64) + new_cap = _charging_cap_numba( + state_is_driving, consumption_arr, charging_cap_arr, + self.t, self.battery_capacity, + ) + self.dt.loc[:, "charging_cap"] = new_cap + self.dt.loc[self.dt["charging_cap"] == 0, "charging_point"] = "none" def run(self): """ diff --git a/emobpy/charging.py b/emobpy/charging.py index ab76471..e8887b2 100644 --- a/emobpy/charging.py +++ b/emobpy/charging.py @@ -138,11 +138,13 @@ def run(self): self._clean() return None self.numpy_array3 = self.profile[['state']].values.T - self.arraystringstate = self.numpy_array3[0] + self.arraystringstate = self.numpy_array3[0].astype(str) self.arraycodestate = np.array([self.states.index(s) for s in self.arraystringstate]) self.numpy_array2 = self.profile[['consumption', 'charging_cap']].values.T + self.arrayconsumption = self.numpy_array2[0].astype(np.float64) + self.arraychargingcap = self.numpy_array2[1].astype(np.float64) self.results = self._immediate(self.pointcode, self.charging_eff, self.battery_capacity, self.soc_init, - self.arraycodestate, *self.numpy_array2, self.t) + self.arraycodestate, self.arrayconsumption, self.arraychargingcap, self.t) self.profile.loc[:, 'actual_soc'] = self.results[0] self.profile.loc[:, 'charge_battery'] = self.results[1] self.profile.loc[:, 'charge_grid'] = self.results[2] @@ -157,7 +159,7 @@ def run(self): self._clean() return None self.numpy_array3 = self.profile[['state', 'consumption', 'charging_cap']].values.T - self.arraystringstate = self.numpy_array3[0] + self.arraystringstate = self.numpy_array3[0].astype(str) self.arraycodestate = np.array([self.states.index(s) for s in self.arraystringstate]) self.arrayconsumption = self.numpy_array3[1].astype(np.float64) self.arraychargingcap = self.numpy_array3[2].astype(np.float64) @@ -173,7 +175,7 @@ def run(self): self.point = self.op_list[5] self.numpy_array4 = self.profile[['state', 'consumption', 'charging_cap', 'hh']].values.T - self.arraystringstate = self.numpy_array4[0] + self.arraystringstate = self.numpy_array4[0].astype(str) self.arraycodestate = np.array([self.states.index(s) for s in self.arraystringstate]) try: self.drivingcode = self.states.index('driving') @@ -595,4 +597,4 @@ def save_profile(self, folder, description=' '): display_all() except: pass - return None + return None \ No newline at end of file diff --git a/emobpy/consumption.py b/emobpy/consumption.py index 1aaf38a..2de2273 100644 --- a/emobpy/consumption.py +++ b/emobpy/consumption.py @@ -76,7 +76,7 @@ p_generatorin, p_motorin, p_generatorout, - qhvac + qhvac_numba, ) from .tools import (Unit, check_for_new_function_name, _add_column_datetime, consumption_progress_bar, wget_progress_bar, display_all) from .init import copy_to_user_data_dir @@ -396,8 +396,7 @@ def search_by_parameter(self, parameter='power', first_x=10, brand_filter=[], mo print_dict = json.loads(json.dumps(self.data)) print_dict.pop('fallback_parameters') - df = pd.DataFrame(columns=['brand', 'model', 'year', 'value', 'unit']) - + rows = [] for brand_name, brand_values in self.data.items(): if brand_name == 'fallback_parameters': continue @@ -411,9 +410,16 @@ def search_by_parameter(self, parameter='power', first_x=10, brand_filter=[], mo continue for para_name, para_value in year_values.items(): if para_name == parameter: - df = df.append( - {'brand': brand_name, 'model': model_name, 'year': year_name, 'value': para_value["value"], 'unit': para_value['unit']}, - ignore_index=True) + rows.append( + { + "brand": brand_name, + "model": model_name, + "year": year_name, + "value": para_value["value"], + "unit": para_value["unit"], + } + ) + df = pd.DataFrame(rows, columns=["brand", "model", "year", "value", "unit"]) logger.info(f'Parameter: {parameter}') data = df.sort_values(by='value', ascending=False).reset_index(drop=True) logger.info(data.head(first_x)) @@ -880,7 +886,9 @@ def __init__(self): self.index_speed = None user_dir = USER_PATH or DEFAULT_DATA_DIR self.datafile = os.path.join(user_dir, DC_FILE) - # self.load_data() + # Cache (index, scale, slide, mean_speed_m_s) -> (speed_array, acc_array) für gleiche Trips + self._cycle_cache = {} + self._cycle_cache_max_size = 500 def __getattr__(self, item): check_for_new_function_name(item) @@ -1091,32 +1099,37 @@ def driving_cycle(self, trip, model, full_driving_cycle=False): trip.time["value"] = np.ceil(Unit(trip._duration["value"], trip._duration["unit"]).convert_to("s").val) trip.time["unit"] = "s" - scale = (trip.time["value"] - // Unit(self.data[trip.index]["time"]["value"], self.data[trip.index]["time"]["unit"]).convert_to("s").val - ) - slide = ( - trip.time["value"] - % Unit(self.data[trip.index]["time"]["value"], self.data[trip.index]["time"]["unit"]).convert_to("s").val - ) - normalized = self.data[trip.index]["normalized"]["value"] - normalized_array = np.array(list(normalized) * int(scale) + list(normalized)[0: int(slide)]) - speed_array = ( - normalized_array - * Unit(trip._mean_speed["value"], trip._mean_speed["unit"]).convert_to("m/s").val - ) - i = 0 - for last_secs in range(-20, 0): - i += 1 - calc = ( - speed_array[last_secs - 1] - speed_array[last_secs - 1] * (i / 100) * 2 - ) - speed_array[last_secs] = max(0, calc) + cycle_time_s = Unit(self.data[trip.index]["time"]["value"], self.data[trip.index]["time"]["unit"]).convert_to("s").val + scale = int(trip.time["value"] // cycle_time_s) + slide = int(trip.time["value"] % cycle_time_s) + mean_speed_m_s = Unit(trip._mean_speed["value"], trip._mean_speed["unit"]).convert_to("m/s").val + + cache_key = (trip.index, scale, slide, round(mean_speed_m_s, 6)) + if cache_key in self._cycle_cache: + speed_array, acc_array = self._cycle_cache[cache_key] + trip.speed["value"] = speed_array.copy() + trip.acceleration["value"] = acc_array.copy() + else: + normalized = self.data[trip.index]["normalized"]["value"] + normalized_array = np.array(list(normalized) * scale + list(normalized)[0: slide]) + speed_array = normalized_array * mean_speed_m_s + i = 0 + for last_secs in range(-20, 0): + i += 1 + calc = ( + speed_array[last_secs - 1] - speed_array[last_secs - 1] * (i / 100) * 2 + ) + speed_array[last_secs] = max(0, calc) + + acc_array = acceleration_array(speed_array) + if len(self._cycle_cache) < self._cycle_cache_max_size: + self._cycle_cache[cache_key] = (speed_array.copy(), acc_array.copy()) + + trip.speed["value"] = speed_array + trip.acceleration["value"] = acc_array - trip.speed["value"] = speed_array trip.speed["unit"] = "m/s" - trip.acceleration["value"] = acceleration_array(speed_array) trip.acceleration["unit"] = "m/s**2" - trip.driving_cycle_name = self.data[trip.index]["name"] @@ -1561,7 +1574,6 @@ def run( self.profile.loc[:, "road_type"] = road_type wt = Weather() - D = wt.humidair_density temp_arr = wt.temp(weather_country, weather_year) pres_arr = wt.pressure(weather_country, weather_year) dp_arr = wt.dewpoint(weather_country, weather_year) @@ -1575,337 +1587,354 @@ def run( self.Trips = Trips() dc = DrivingCycle() dc.load_data() - total = len(self.profile[self.profile["state"] == "driving"]) - current = 1 - - for i, row in self.profile.iterrows(): - if row["state"] == "driving": - consumption_progress_bar(current, total) - current += 1 - trip = Trip(self.Trips) - trip.driving_cycle_type = driving_cycle_type - trip.add_distance_duration( - distance={"value": row["distance"], "unit": "km"}, - duration={"value": row["trip_duration"], "unit": "min"}, - ) - dc.driving_cycle(trip, self.vehicle, full_driving_cycle=False) - v = trip.speed["value"] # m/s - acc = trip.acceleration["value"] # m/s2 - targ_temp, cop, ret = self._cop_and_target_temp(row["temp_degC"]) - frontal_area = self.vehicle.parameters["front_area"] - P_max = ( - self.vehicle.parameters["power"] * 1000 - ) # kW to W - f_d = self.vehicle.parameters["drag_coeff"] - f_r = rolling_resistance_coeff( - method="M1", - temp=row["temp_degC"], - v=v * 3.6, - road_type=row["road_type"], - ) - # f_r = rolling_resistance_coeff(method='M2', v=v*3.6, tire_type=0, road_type=4) - m_i = self.vehicle.parameters["inertial_mass"] - m_c = self.vehicle.parameters["curb_weight"] - m_v = vehicle_mass(m_c, passenger_mass * passenger_nr) - P_rol = prollingresistance(f_r, m_v, GRAVITY, v) - P_air = pairdrag( - row["air_density_kg/m3"], frontal_area, f_d, v, row["wind_m/s"] - ) # last arg is wind speed - P_g = p_gravity( - m_v, GRAVITY, v, row["slope_rad"] - ) # last arg is road slope - P_ine = pinertia(m_i, m_v, acc, v) - P_wheel = p_wheel(P_rol, P_air, P_g, P_ine) - P_m_o = p_motorout(P_wheel, self.transmission_eff) - n_rb = EFFICIENCYregenerative_braking(acc) - P_gen_in = p_generatorin(P_wheel, self.transmission_eff, n_rb) - Load_p_m = P_m_o / P_max - Load_p_g = P_gen_in / P_max - n_mot = self.η.get_efficiency(Load_p_m, 1) - n_gen = self.η.get_efficiency(Load_p_g, -1) - P_m_in = p_motorin(P_m_o, n_mot) - P_g_out = p_generatorout(P_gen_in, n_gen) - P_aux = np.array([self.auxiliary_power] * len(v)) - Q_hvac, Tcabin = qhvac( - D, - row["temp_degC"], - targ_temp, - self.cabin_volume, - air_flow, - heat_insulation.zone_layers_, - heat_insulation.zone_surface_, - heat_insulation.layer_conductivity_, - heat_insulation.layer_thickness_, - v, - Q_sensible=passenger_sensible_heat, - persons=passenger_nr, - air_cabin_heat_transfer_coef=air_cabin_heat_transfer_coef, - ) - P_hvac = np.abs(Q_hvac[:, 0]) / cop - P_gen_bat_charg = P_g_out * self.battery_charge_eff * -1 - P_bat = (P_m_in + P_aux + P_hvac) / self.battery_discharge_eff - # section to calculate consumption - P_all = P_m_in + P_aux + P_hvac + P_g_out - P_all_negative = P_all.copy() - P_all_negative[P_all_negative > 0.0] = 0.0 - P_all_positive = P_all.copy() - P_all_positive[P_all_positive < 0.0] = 0.0 - P_bat_chg = P_all_negative * self.battery_charge_eff - P_bat_dischg = P_all_positive / self.battery_discharge_eff - P_bat_actual = np.add(P_bat_dischg, P_bat_chg) # W - consumption = P_bat_actual.sum() / 1000 / 3600 # kWh - rate = consumption / v.sum() * 100000 # kWh/100 km - - # Add variables to trip object: International units (power in W) - trip.results["targ_temp"] = targ_temp - trip.results["cop"] = cop - trip.results["ret"] = ret - trip.results["frontal_area"] = frontal_area - trip.results["P_max"] = P_max - trip.results["Drag_coeff"] = f_d - trip.results["roll_res_coeff"] = f_r - trip.results["m_i"] = m_i - trip.results["m_c"] = m_c - trip.results["m_v"] = m_v - trip.results["P_rol"] = P_rol - trip.results["P_air"] = P_air - trip.results["P_g"] = P_g - trip.results["P_ine"] = P_ine - trip.results["P_wheel"] = P_wheel - trip.results["P_gen_in"] = P_gen_in - trip.results["Load_p_m"] = Load_p_m - trip.results["Load_p_g"] = Load_p_g - trip.results["n_mot"] = n_mot - trip.results["n_gen"] = n_gen - trip.results["P_m_in"] = P_m_in - trip.results["P_g_out"] = P_g_out - trip.results["P_aux"] = P_aux - trip.results["Q_hvac"] = Q_hvac - trip.results["Tcabin"] = Tcabin - trip.results["Tout"] = row["temp_degC"] - trip.results["P_hvac"] = P_hvac - - trip.results["P_gen_bat_charg"] = P_gen_bat_charg - trip.results["P_bat"] = P_bat # only all positive loads - trip.results[ - "P_bat_actual" - ] = P_bat_actual # positive load after generation subtraction and negative load (generation) after - # positive loads subtraction - - # Variable for the balance - - P_wheel_pos = P_wheel[P_wheel > 0].sum() # Ws - P_wheel_neg = P_wheel[P_wheel < 0].sum() * -1 # Ws - P_m_o_t = P_m_o.sum() # Ws - P_gen_in_t = P_gen_in.sum() * -1 # Ws - P_m_in_t = P_m_in.sum() # Ws - P_g_out_t = P_g_out.sum() * -1 # Ws - P_aux_t = P_aux.sum() # Ws - P_hvac_t = P_hvac.sum() # Ws - heat_source = np.abs(Q_hvac[:, 0]).sum() - P_hvac_t # Ws - P_gen_bat_charg_t = P_gen_bat_charg.sum() # Ws - P_gen_bat_dischg_t = ( - P_gen_bat_charg_t * self.battery_discharge_eff - ) # Ws - P_bat_t = P_bat.sum() # Ws - - trip.consumption[ - "value" - ] = consumption # the only option this value be to small or negative is the ev goes downhill most of - # the trip - trip.consumption["unit"] = "kWh" - trip.rate["value"] = rate - trip.rate["unit"] = "kWh/100 km" - - loss_gen = P_gen_in_t - P_g_out_t - loss_trans_m = P_m_o_t - P_wheel_pos - loss_trans_g = P_wheel_neg - P_gen_in_t - loss_motor = P_m_in_t - P_m_o_t - loss_gen_bat_charg = P_gen_bat_charg_t * (1 - self.battery_charge_eff) - loss_gen_bat_dischg = P_gen_bat_charg_t * ( - 1 - self.battery_discharge_eff - ) - loss_bat = P_bat_t * (1 - self.battery_discharge_eff) - - if ret == 1: - cooling = 0 - heating = P_hvac_t + heat_source - elif ret == -1: - cooling = P_hvac_t + heat_source - heating = 0 - elif ret == 0: - cooling = 0 - heating = 0 - - # data for sankey diagram - j = np.zeros((v.shape[0], 7)) - j[:, 0] = P_rol - j[:, 1] = P_air - j[:, 2] = P_g - j[:, 3] = P_ine - j[:, 4] = np.sum(j[:, 0:4], axis=1) - j[:, 5] = j[:, 4] - j[np.where(j[:, 5] > 0.0), 5] = 0 - j[:, 6] = j[:, 4] - j[np.where(j[:, 6] < 0.0), 6] = 0 - - ig = np.zeros((v.shape[0], 4)) - ig[np.where(j[:, 5] < 0.0), 0:4] = j[np.where(j[:, 5] < 0.0), 0:4] - ig[np.where(ig[:, 0] > 0.0), 0] = 0 - ig[np.where(ig[:, 1] > 0.0), 1] = 0 - ig[np.where(ig[:, 2] > 0.0), 2] = 0 - ig[np.where(ig[:, 3] > 0.0), 3] = 0 - xg = np.true_divide( - ig, - ig.sum(axis=1, keepdims=True), - out=np.zeros_like(ig), - where=ig.sum(axis=1, keepdims=True) != 0, - ) - yg = (xg.T * j[:, 5]).T * -1 - zg = yg.sum(axis=0) - - ip = np.zeros((v.shape[0], 4)) - ip[np.where(j[:, 6] > 0.0), 0:4] = j[np.where(j[:, 6] > 0.0), 0:4] - ip[np.where(ip[:, 0] < 0.0), 0] = 0 - ip[np.where(ip[:, 1] < 0.0), 1] = 0 - ip[np.where(ip[:, 2] < 0.0), 2] = 0 - ip[np.where(ip[:, 3] < 0.0), 3] = 0 - xp = np.true_divide( - ip, - ip.sum(axis=1, keepdims=True), - out=np.zeros_like(ip), - where=ip.sum(axis=1, keepdims=True) != 0, - ) - yp = (xp.T * j[:, 6]).T - zp = yp.sum(axis=0) - gra_neg = zg[2] - acc_neg = zg[3] - - rol_pos = zp[0] - air_pos = zp[1] - gra_pos = zp[2] - acc_pos = zp[3] - - self.profile.loc[i, "consumption kWh/100 km"] = rate - self.profile.loc[i, "consumption kWh"] = consumption - self.profile.loc[i, "battery discharge kWh"] = P_bat_t / 3600 / 1000 - self.profile.loc[i, "regeneration kWh"] = ( - P_gen_bat_dischg_t / 3600 / 1000 - ) - self.profile.loc[i, "auxiliary kWh"] = P_aux_t / 3600 / 1000 - self.profile.loc[i, "hvac kWh"] = P_hvac_t / 3600 / 1000 - self.profile.loc[i, "motor in kWh"] = P_m_in_t / 3600 / 1000 - self.profile.loc[i, "transmission in kWh"] = P_m_o_t / 3600 / 1000 - self.profile.loc[i, "wheel kWh"] = P_wheel_pos / 3600 / 1000 - self.profile.loc[i, "rolling res kWh"] = rol_pos / 3600 / 1000 - self.profile.loc[i, "air res kWh"] = air_pos / 3600 / 1000 - self.profile.loc[i, "gravity kWh"] = gra_pos / 3600 / 1000 - self.profile.loc[i, "acceleration kWh"] = acc_pos / 3600 / 1000 - self.profile.loc[i, "trip code"] = trip.code - - stv = [ - ["Heat source", "HVAC", heat_source / 3600 / 1000], - ["Potential energy", "Gravity force", gra_neg / 3600 / 1000], - [ - "Battery", - "Discharge", - (P_bat_t - P_gen_bat_charg_t) / 3600 / 1000, - ], - [ - "Discharge", - "Losses", - (loss_bat + loss_gen_bat_dischg) / 3600 / 1000, - ], - ["Discharge", "HVAC", P_hvac_t / 3600 / 1000], - ["Discharge", "Auxiliary", P_aux_t / 3600 / 1000], - ["Discharge", "Motor", P_m_in_t / 3600 / 1000], - [ - "reg_braking", - "Discharge", - P_gen_bat_dischg_t / 3600 / 1000, - ], - [ - "reg_braking", - "Losses", - loss_gen_bat_charg / 3600 / 1000, - ], - ["HVAC", "Cooling", cooling / 3600 / 1000], - ["HVAC", "Heating", heating / 3600 / 1000], - ["Motor", "Transmission of traction", P_m_o_t / 3600 / 1000], - ["Motor", "Losses", loss_motor / 3600 / 1000], - ["Transmission of traction", "Wheel", P_wheel_pos / 3600 / 1000], - ["Transmission of traction", "Losses", loss_trans_m / 3600 / 1000], - ["Wheel", "Rolling resistance", rol_pos / 3600 / 1000], - ["Wheel", "Air resistance", air_pos / 3600 / 1000], - ["Wheel", "Gravity force", gra_pos / 3600 / 1000], - ["Wheel", "Acceleration force", acc_pos / 3600 / 1000], - ["Rolling resistance", "Losses", rol_pos / 3600 / 1000], - ["Air resistance", "Losses", air_pos / 3600 / 1000], - ["Gravity force", "Kinetic energy", gra_neg / 3600 / 1000], - ["Gravity force", "Losses", (gra_pos - gra_neg) / 3600 / 1000], - ["Acceleration force", "Kinetic energy", acc_neg / 3600 / 1000], - ["Acceleration force", "Losses", (acc_pos - acc_neg) / 3600 / 1000], - [ - "Kinetic energy", - "Transmission of regenerative", - (acc_neg + gra_neg) / 3600 / 1000, - ], - [ - "Transmission of regenerative", - "Generator", - P_gen_in_t / 3600 / 1000, - ], - [ - "Transmission of regenerative", - "Losses", - loss_trans_g / 3600 / 1000, - ], - ["Generator", "reg_braking", P_g_out_t / 3600 / 1000], - ["Generator", "Losses", loss_gen / 3600 / 1000], - ["Cooling", "Losses", cooling / 3600 / 1000], - ["Heating", "Losses", heating / 3600 / 1000], - ["Auxiliary", "Losses", P_aux_t / 3600 / 1000], - ] - - link_label = [] - for lk in stv: - llk = [lk[0], lk[1], str(round(lk[2], 1))] - link_label.append("->".join(llk)) - - sort = np.array(stv, dtype=object) - s = sort.T[0].tolist() - t = sort.T[1].tolist() - v = sort.T[2] - - balance = {} - balance["label"] = [ - "Heat source", - "Potential energy", + driving_indices = self.profile.index[self.profile["state"] == "driving"].tolist() + total = len(driving_indices) + # Listen für Bulk-Zuweisung am Ende (weniger .loc-Overhead) + rate_list = [] + consumption_list = [] + P_bat_t_list = [] + P_gen_bat_dischg_t_list = [] + P_aux_t_list = [] + P_hvac_t_list = [] + P_m_in_t_list = [] + P_m_o_t_list = [] + P_wheel_pos_list = [] + rol_pos_list = [] + air_pos_list = [] + gra_pos_list = [] + acc_pos_list = [] + trip_codes_list = [] + + for current, i in enumerate(driving_indices, 1): + consumption_progress_bar(current, total) + row = self.profile.loc[i] + trip = Trip(self.Trips) + trip.driving_cycle_type = driving_cycle_type + trip.add_distance_duration( + distance={"value": row["distance"], "unit": "km"}, + duration={"value": row["trip_duration"], "unit": "min"}, + ) + dc.driving_cycle(trip, self.vehicle, full_driving_cycle=False) + v = trip.speed["value"] # m/s + acc = trip.acceleration["value"] # m/s2 + targ_temp, cop, ret = self._cop_and_target_temp(row["temp_degC"]) + frontal_area = self.vehicle.parameters["front_area"] + P_max = ( + self.vehicle.parameters["power"] * 1000 + ) # kW to W + f_d = self.vehicle.parameters["drag_coeff"] + f_r = rolling_resistance_coeff( + method="M1", + temp=row["temp_degC"], + v=v * 3.6, + road_type=row["road_type"], + ) + m_i = self.vehicle.parameters["inertial_mass"] + m_c = self.vehicle.parameters["curb_weight"] + m_v = vehicle_mass(m_c, passenger_mass * passenger_nr) + P_rol = prollingresistance(f_r, m_v, GRAVITY, v) + P_air = pairdrag( + row["air_density_kg/m3"], frontal_area, f_d, v, row["wind_m/s"] + ) + P_g = p_gravity( + m_v, GRAVITY, v, row["slope_rad"] + ) + P_ine = pinertia(m_i, m_v, acc, v) + P_wheel = p_wheel(P_rol, P_air, P_g, P_ine) + P_m_o = p_motorout(P_wheel, self.transmission_eff) + n_rb = EFFICIENCYregenerative_braking(acc) + P_gen_in = p_generatorin(P_wheel, self.transmission_eff, n_rb) + Load_p_m = P_m_o / P_max + Load_p_g = P_gen_in / P_max + n_mot = self.η.get_efficiency(Load_p_m, 1) + n_gen = self.η.get_efficiency(Load_p_g, -1) + P_m_in = p_motorin(P_m_o, n_mot) + P_g_out = p_generatorout(P_gen_in, n_gen) + P_aux = np.array([self.auxiliary_power] * len(v)) + Q_hvac, Tcabin = qhvac_numba( + row["temp_degC"], + targ_temp, + self.cabin_volume, + air_flow, + heat_insulation.zone_layers_, + heat_insulation.zone_surface_, + heat_insulation.layer_conductivity_, + heat_insulation.layer_thickness_, + v, + Q_sensible=passenger_sensible_heat, + persons=passenger_nr, + air_cabin_heat_transfer_coef=air_cabin_heat_transfer_coef, + ) + P_hvac = np.abs(Q_hvac[:, 0]) / cop + P_gen_bat_charg = P_g_out * self.battery_charge_eff * -1 + P_bat = (P_m_in + P_aux + P_hvac) / self.battery_discharge_eff + P_all = P_m_in + P_aux + P_hvac + P_g_out + P_all_negative = P_all.copy() + P_all_negative[P_all_negative > 0.0] = 0.0 + P_all_positive = P_all.copy() + P_all_positive[P_all_positive < 0.0] = 0.0 + P_bat_chg = P_all_negative * self.battery_charge_eff + P_bat_dischg = P_all_positive / self.battery_discharge_eff + P_bat_actual = np.add(P_bat_dischg, P_bat_chg) # W + consumption = P_bat_actual.sum() / 1000 / 3600 # kWh + rate = consumption / v.sum() * 100000 # kWh/100 km + + trip.results["targ_temp"] = targ_temp + trip.results["cop"] = cop + trip.results["ret"] = ret + trip.results["frontal_area"] = frontal_area + trip.results["P_max"] = P_max + trip.results["Drag_coeff"] = f_d + trip.results["roll_res_coeff"] = f_r + trip.results["m_i"] = m_i + trip.results["m_c"] = m_c + trip.results["m_v"] = m_v + trip.results["P_rol"] = P_rol + trip.results["P_air"] = P_air + trip.results["P_g"] = P_g + trip.results["P_ine"] = P_ine + trip.results["P_wheel"] = P_wheel + trip.results["P_gen_in"] = P_gen_in + trip.results["Load_p_m"] = Load_p_m + trip.results["Load_p_g"] = Load_p_g + trip.results["n_mot"] = n_mot + trip.results["n_gen"] = n_gen + trip.results["P_m_in"] = P_m_in + trip.results["P_g_out"] = P_g_out + trip.results["P_aux"] = P_aux + trip.results["Q_hvac"] = Q_hvac + trip.results["Tcabin"] = Tcabin + trip.results["Tout"] = row["temp_degC"] + trip.results["P_hvac"] = P_hvac + + trip.results["P_gen_bat_charg"] = P_gen_bat_charg + trip.results["P_bat"] = P_bat + trip.results["P_bat_actual"] = P_bat_actual + + P_wheel_pos = P_wheel[P_wheel > 0].sum() # Ws + P_wheel_neg = P_wheel[P_wheel < 0].sum() * -1 # Ws + P_m_o_t = P_m_o.sum() # Ws + P_gen_in_t = P_gen_in.sum() * -1 # Ws + P_m_in_t = P_m_in.sum() # Ws + P_g_out_t = P_g_out.sum() * -1 # Ws + P_aux_t = P_aux.sum() # Ws + P_hvac_t = P_hvac.sum() # Ws + heat_source = np.abs(Q_hvac[:, 0]).sum() - P_hvac_t # Ws + P_gen_bat_charg_t = P_gen_bat_charg.sum() # Ws + P_gen_bat_dischg_t = ( + P_gen_bat_charg_t * self.battery_discharge_eff + ) # Ws + P_bat_t = P_bat.sum() # Ws + + trip.consumption["value"] = consumption + trip.consumption["unit"] = "kWh" + trip.rate["value"] = rate + trip.rate["unit"] = "kWh/100 km" + + loss_gen = P_gen_in_t - P_g_out_t + loss_trans_m = P_m_o_t - P_wheel_pos + loss_trans_g = P_wheel_neg - P_gen_in_t + loss_motor = P_m_in_t - P_m_o_t + loss_gen_bat_charg = P_gen_bat_charg_t * (1 - self.battery_charge_eff) + loss_gen_bat_dischg = P_gen_bat_charg_t * ( + 1 - self.battery_discharge_eff + ) + loss_bat = P_bat_t * (1 - self.battery_discharge_eff) + + if ret == 1: + cooling = 0 + heating = P_hvac_t + heat_source + elif ret == -1: + cooling = P_hvac_t + heat_source + heating = 0 + elif ret == 0: + cooling = 0 + heating = 0 + + j = np.zeros((v.shape[0], 7)) + j[:, 0] = P_rol + j[:, 1] = P_air + j[:, 2] = P_g + j[:, 3] = P_ine + j[:, 4] = np.sum(j[:, 0:4], axis=1) + j[:, 5] = j[:, 4] + j[np.where(j[:, 5] > 0.0), 5] = 0 + j[:, 6] = j[:, 4] + j[np.where(j[:, 6] < 0.0), 6] = 0 + + ig = np.zeros((v.shape[0], 4)) + ig[np.where(j[:, 5] < 0.0), 0:4] = j[np.where(j[:, 5] < 0.0), 0:4] + ig[np.where(ig[:, 0] > 0.0), 0] = 0 + ig[np.where(ig[:, 1] > 0.0), 1] = 0 + ig[np.where(ig[:, 2] > 0.0), 2] = 0 + ig[np.where(ig[:, 3] > 0.0), 3] = 0 + xg = np.true_divide( + ig, + ig.sum(axis=1, keepdims=True), + out=np.zeros_like(ig), + where=ig.sum(axis=1, keepdims=True) != 0, + ) + yg = (xg.T * j[:, 5]).T * -1 + zg = yg.sum(axis=0) + + ip = np.zeros((v.shape[0], 4)) + ip[np.where(j[:, 6] > 0.0), 0:4] = j[np.where(j[:, 6] > 0.0), 0:4] + ip[np.where(ip[:, 0] < 0.0), 0] = 0 + ip[np.where(ip[:, 1] < 0.0), 1] = 0 + ip[np.where(ip[:, 2] < 0.0), 2] = 0 + ip[np.where(ip[:, 3] < 0.0), 3] = 0 + xp = np.true_divide( + ip, + ip.sum(axis=1, keepdims=True), + out=np.zeros_like(ip), + where=ip.sum(axis=1, keepdims=True) != 0, + ) + yp = (xp.T * j[:, 6]).T + zp = yp.sum(axis=0) + gra_neg = zg[2] + acc_neg = zg[3] + + rol_pos = zp[0] + air_pos = zp[1] + gra_pos = zp[2] + acc_pos = zp[3] + + rate_list.append(rate) + consumption_list.append(consumption) + P_bat_t_list.append(P_bat_t / 3600 / 1000) + P_gen_bat_dischg_t_list.append(P_gen_bat_dischg_t / 3600 / 1000) + P_aux_t_list.append(P_aux_t / 3600 / 1000) + P_hvac_t_list.append(P_hvac_t / 3600 / 1000) + P_m_in_t_list.append(P_m_in_t / 3600 / 1000) + P_m_o_t_list.append(P_m_o_t / 3600 / 1000) + P_wheel_pos_list.append(P_wheel_pos / 3600 / 1000) + rol_pos_list.append(rol_pos / 3600 / 1000) + air_pos_list.append(air_pos / 3600 / 1000) + gra_pos_list.append(gra_pos / 3600 / 1000) + acc_pos_list.append(acc_pos / 3600 / 1000) + trip_codes_list.append(trip.code) + + stv = [ + ["Heat source", "HVAC", heat_source / 3600 / 1000], + ["Potential energy", "Gravity force", gra_neg / 3600 / 1000], + [ "Battery", "Discharge", + (P_bat_t - P_gen_bat_charg_t) / 3600 / 1000, + ], + [ + "Discharge", + "Losses", + (loss_bat + loss_gen_bat_dischg) / 3600 / 1000, + ], + ["Discharge", "HVAC", P_hvac_t / 3600 / 1000], + ["Discharge", "Auxiliary", P_aux_t / 3600 / 1000], + ["Discharge", "Motor", P_m_in_t / 3600 / 1000], + [ + "reg_braking", + "Discharge", + P_gen_bat_dischg_t / 3600 / 1000, + ], + [ "reg_braking", - "HVAC", - "Motor", - "Generator", - "Transmission of traction", - "Wheel", - "Kinetic energy", - "Cooling", - "Heating", - "Auxiliary", - "Gravity force", - "Acceleration force", - "Rolling resistance", - "Air resistance", "Losses", + loss_gen_bat_charg / 3600 / 1000, + ], + ["HVAC", "Cooling", cooling / 3600 / 1000], + ["HVAC", "Heating", heating / 3600 / 1000], + ["Motor", "Transmission of traction", P_m_o_t / 3600 / 1000], + ["Motor", "Losses", loss_motor / 3600 / 1000], + ["Transmission of traction", "Wheel", P_wheel_pos / 3600 / 1000], + ["Transmission of traction", "Losses", loss_trans_m / 3600 / 1000], + ["Wheel", "Rolling resistance", rol_pos / 3600 / 1000], + ["Wheel", "Air resistance", air_pos / 3600 / 1000], + ["Wheel", "Gravity force", gra_pos / 3600 / 1000], + ["Wheel", "Acceleration force", acc_pos / 3600 / 1000], + ["Rolling resistance", "Losses", rol_pos / 3600 / 1000], + ["Air resistance", "Losses", air_pos / 3600 / 1000], + ["Gravity force", "Kinetic energy", gra_neg / 3600 / 1000], + ["Gravity force", "Losses", (gra_pos - gra_neg) / 3600 / 1000], + ["Acceleration force", "Kinetic energy", acc_neg / 3600 / 1000], + ["Acceleration force", "Losses", (acc_pos - acc_neg) / 3600 / 1000], + [ + "Kinetic energy", "Transmission of regenerative", - ] - balance["source"] = [balance["label"].index(i) for i in s] - balance["target"] = [balance["label"].index(i) for i in t] - balance["value"] = v - balance["link_label"] = link_label - balance["data"] = stv - trip.balance = balance + (acc_neg + gra_neg) / 3600 / 1000, + ], + [ + "Transmission of regenerative", + "Generator", + P_gen_in_t / 3600 / 1000, + ], + [ + "Transmission of regenerative", + "Losses", + loss_trans_g / 3600 / 1000, + ], + ["Generator", "reg_braking", P_g_out_t / 3600 / 1000], + ["Generator", "Losses", loss_gen / 3600 / 1000], + ["Cooling", "Losses", cooling / 3600 / 1000], + ["Heating", "Losses", heating / 3600 / 1000], + ["Auxiliary", "Losses", P_aux_t / 3600 / 1000], + ] + + link_label = [] + for lk in stv: + llk = [lk[0], lk[1], str(round(lk[2], 1))] + link_label.append("->".join(llk)) + + sort = np.array(stv, dtype=object) + s = sort.T[0].tolist() + t = sort.T[1].tolist() + v = sort.T[2] + + balance = {} + balance["label"] = [ + "Heat source", + "Potential energy", + "Battery", + "Discharge", + "reg_braking", + "HVAC", + "Motor", + "Generator", + "Transmission of traction", + "Wheel", + "Kinetic energy", + "Cooling", + "Heating", + "Auxiliary", + "Gravity force", + "Acceleration force", + "Rolling resistance", + "Air resistance", + "Losses", + "Transmission of regenerative", + ] + balance["source"] = [balance["label"].index(i) for i in s] + balance["target"] = [balance["label"].index(i) for i in t] + balance["value"] = v + balance["link_label"] = link_label + balance["data"] = stv + trip.balance = balance + + # Bulk-Zuweisung (vektorisiert statt vieler .loc pro Trip) + scale = 3600.0 * 1000.0 + self.profile.loc[driving_indices, "consumption kWh/100 km"] = np.array(rate_list) + self.profile.loc[driving_indices, "consumption kWh"] = np.array(consumption_list) + self.profile.loc[driving_indices, "battery discharge kWh"] = np.array(P_bat_t_list) + self.profile.loc[driving_indices, "regeneration kWh"] = np.array(P_gen_bat_dischg_t_list) + self.profile.loc[driving_indices, "auxiliary kWh"] = np.array(P_aux_t_list) + self.profile.loc[driving_indices, "hvac kWh"] = np.array(P_hvac_t_list) + self.profile.loc[driving_indices, "motor in kWh"] = np.array(P_m_in_t_list) + self.profile.loc[driving_indices, "transmission in kWh"] = np.array(P_m_o_t_list) + self.profile.loc[driving_indices, "wheel kWh"] = np.array(P_wheel_pos_list) + self.profile.loc[driving_indices, "rolling res kWh"] = np.array(rol_pos_list) + self.profile.loc[driving_indices, "air res kWh"] = np.array(air_pos_list) + self.profile.loc[driving_indices, "gravity kWh"] = np.array(gra_pos_list) + self.profile.loc[driving_indices, "acceleration kWh"] = np.array(acc_pos_list) + self.profile.loc[driving_indices, "trip code"] = trip_codes_list + print("") self._fill_rows() diff --git a/emobpy/data/base/Visualize_and_Export.ipynb b/emobpy/data/base/Visualize_and_Export.ipynb index 9d60357..d82de82 100644 --- a/emobpy/data/base/Visualize_and_Export.ipynb +++ b/emobpy/data/base/Visualize_and_Export.ipynb @@ -1,417 +1,428 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "moderate-measurement", - "metadata": {}, - "outputs": [], - "source": [ - "from emobpy import DataBase, Export\n", - "from emobpy.plot import NBplot" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "subject-sussex", - "metadata": {}, - "outputs": [], - "source": [ - "DBm = DataBase('db')\n", - "DBm.loadfiles_batch(kind=\"driving\") # load files in parallel that only contains Mobility time-series" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "level-lightning", - "metadata": {}, - "outputs": [], - "source": [ - "mname = list(DBm.db.keys())[0]\n", - "mname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "level-friday", - "metadata": {}, - "outputs": [], - "source": [ - "vizm = NBplot(DBm)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "discrete-tower", - "metadata": {}, - "outputs": [], - "source": [ - "figm = vizm.sgplot_dp(mname)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9163fb06", - "metadata": {}, - "outputs": [], - "source": [ - "figm.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "scientific-liverpool", - "metadata": {}, - "outputs": [], - "source": [ - "DBc = DataBase('db')\n", - "DBc.loadfiles_batch(kind=\"consumption\", add_variables=['Trips'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "empty-elite", - "metadata": {}, - "outputs": [], - "source": [ - "cname = list(DBc.db.keys())[0]\n", - "cname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "sound-office", - "metadata": {}, - "outputs": [], - "source": [ - "vizc = NBplot(DBc)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "neural-haiti", - "metadata": {}, - "outputs": [], - "source": [ - "figc = vizc.sankey(cname, include=None, to_html=False, path='sankey.html')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "beneficial-today", - "metadata": {}, - "outputs": [], - "source": [ - "figc.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "encouraging-literature", - "metadata": {}, - "outputs": [], - "source": [ - "DBa = DataBase('db')\n", - "DBa.loadfiles_batch(kind=\"availability\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "suited-windows", - "metadata": {}, - "outputs": [], - "source": [ - "aname = list(DBa.db.keys())[0]\n", - "aname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "preliminary-consent", - "metadata": {}, - "outputs": [], - "source": [ - "viza = NBplot(DBa)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "spare-syntax", - "metadata": {}, - "outputs": [], - "source": [ - "figg = viza.sgplot_ga(aname, rng=None, to_html=False, path=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f4d4fe33", - "metadata": {}, - "outputs": [], - "source": [ - "figg.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "statistical-newcastle", - "metadata": {}, - "outputs": [], - "source": [ - "DBd = DataBase('db')\n", - "DBd.loadfiles_batch(kind=\"charging\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "representative-current", - "metadata": {}, - "outputs": [], - "source": [ - "dname = list(DBd.db.keys())[0]\n", - "dname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "smoking-lambda", - "metadata": {}, - "outputs": [], - "source": [ - "vizd = NBplot(DBd)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "rapid-advice", - "metadata": {}, - "outputs": [], - "source": [ - "figd = vizd.sgplot_ged(dname, rng=None, to_html=False, path=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a9a4efd0", - "metadata": {}, - "outputs": [], - "source": [ - "figd.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "protecting-reliance", - "metadata": {}, - "outputs": [], - "source": [ - "DB = DataBase('db')\n", - "DB.update()\n", - "Exp = Export()\n", - "Exp.loaddata(DB)\n", - "Exp.to_csv()\n", - "Exp.save_files()\n", - "# See the two CSV files at \"db\" folder" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6b9a54e5", - "metadata": {}, - "outputs": [], - "source": [ - "viz = NBplot(DB)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1e6e606b", - "metadata": {}, - "outputs": [], - "source": [ - "fig = viz.overview(dname)\n", - "fig.show()" - ] - }, - { - "cell_type": "markdown", - "id": "weekly-nelson", - "metadata": {}, - "source": [ - "### Playing with data frames: profiles and time series" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "republican-surveillance", - "metadata": {}, - "outputs": [], - "source": [ - "list(DB.db.keys())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "detected-alabama", - "metadata": {}, - "outputs": [], - "source": [ - "TS_id = list(DB.db.keys())[0] # you can choose any\n", - "TS_id" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "excellent-affect", - "metadata": {}, - "outputs": [], - "source": [ - "df = DB.db[TS_id]['timeseries']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "broke-reconstruction", - "metadata": {}, - "outputs": [], - "source": [ - "df" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "rough-bidder", - "metadata": {}, - "outputs": [], - "source": [ - "df[['distance']].iplot()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "organic-argument", - "metadata": {}, - "outputs": [], - "source": [ - "pf = DB.db[TS_id]['profile']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "polyphonic-parade", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "pf # distance km and duration min" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "juvenile-israeli", - "metadata": {}, - "outputs": [], - "source": [ - "for name in DB.db:\n", - " kind = DB.db[name]['kind']\n", - " if kind != 'driving':\n", - " input_ = DB.db[name]['input'] # upstream profile, e.g. charging <- availability <- consumption <- driving\n", - " print(kind, name, '<-', input_)\n", - " else:\n", - " print(kind, name)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "318c64cd", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS = DB.db[cname]['timeseries']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8ee83d02", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e375f67a", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS[['consumption','instant consumption in W', 'average power in W']].iplot() # Consumption in kWh/timestep -> timestep 15 min in this example\n", - "# Instant consumption only displayed when timestep is 1s." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bc643a8b", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "moderate-measurement", + "metadata": {}, + "outputs": [], + "source": [ + "from emobpy import DataBase, Export\n", + "from emobpy.plot import NBplot\n", + "import plotly.express as px\n", + "import plotly.graph_objects as go" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "subject-sussex", + "metadata": {}, + "outputs": [], + "source": [ + "DBm = DataBase('db')\n", + "DBm.loadfiles_batch(kind=\"driving\") # load files in parallel that only contains Mobility time-series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "level-lightning", + "metadata": {}, + "outputs": [], + "source": [ + "mname = list(DBm.db.keys())[0]\n", + "mname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "level-friday", + "metadata": {}, + "outputs": [], + "source": [ + "vizm = NBplot(DBm)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "discrete-tower", + "metadata": {}, + "outputs": [], + "source": [ + "figm = vizm.sgplot_dp(mname)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9163fb06", + "metadata": {}, + "outputs": [], + "source": [ + "figm.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "scientific-liverpool", + "metadata": {}, + "outputs": [], + "source": [ + "DBc = DataBase('db')\n", + "DBc.loadfiles_batch(kind=\"consumption\", add_variables=['Trips'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "empty-elite", + "metadata": {}, + "outputs": [], + "source": [ + "cname = list(DBc.db.keys())[0]\n", + "cname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "sound-office", + "metadata": {}, + "outputs": [], + "source": [ + "vizc = NBplot(DBc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "neural-haiti", + "metadata": {}, + "outputs": [], + "source": [ + "figc = vizc.sankey(cname, include=None, to_html=False, path='sankey.html')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "beneficial-today", + "metadata": {}, + "outputs": [], + "source": [ + "figc.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "encouraging-literature", + "metadata": {}, + "outputs": [], + "source": [ + "DBa = DataBase('db')\n", + "DBa.loadfiles_batch(kind=\"availability\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "suited-windows", + "metadata": {}, + "outputs": [], + "source": [ + "aname = list(DBa.db.keys())[0]\n", + "aname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "preliminary-consent", + "metadata": {}, + "outputs": [], + "source": [ + "viza = NBplot(DBa)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "spare-syntax", + "metadata": {}, + "outputs": [], + "source": [ + "figg = viza.sgplot_ga(aname, rng=None, to_html=False, path=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4d4fe33", + "metadata": {}, + "outputs": [], + "source": [ + "figg.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "statistical-newcastle", + "metadata": {}, + "outputs": [], + "source": [ + "DBd = DataBase('db')\n", + "DBd.loadfiles_batch(kind=\"charging\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "representative-current", + "metadata": {}, + "outputs": [], + "source": [ + "dname = list(DBd.db.keys())[0]\n", + "dname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "smoking-lambda", + "metadata": {}, + "outputs": [], + "source": [ + "vizd = NBplot(DBd)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "rapid-advice", + "metadata": {}, + "outputs": [], + "source": [ + "figd = vizd.sgplot_ged(dname, rng=None, to_html=False, path=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9a4efd0", + "metadata": {}, + "outputs": [], + "source": [ + "figd.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "protecting-reliance", + "metadata": {}, + "outputs": [], + "source": [ + "DB = DataBase('db')\n", + "DB.update()\n", + "Exp = Export()\n", + "Exp.loaddata(DB)\n", + "Exp.to_csv()\n", + "Exp.save_files()\n", + "# See the two CSV files at \"db\" folder" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b9a54e5", + "metadata": {}, + "outputs": [], + "source": [ + "viz = NBplot(DB)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e6e606b", + "metadata": {}, + "outputs": [], + "source": [ + "fig = viz.overview(dname)\n", + "fig.show()" + ] + }, + { + "cell_type": "markdown", + "id": "weekly-nelson", + "metadata": {}, + "source": [ + "### Playing with data frames: profiles and time series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "republican-surveillance", + "metadata": {}, + "outputs": [], + "source": [ + "list(DB.db.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "detected-alabama", + "metadata": {}, + "outputs": [], + "source": [ + "TS_id = list(DB.db.keys())[0] # you can choose any\n", + "TS_id" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "excellent-affect", + "metadata": {}, + "outputs": [], + "source": [ + "df = DB.db[TS_id]['timeseries']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "broke-reconstruction", + "metadata": {}, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "rough-bidder", + "metadata": {}, + "outputs": [], + "source": [ + "fig_dist = px.line(df, y=\"distance\", title=\"distance\")\n", + "fig_dist.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "organic-argument", + "metadata": {}, + "outputs": [], + "source": [ + "pf = DB.db[TS_id]['profile']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "polyphonic-parade", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "pf # distance km and duration min" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "juvenile-israeli", + "metadata": {}, + "outputs": [], + "source": [ + "for name in DB.db:\n", + " kind = DB.db[name]['kind']\n", + " if kind != 'driving':\n", + " input_ = DB.db[name]['input'] # upstream profile, e.g. charging <- availability <- consumption <- driving\n", + " print(kind, name, '<-', input_)\n", + " else:\n", + " print(kind, name)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "318c64cd", + "metadata": {}, + "outputs": [], + "source": [ + "Consumption_TS = DB.db[cname]['timeseries']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ee83d02", + "metadata": {}, + "outputs": [], + "source": [ + "Consumption_TS" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e375f67a", + "metadata": {}, + "outputs": [], + "source": [ + "cols = [\"consumption\", \"instant consumption in W\", \"average power in W\"]\n", + "fig_cons = go.Figure()\n", + "for col in cols:\n", + " fig_cons.add_trace(\n", + " go.Scatter(x=Consumption_TS.index, y=Consumption_TS[col], name=col, mode=\"lines\")\n", + " )\n", + "fig_cons.update_layout(title=\"Consumption time series\")\n", + "fig_cons.show()\n", + "# Consumption in kWh/timestep -> timestep 15 min in this example\n", + "# Instant consumption only displayed when timestep is 1s." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc643a8b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/emobpy/data/eg3/Visualize_and_Export.ipynb b/emobpy/data/eg3/Visualize_and_Export.ipynb index 9d60357..d82de82 100644 --- a/emobpy/data/eg3/Visualize_and_Export.ipynb +++ b/emobpy/data/eg3/Visualize_and_Export.ipynb @@ -1,417 +1,428 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "moderate-measurement", - "metadata": {}, - "outputs": [], - "source": [ - "from emobpy import DataBase, Export\n", - "from emobpy.plot import NBplot" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "subject-sussex", - "metadata": {}, - "outputs": [], - "source": [ - "DBm = DataBase('db')\n", - "DBm.loadfiles_batch(kind=\"driving\") # load files in parallel that only contains Mobility time-series" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "level-lightning", - "metadata": {}, - "outputs": [], - "source": [ - "mname = list(DBm.db.keys())[0]\n", - "mname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "level-friday", - "metadata": {}, - "outputs": [], - "source": [ - "vizm = NBplot(DBm)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "discrete-tower", - "metadata": {}, - "outputs": [], - "source": [ - "figm = vizm.sgplot_dp(mname)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9163fb06", - "metadata": {}, - "outputs": [], - "source": [ - "figm.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "scientific-liverpool", - "metadata": {}, - "outputs": [], - "source": [ - "DBc = DataBase('db')\n", - "DBc.loadfiles_batch(kind=\"consumption\", add_variables=['Trips'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "empty-elite", - "metadata": {}, - "outputs": [], - "source": [ - "cname = list(DBc.db.keys())[0]\n", - "cname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "sound-office", - "metadata": {}, - "outputs": [], - "source": [ - "vizc = NBplot(DBc)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "neural-haiti", - "metadata": {}, - "outputs": [], - "source": [ - "figc = vizc.sankey(cname, include=None, to_html=False, path='sankey.html')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "beneficial-today", - "metadata": {}, - "outputs": [], - "source": [ - "figc.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "encouraging-literature", - "metadata": {}, - "outputs": [], - "source": [ - "DBa = DataBase('db')\n", - "DBa.loadfiles_batch(kind=\"availability\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "suited-windows", - "metadata": {}, - "outputs": [], - "source": [ - "aname = list(DBa.db.keys())[0]\n", - "aname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "preliminary-consent", - "metadata": {}, - "outputs": [], - "source": [ - "viza = NBplot(DBa)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "spare-syntax", - "metadata": {}, - "outputs": [], - "source": [ - "figg = viza.sgplot_ga(aname, rng=None, to_html=False, path=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f4d4fe33", - "metadata": {}, - "outputs": [], - "source": [ - "figg.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "statistical-newcastle", - "metadata": {}, - "outputs": [], - "source": [ - "DBd = DataBase('db')\n", - "DBd.loadfiles_batch(kind=\"charging\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "representative-current", - "metadata": {}, - "outputs": [], - "source": [ - "dname = list(DBd.db.keys())[0]\n", - "dname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "smoking-lambda", - "metadata": {}, - "outputs": [], - "source": [ - "vizd = NBplot(DBd)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "rapid-advice", - "metadata": {}, - "outputs": [], - "source": [ - "figd = vizd.sgplot_ged(dname, rng=None, to_html=False, path=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a9a4efd0", - "metadata": {}, - "outputs": [], - "source": [ - "figd.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "protecting-reliance", - "metadata": {}, - "outputs": [], - "source": [ - "DB = DataBase('db')\n", - "DB.update()\n", - "Exp = Export()\n", - "Exp.loaddata(DB)\n", - "Exp.to_csv()\n", - "Exp.save_files()\n", - "# See the two CSV files at \"db\" folder" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6b9a54e5", - "metadata": {}, - "outputs": [], - "source": [ - "viz = NBplot(DB)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1e6e606b", - "metadata": {}, - "outputs": [], - "source": [ - "fig = viz.overview(dname)\n", - "fig.show()" - ] - }, - { - "cell_type": "markdown", - "id": "weekly-nelson", - "metadata": {}, - "source": [ - "### Playing with data frames: profiles and time series" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "republican-surveillance", - "metadata": {}, - "outputs": [], - "source": [ - "list(DB.db.keys())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "detected-alabama", - "metadata": {}, - "outputs": [], - "source": [ - "TS_id = list(DB.db.keys())[0] # you can choose any\n", - "TS_id" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "excellent-affect", - "metadata": {}, - "outputs": [], - "source": [ - "df = DB.db[TS_id]['timeseries']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "broke-reconstruction", - "metadata": {}, - "outputs": [], - "source": [ - "df" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "rough-bidder", - "metadata": {}, - "outputs": [], - "source": [ - "df[['distance']].iplot()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "organic-argument", - "metadata": {}, - "outputs": [], - "source": [ - "pf = DB.db[TS_id]['profile']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "polyphonic-parade", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "pf # distance km and duration min" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "juvenile-israeli", - "metadata": {}, - "outputs": [], - "source": [ - "for name in DB.db:\n", - " kind = DB.db[name]['kind']\n", - " if kind != 'driving':\n", - " input_ = DB.db[name]['input'] # upstream profile, e.g. charging <- availability <- consumption <- driving\n", - " print(kind, name, '<-', input_)\n", - " else:\n", - " print(kind, name)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "318c64cd", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS = DB.db[cname]['timeseries']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8ee83d02", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e375f67a", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS[['consumption','instant consumption in W', 'average power in W']].iplot() # Consumption in kWh/timestep -> timestep 15 min in this example\n", - "# Instant consumption only displayed when timestep is 1s." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bc643a8b", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "moderate-measurement", + "metadata": {}, + "outputs": [], + "source": [ + "from emobpy import DataBase, Export\n", + "from emobpy.plot import NBplot\n", + "import plotly.express as px\n", + "import plotly.graph_objects as go" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "subject-sussex", + "metadata": {}, + "outputs": [], + "source": [ + "DBm = DataBase('db')\n", + "DBm.loadfiles_batch(kind=\"driving\") # load files in parallel that only contains Mobility time-series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "level-lightning", + "metadata": {}, + "outputs": [], + "source": [ + "mname = list(DBm.db.keys())[0]\n", + "mname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "level-friday", + "metadata": {}, + "outputs": [], + "source": [ + "vizm = NBplot(DBm)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "discrete-tower", + "metadata": {}, + "outputs": [], + "source": [ + "figm = vizm.sgplot_dp(mname)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9163fb06", + "metadata": {}, + "outputs": [], + "source": [ + "figm.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "scientific-liverpool", + "metadata": {}, + "outputs": [], + "source": [ + "DBc = DataBase('db')\n", + "DBc.loadfiles_batch(kind=\"consumption\", add_variables=['Trips'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "empty-elite", + "metadata": {}, + "outputs": [], + "source": [ + "cname = list(DBc.db.keys())[0]\n", + "cname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "sound-office", + "metadata": {}, + "outputs": [], + "source": [ + "vizc = NBplot(DBc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "neural-haiti", + "metadata": {}, + "outputs": [], + "source": [ + "figc = vizc.sankey(cname, include=None, to_html=False, path='sankey.html')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "beneficial-today", + "metadata": {}, + "outputs": [], + "source": [ + "figc.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "encouraging-literature", + "metadata": {}, + "outputs": [], + "source": [ + "DBa = DataBase('db')\n", + "DBa.loadfiles_batch(kind=\"availability\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "suited-windows", + "metadata": {}, + "outputs": [], + "source": [ + "aname = list(DBa.db.keys())[0]\n", + "aname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "preliminary-consent", + "metadata": {}, + "outputs": [], + "source": [ + "viza = NBplot(DBa)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "spare-syntax", + "metadata": {}, + "outputs": [], + "source": [ + "figg = viza.sgplot_ga(aname, rng=None, to_html=False, path=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4d4fe33", + "metadata": {}, + "outputs": [], + "source": [ + "figg.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "statistical-newcastle", + "metadata": {}, + "outputs": [], + "source": [ + "DBd = DataBase('db')\n", + "DBd.loadfiles_batch(kind=\"charging\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "representative-current", + "metadata": {}, + "outputs": [], + "source": [ + "dname = list(DBd.db.keys())[0]\n", + "dname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "smoking-lambda", + "metadata": {}, + "outputs": [], + "source": [ + "vizd = NBplot(DBd)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "rapid-advice", + "metadata": {}, + "outputs": [], + "source": [ + "figd = vizd.sgplot_ged(dname, rng=None, to_html=False, path=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9a4efd0", + "metadata": {}, + "outputs": [], + "source": [ + "figd.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "protecting-reliance", + "metadata": {}, + "outputs": [], + "source": [ + "DB = DataBase('db')\n", + "DB.update()\n", + "Exp = Export()\n", + "Exp.loaddata(DB)\n", + "Exp.to_csv()\n", + "Exp.save_files()\n", + "# See the two CSV files at \"db\" folder" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b9a54e5", + "metadata": {}, + "outputs": [], + "source": [ + "viz = NBplot(DB)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e6e606b", + "metadata": {}, + "outputs": [], + "source": [ + "fig = viz.overview(dname)\n", + "fig.show()" + ] + }, + { + "cell_type": "markdown", + "id": "weekly-nelson", + "metadata": {}, + "source": [ + "### Playing with data frames: profiles and time series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "republican-surveillance", + "metadata": {}, + "outputs": [], + "source": [ + "list(DB.db.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "detected-alabama", + "metadata": {}, + "outputs": [], + "source": [ + "TS_id = list(DB.db.keys())[0] # you can choose any\n", + "TS_id" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "excellent-affect", + "metadata": {}, + "outputs": [], + "source": [ + "df = DB.db[TS_id]['timeseries']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "broke-reconstruction", + "metadata": {}, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "rough-bidder", + "metadata": {}, + "outputs": [], + "source": [ + "fig_dist = px.line(df, y=\"distance\", title=\"distance\")\n", + "fig_dist.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "organic-argument", + "metadata": {}, + "outputs": [], + "source": [ + "pf = DB.db[TS_id]['profile']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "polyphonic-parade", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "pf # distance km and duration min" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "juvenile-israeli", + "metadata": {}, + "outputs": [], + "source": [ + "for name in DB.db:\n", + " kind = DB.db[name]['kind']\n", + " if kind != 'driving':\n", + " input_ = DB.db[name]['input'] # upstream profile, e.g. charging <- availability <- consumption <- driving\n", + " print(kind, name, '<-', input_)\n", + " else:\n", + " print(kind, name)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "318c64cd", + "metadata": {}, + "outputs": [], + "source": [ + "Consumption_TS = DB.db[cname]['timeseries']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ee83d02", + "metadata": {}, + "outputs": [], + "source": [ + "Consumption_TS" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e375f67a", + "metadata": {}, + "outputs": [], + "source": [ + "cols = [\"consumption\", \"instant consumption in W\", \"average power in W\"]\n", + "fig_cons = go.Figure()\n", + "for col in cols:\n", + " fig_cons.add_trace(\n", + " go.Scatter(x=Consumption_TS.index, y=Consumption_TS[col], name=col, mode=\"lines\")\n", + " )\n", + "fig_cons.update_layout(title=\"Consumption time series\")\n", + "fig_cons.show()\n", + "# Consumption in kWh/timestep -> timestep 15 min in this example\n", + "# Instant consumption only displayed when timestep is 1s." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc643a8b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/emobpy/data/eg4/Visualize_and_Export.ipynb b/emobpy/data/eg4/Visualize_and_Export.ipynb index 9d60357..d82de82 100644 --- a/emobpy/data/eg4/Visualize_and_Export.ipynb +++ b/emobpy/data/eg4/Visualize_and_Export.ipynb @@ -1,417 +1,428 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "moderate-measurement", - "metadata": {}, - "outputs": [], - "source": [ - "from emobpy import DataBase, Export\n", - "from emobpy.plot import NBplot" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "subject-sussex", - "metadata": {}, - "outputs": [], - "source": [ - "DBm = DataBase('db')\n", - "DBm.loadfiles_batch(kind=\"driving\") # load files in parallel that only contains Mobility time-series" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "level-lightning", - "metadata": {}, - "outputs": [], - "source": [ - "mname = list(DBm.db.keys())[0]\n", - "mname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "level-friday", - "metadata": {}, - "outputs": [], - "source": [ - "vizm = NBplot(DBm)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "discrete-tower", - "metadata": {}, - "outputs": [], - "source": [ - "figm = vizm.sgplot_dp(mname)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9163fb06", - "metadata": {}, - "outputs": [], - "source": [ - "figm.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "scientific-liverpool", - "metadata": {}, - "outputs": [], - "source": [ - "DBc = DataBase('db')\n", - "DBc.loadfiles_batch(kind=\"consumption\", add_variables=['Trips'])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "empty-elite", - "metadata": {}, - "outputs": [], - "source": [ - "cname = list(DBc.db.keys())[0]\n", - "cname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "sound-office", - "metadata": {}, - "outputs": [], - "source": [ - "vizc = NBplot(DBc)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "neural-haiti", - "metadata": {}, - "outputs": [], - "source": [ - "figc = vizc.sankey(cname, include=None, to_html=False, path='sankey.html')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "beneficial-today", - "metadata": {}, - "outputs": [], - "source": [ - "figc.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "encouraging-literature", - "metadata": {}, - "outputs": [], - "source": [ - "DBa = DataBase('db')\n", - "DBa.loadfiles_batch(kind=\"availability\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "suited-windows", - "metadata": {}, - "outputs": [], - "source": [ - "aname = list(DBa.db.keys())[0]\n", - "aname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "preliminary-consent", - "metadata": {}, - "outputs": [], - "source": [ - "viza = NBplot(DBa)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "spare-syntax", - "metadata": {}, - "outputs": [], - "source": [ - "figg = viza.sgplot_ga(aname, rng=None, to_html=False, path=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f4d4fe33", - "metadata": {}, - "outputs": [], - "source": [ - "figg.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "statistical-newcastle", - "metadata": {}, - "outputs": [], - "source": [ - "DBd = DataBase('db')\n", - "DBd.loadfiles_batch(kind=\"charging\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "representative-current", - "metadata": {}, - "outputs": [], - "source": [ - "dname = list(DBd.db.keys())[0]\n", - "dname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "smoking-lambda", - "metadata": {}, - "outputs": [], - "source": [ - "vizd = NBplot(DBd)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "rapid-advice", - "metadata": {}, - "outputs": [], - "source": [ - "figd = vizd.sgplot_ged(dname, rng=None, to_html=False, path=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a9a4efd0", - "metadata": {}, - "outputs": [], - "source": [ - "figd.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "protecting-reliance", - "metadata": {}, - "outputs": [], - "source": [ - "DB = DataBase('db')\n", - "DB.update()\n", - "Exp = Export()\n", - "Exp.loaddata(DB)\n", - "Exp.to_csv()\n", - "Exp.save_files()\n", - "# See the two CSV files at \"db\" folder" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6b9a54e5", - "metadata": {}, - "outputs": [], - "source": [ - "viz = NBplot(DB)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1e6e606b", - "metadata": {}, - "outputs": [], - "source": [ - "fig = viz.overview(dname)\n", - "fig.show()" - ] - }, - { - "cell_type": "markdown", - "id": "weekly-nelson", - "metadata": {}, - "source": [ - "### Playing with data frames: profiles and time series" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "republican-surveillance", - "metadata": {}, - "outputs": [], - "source": [ - "list(DB.db.keys())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "detected-alabama", - "metadata": {}, - "outputs": [], - "source": [ - "TS_id = list(DB.db.keys())[0] # you can choose any\n", - "TS_id" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "excellent-affect", - "metadata": {}, - "outputs": [], - "source": [ - "df = DB.db[TS_id]['timeseries']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "broke-reconstruction", - "metadata": {}, - "outputs": [], - "source": [ - "df" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "rough-bidder", - "metadata": {}, - "outputs": [], - "source": [ - "df[['distance']].iplot()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "organic-argument", - "metadata": {}, - "outputs": [], - "source": [ - "pf = DB.db[TS_id]['profile']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "polyphonic-parade", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "pf # distance km and duration min" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "juvenile-israeli", - "metadata": {}, - "outputs": [], - "source": [ - "for name in DB.db:\n", - " kind = DB.db[name]['kind']\n", - " if kind != 'driving':\n", - " input_ = DB.db[name]['input'] # upstream profile, e.g. charging <- availability <- consumption <- driving\n", - " print(kind, name, '<-', input_)\n", - " else:\n", - " print(kind, name)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "318c64cd", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS = DB.db[cname]['timeseries']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8ee83d02", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e375f67a", - "metadata": {}, - "outputs": [], - "source": [ - "Consumption_TS[['consumption','instant consumption in W', 'average power in W']].iplot() # Consumption in kWh/timestep -> timestep 15 min in this example\n", - "# Instant consumption only displayed when timestep is 1s." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bc643a8b", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "moderate-measurement", + "metadata": {}, + "outputs": [], + "source": [ + "from emobpy import DataBase, Export\n", + "from emobpy.plot import NBplot\n", + "import plotly.express as px\n", + "import plotly.graph_objects as go" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "subject-sussex", + "metadata": {}, + "outputs": [], + "source": [ + "DBm = DataBase('db')\n", + "DBm.loadfiles_batch(kind=\"driving\") # load files in parallel that only contains Mobility time-series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "level-lightning", + "metadata": {}, + "outputs": [], + "source": [ + "mname = list(DBm.db.keys())[0]\n", + "mname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "level-friday", + "metadata": {}, + "outputs": [], + "source": [ + "vizm = NBplot(DBm)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "discrete-tower", + "metadata": {}, + "outputs": [], + "source": [ + "figm = vizm.sgplot_dp(mname)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9163fb06", + "metadata": {}, + "outputs": [], + "source": [ + "figm.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "scientific-liverpool", + "metadata": {}, + "outputs": [], + "source": [ + "DBc = DataBase('db')\n", + "DBc.loadfiles_batch(kind=\"consumption\", add_variables=['Trips'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "empty-elite", + "metadata": {}, + "outputs": [], + "source": [ + "cname = list(DBc.db.keys())[0]\n", + "cname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "sound-office", + "metadata": {}, + "outputs": [], + "source": [ + "vizc = NBplot(DBc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "neural-haiti", + "metadata": {}, + "outputs": [], + "source": [ + "figc = vizc.sankey(cname, include=None, to_html=False, path='sankey.html')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "beneficial-today", + "metadata": {}, + "outputs": [], + "source": [ + "figc.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "encouraging-literature", + "metadata": {}, + "outputs": [], + "source": [ + "DBa = DataBase('db')\n", + "DBa.loadfiles_batch(kind=\"availability\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "suited-windows", + "metadata": {}, + "outputs": [], + "source": [ + "aname = list(DBa.db.keys())[0]\n", + "aname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "preliminary-consent", + "metadata": {}, + "outputs": [], + "source": [ + "viza = NBplot(DBa)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "spare-syntax", + "metadata": {}, + "outputs": [], + "source": [ + "figg = viza.sgplot_ga(aname, rng=None, to_html=False, path=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4d4fe33", + "metadata": {}, + "outputs": [], + "source": [ + "figg.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "statistical-newcastle", + "metadata": {}, + "outputs": [], + "source": [ + "DBd = DataBase('db')\n", + "DBd.loadfiles_batch(kind=\"charging\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "representative-current", + "metadata": {}, + "outputs": [], + "source": [ + "dname = list(DBd.db.keys())[0]\n", + "dname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "smoking-lambda", + "metadata": {}, + "outputs": [], + "source": [ + "vizd = NBplot(DBd)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "rapid-advice", + "metadata": {}, + "outputs": [], + "source": [ + "figd = vizd.sgplot_ged(dname, rng=None, to_html=False, path=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9a4efd0", + "metadata": {}, + "outputs": [], + "source": [ + "figd.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "protecting-reliance", + "metadata": {}, + "outputs": [], + "source": [ + "DB = DataBase('db')\n", + "DB.update()\n", + "Exp = Export()\n", + "Exp.loaddata(DB)\n", + "Exp.to_csv()\n", + "Exp.save_files()\n", + "# See the two CSV files at \"db\" folder" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b9a54e5", + "metadata": {}, + "outputs": [], + "source": [ + "viz = NBplot(DB)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e6e606b", + "metadata": {}, + "outputs": [], + "source": [ + "fig = viz.overview(dname)\n", + "fig.show()" + ] + }, + { + "cell_type": "markdown", + "id": "weekly-nelson", + "metadata": {}, + "source": [ + "### Playing with data frames: profiles and time series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "republican-surveillance", + "metadata": {}, + "outputs": [], + "source": [ + "list(DB.db.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "detected-alabama", + "metadata": {}, + "outputs": [], + "source": [ + "TS_id = list(DB.db.keys())[0] # you can choose any\n", + "TS_id" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "excellent-affect", + "metadata": {}, + "outputs": [], + "source": [ + "df = DB.db[TS_id]['timeseries']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "broke-reconstruction", + "metadata": {}, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "rough-bidder", + "metadata": {}, + "outputs": [], + "source": [ + "fig_dist = px.line(df, y=\"distance\", title=\"distance\")\n", + "fig_dist.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "organic-argument", + "metadata": {}, + "outputs": [], + "source": [ + "pf = DB.db[TS_id]['profile']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "polyphonic-parade", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "pf # distance km and duration min" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "juvenile-israeli", + "metadata": {}, + "outputs": [], + "source": [ + "for name in DB.db:\n", + " kind = DB.db[name]['kind']\n", + " if kind != 'driving':\n", + " input_ = DB.db[name]['input'] # upstream profile, e.g. charging <- availability <- consumption <- driving\n", + " print(kind, name, '<-', input_)\n", + " else:\n", + " print(kind, name)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "318c64cd", + "metadata": {}, + "outputs": [], + "source": [ + "Consumption_TS = DB.db[cname]['timeseries']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ee83d02", + "metadata": {}, + "outputs": [], + "source": [ + "Consumption_TS" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e375f67a", + "metadata": {}, + "outputs": [], + "source": [ + "cols = [\"consumption\", \"instant consumption in W\", \"average power in W\"]\n", + "fig_cons = go.Figure()\n", + "for col in cols:\n", + " fig_cons.add_trace(\n", + " go.Scatter(x=Consumption_TS.index, y=Consumption_TS[col], name=col, mode=\"lines\")\n", + " )\n", + "fig_cons.update_layout(title=\"Consumption time series\")\n", + "fig_cons.show()\n", + "# Consumption in kWh/timestep -> timestep 15 min in this example\n", + "# Instant consumption only displayed when timestep is 1s." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc643a8b", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/emobpy/export.py b/emobpy/export.py index d5b3bec..1c5b7c2 100644 --- a/emobpy/export.py +++ b/emobpy/export.py @@ -137,7 +137,7 @@ def to_csv(self): self.optdict = dict(zip(self.setopt, range(len(self.setopt)))) self.arr_options = np.empty((len(self.setopt), len(self.code), self.rows)) for id1, cd in enumerate(self.code): - if self.subscen[cd]: + if cd in self.subscen and self.subscen[cd]: for key, value in self.subscen[cd].items(): id0 = self.optdict[key] df = self.data.db[value]["timeseries"][ @@ -165,7 +165,8 @@ def to_csv(self): self.final["Hour", "-", "-"] = ["h" + str(j + 1) for j in range(self.rows)] self.final.set_index(("Hour", "-", "-"), inplace=True) self.final.index.name = "Hour" - self.final = self.final.round(7) + _num = self.final.select_dtypes(include="number").columns + self.final[_num] = self.final[_num].astype(np.float64).round(7) def save_files(self, repository=""): """ diff --git a/emobpy/functions.py b/emobpy/functions.py index 5ace076..b3dcfb8 100644 --- a/emobpy/functions.py +++ b/emobpy/functions.py @@ -495,6 +495,97 @@ def resistances(zone_layer, zone_area, layer_conductivity, layer_thickness, return R_z.sum() +@numba.jit(nopython=True) +def _density_ideal_gas_numba(T_C, P_mbar): + """Luftdichte nach Idealgasgesetz [kg/m³]; T_C in °C, P_mbar in mbar.""" + return (100.0 * P_mbar) / (287.05 * (T_C + 273.15)) + + +@numba.jit(nopython=True) +def qhvac_numba( + T_out, + T_targ, + cabin_volume, + flow_air, + zone_layer, + zone_area, + layer_conductivity, + layer_thickness, + vehicle_speed, + Q_sensible=70.0, + persons=1.0, + P_out=1013.25, + air_cabin_heat_transfer_coef=10.0, +): + """ + Numba-beschleunigte HVAC-Wärmelast mit Idealgas-Dichte (wie qhvac, aber ohne D-Callable). + Q[:, 0] = Qtotal; weitere Spalten wie in qhvac. + """ + n = vehicle_speed.shape[0] + T = np.zeros(n) + Q = np.zeros((n, 8)) + if T_targ is None or (T_targ != T_targ): + return Q, T + t_diff = T_out - T_targ + if t_diff > 0: + plus = -0.05 + sign = -1 + else: + plus = 0.05 + sign = 1 + + rho_out = _density_ideal_gas_numba(T_out, P_out) + mass_flow_in = flow_air * rho_out + cp_out = cp(T_out) + + for tm in range(n): + if tm == 0: + t_1 = T_out + t = T_out + plus + else: + t_1 = T[tm - 1] + if sign == -1: + if np.round(t, 2) > T_targ: + t += plus + else: + t = T_targ + else: + if np.round(t, 2) < T_targ: + t += plus + else: + t = T_targ + + Q_in_per = q_person(Q_sensible, persons) + Q[tm, 1] = Q_in_per + Q_in_vent = q_ventilation(rho_out, flow_air, cp_out, T_out) + Q[tm, 2] = Q_in_vent + rho_t = _density_ideal_gas_numba(t, P_out) + cp_t = cp(t) + Q_out_vent = q_ventilation( + rho_t, mass_flow_in / rho_t, cp_t, t + ) + Q[tm, 3] = Q_out_vent + Q_tr = q_transfer( + zone_layer, zone_area, layer_conductivity, + layer_thickness, t, T_out, vehicle_speed[tm], + air_cabin_heat_transfer_coef, + ) + Q[tm, 4] = Q_tr + Q[tm, 0] = ( + cabin_volume * rho_t * cp_t * (t - t_1) + - Q_in_per - Q[tm, 2] + Q_out_vent + Q_tr + ) + T[tm] = t + Q[tm, 5] = rho_out + Q[tm, 6] = rho_t + Q[tm, 7] = resistances( + zone_layer, zone_area, layer_conductivity, + layer_thickness, vehicle_speed[tm], + air_cabin_heat_transfer_coef, + ) + return Q, T + + # @numba.jit(nopython=True) def qhvac(D, T_out, diff --git a/emobpy/mobility.py b/emobpy/mobility.py index d193ae2..c0673b6 100755 --- a/emobpy/mobility.py +++ b/emobpy/mobility.py @@ -924,20 +924,20 @@ def _fill_rows(self): self.timeseries = pd.DataFrame(columns=self.db.columns) self.timeseries.loc[:, "hh"] = np.arange(0, self.hours, self.t) - # Start New version, which works for 1s-based profiles: - temp_timeseries = [round(num * 3600) for num in self.timeseries["hh"]] - temp_db = [round(num * 3600) for num in self.db["hr"]] - temp_intersection_list = list(set(temp_timeseries).intersection(temp_db)) - - self.idx = [] - for i in temp_intersection_list: - self.idx.append(temp_timeseries.index(i)) - self.idx = np.sort(self.idx).tolist() # values might be unsorted -> sort + # Start New version, which works for 1s-based profiles (vectorized): + temp_ts = np.round(self.timeseries["hh"].values * 3600).astype(np.int64) + temp_db = np.round(self.db["hr"].values * 3600).astype(np.int64) + order = np.argsort(temp_ts) + sorted_ts = temp_ts[order] + pos = np.searchsorted(sorted_ts, temp_db) + idx = order[pos] + sorted_by_idx = np.argsort(idx) + self.idx = idx[sorted_by_idx].tolist() # End new version self.mixed = self.repeats_float + self.repeats_str + self.copied for r in self.mixed: - self.val = self.db[r].values.tolist() + self.val = self.db[r].values[sorted_by_idx] self.timeseries.loc[self.idx, r] = self.val self.timeseries.loc[self.totalrows - 1, "state"] = self.db["state"].iloc[-1] self.timeseries.loc[self.totalrows - 1, "hr"] = self.timeseries["hh"][self.totalrows - 1] @@ -1034,7 +1034,17 @@ def run(self): self.prev_dest = self.initial_state # it is the first state at the beginning of the profile self.total_days = int(self.hours / 24) - self.profile = pd.DataFrame() + hr_list = [] + state_list = [] + departure_list = [] + arrival_list = [] + last_arrival_list = [] + purpose_list = [] + duration_list = [] + weekday_list = [] + category_list = [] + distance_list = [] + trip_duration_list = [] endflag = False lastflag = False for _ in range(self.numb_weeks): @@ -1046,51 +1056,73 @@ def run(self): self._select_tour() self.prev_dest = copy.deepcopy(self.prev_dst) if not self.no_trip: - for _, row in self.tour.iterrows(): - self.hr = row["departure"] + self.days * 24.0 - self.t + for row in self.tour.itertuples(index=False): + self.hr = row.departure + self.days * 24.0 - self.t if self.hr == self.hours - self.t: - self.profile.loc[self.hr, "hr"] = self.hr - self.profile.loc[self.hr, "state"] = row["state"] - self.profile.loc[self.hr, "departure"] = row["departure"] - self.profile.loc[self.hr, "arrival"] = row["arrival"] - self.profile.loc[self.hr, "last_arrival"] = row["last_arrival"] - self.profile.loc[self.hr, "purpose"] = row["purpose"] - self.profile.loc[self.hr, "duration"] = row["duration"] - self.profile.loc[self.hr, "weekday"] = self.weeks[self.n_day]["day"] - self.profile.loc[self.hr, "category"] = self.user_defined - self.profile.loc[self.hr, "distance"] = 0 - self.profile.loc[self.hr, "trip_duration"] = 0 + hr_list.append(self.hr) + state_list.append(row.state) + departure_list.append(row.departure) + arrival_list.append(row.arrival) + last_arrival_list.append(row.last_arrival) + purpose_list.append(row.purpose) + duration_list.append(row.duration) + weekday_list.append(self.weeks[self.n_day]["day"]) + category_list.append(self.user_defined) + distance_list.append(0) + trip_duration_list.append(0) endflag = True break elif self.hr > self.hours - self.t: endflag = True break elif self.hr < self.hours - self.t: - self.profile.loc[self.hr, "hr"] = self.hr - self.profile.loc[self.hr, "state"] = row["state"] - self.profile.loc[self.hr, "departure"] = row["departure"] - self.profile.loc[self.hr, "arrival"] = row["arrival"] - self.profile.loc[self.hr, "last_arrival"] = row["last_arrival"] - self.profile.loc[self.hr, "purpose"] = row["purpose"] - self.profile.loc[self.hr, "duration"] = row["duration"] - self.profile.loc[self.hr, "weekday"] = self.weeks[self.n_day]["day"] - self.profile.loc[self.hr, "category"] = self.user_defined - self.profile.loc[self.hr, "distance"] = 0 - self.profile.loc[self.hr, "trip_duration"] = 0 - # if (self.hr + row["timesteps"] * self.t) > self.hours - self.t: - # endflag = True - # break - # add driving in next row - self.profile.loc[self.hr + row["timesteps"] * self.t, "hr"] = (self.hr + row["timesteps"] * self.t) - self.profile.loc[self.hr + row["timesteps"] * self.t, "state"] = "driving" - self.profile.loc[self.hr + row["timesteps"] * self.t, "distance"] = row["distance"] - self.profile.loc[self.hr + row["timesteps"] * self.t, "trip_duration"] = row["trip_duration"] + hr_list.append(self.hr) + state_list.append(row.state) + departure_list.append(row.departure) + arrival_list.append(row.arrival) + last_arrival_list.append(row.last_arrival) + purpose_list.append(row.purpose) + duration_list.append(row.duration) + weekday_list.append(self.weeks[self.n_day]["day"]) + category_list.append(self.user_defined) + distance_list.append(0) + trip_duration_list.append(0) + hr_drive = self.hr + row.timesteps * self.t + hr_list.append(hr_drive) + state_list.append("driving") + departure_list.append(np.nan) + arrival_list.append(np.nan) + last_arrival_list.append(np.nan) + purpose_list.append(np.nan) + duration_list.append(np.nan) + weekday_list.append(np.nan) + category_list.append(np.nan) + distance_list.append(row.distance) + trip_duration_list.append(row.trip_duration) if endflag: lastflag = True break if lastflag: break print("") + if hr_list: + self.profile = pd.DataFrame({ + "hr": hr_list, + "state": state_list, + "departure": departure_list, + "arrival": arrival_list, + "last_arrival": last_arrival_list, + "purpose": purpose_list, + "duration": duration_list, + "weekday": weekday_list, + "category": category_list, + "distance": distance_list, + "trip_duration": trip_duration_list, + }) + self.profile.set_index("hr", inplace=True) + self.profile["hr"] = self.profile.index # Spalte für _fill_rows (db["hr"]) + else: + self.profile = pd.DataFrame() if not self.profile.empty: if self.profile["state"].iloc[-1] == "driving": # remove the last row self.profile diff --git a/emobpy/plot.py b/emobpy/plot.py index 17c9a42..ca24775 100644 --- a/emobpy/plot.py +++ b/emobpy/plot.py @@ -7,11 +7,9 @@ try: import plotly.graph_objects as go - from plotly.offline import iplot + import plotly.colors as pc from plotly.subplots import make_subplots from IPython.display import display, HTML - import cufflinks as cf - cf.go_offline() except ImportError: raise Exception("This plotly code only works within a jupyter notebook") @@ -77,18 +75,61 @@ def sgplot_dp(self, tscode, rng=None, to_html=False, path=None): .fillna(0) ) cn.columns = cn.columns.droplevel() - rr = (cn.T / cn.T.sum(axis=0)).T - figa = rr.iplot(kind="area", fill=True, asFigure=True) - figb = df["distance"].iplot(asFigure=True) - fig = cf.subplots([figa, figb], shape=(2, 1), shared_xaxes=True) - fig["layout"]["yaxis"].update( - {"title": "Location", "rangemode": "tozero", "domain": [0.7, 1.0], 'tickformat':".1%"} + rr = (cn.T / cn.T.sum(axis=0)).T.astype(float) + # Plotly-native stacked area + line (avoids legacy third-party dataframe plotting) + palette = pc.qualitative.Plotly + fig = make_subplots( + rows=2, + cols=1, + shared_xaxes=True, + vertical_spacing=0.08, + row_heights=[0.32, 0.68], ) - fig["layout"]["yaxis2"].update( - {"title": "Distance (km)", "rangemode": "tozero", "domain": [0.0, 0.65]} + for i, col in enumerate(rr.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=rr.index, + y=rr[col], + name=str(col), + mode="lines", + stackgroup="dp_states", + line=dict(width=0.5, color=color), + fillcolor=color, + hovertemplate="%{y:.1%}%{fullData.name}", + ), + row=1, + col=1, + ) + fig.add_trace( + go.Scatter( + x=df.index, + y=df["distance"].astype("float64"), + name="distance", + mode="lines", + line=dict(color="#636EFA"), + ), + row=2, + col=1, + ) + fig.update_yaxes( + title_text="Location", + rangemode="tozero", + tickformat=".1%", + row=1, + col=1, + ) + fig.update_yaxes( + title_text="Distance (km)", + rangemode="tozero", + row=2, + col=1, + ) + fig.update_layout( + paper_bgcolor="white", + plot_bgcolor="white", + margin=dict(l=10, r=10, t=20, b=10, pad=0), ) - - fig = go.Figure(data=fig["data"], layout=fig["layout"]) if to_html: if path is None: raise Exception( @@ -132,76 +173,109 @@ def sgplot_ga(self, tscode, rng=None, to_html=False, path=None): .fillna(0) ) cn.columns = cn.columns.droplevel() - rr = (cn.T / cn.T.sum(axis=0)).T - figa = rr.iplot(kind="area", fill=True, asFigure=True) + rr = (cn.T / cn.T.sum(axis=0)).T.astype(float) dk = dt[["consumption", "charging_cap"]] - figb = dk.iplot(asFigure=True) - dd = dt["soc"] - figc = dd.iplot(asFigure=True) - fig = cf.subplots([figa, figb, figc], shape=(3, 1), shared_xaxes=True) - fig["layout"]["xaxis"].update( - {"tickfont": {"family": "Arial, sans-serif", "size": 13, "color": "black"}} - ) - fig["layout"]["yaxis"].update( - { - "title": "Location", - "titlefont": {"size": 12}, - "showgrid": False, - "showline": True, - "rangemode": "tozero", - "zeroline": True, - "domain": [0.75, 1.0], - "tickformat":".1%", - "tickfont": { - "family": "Arial, sans-serif", - "size": 12, - "color": "black", - }, - "linewidth": 2, - } + dd = pd.to_numeric(dt["soc"], errors="coerce").astype("float64") + palette = pc.qualitative.Plotly + fig = make_subplots( + rows=3, + cols=1, + shared_xaxes=True, + vertical_spacing=0.06, + row_heights=[0.28, 0.36, 0.36], ) - fig["layout"]["yaxis2"].update( - { - "title": "Grid Availability (kW)", - "titlefont": {"size": 12}, - "showgrid": True, - "showline": True, - "rangemode": "tozero", - "domain": [0.4, 0.7], - "tickfont": { - "family": "Arial, sans-serif", - "size": 12, - "color": "black", - }, - "linewidth": 2, - } + for i, col in enumerate(rr.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=rr.index, + y=rr[col], + name=str(col), + mode="lines", + stackgroup="ga_states", + line=dict(width=0.5, color=color), + fillcolor=color, + hovertemplate="%{y:.1%}%{fullData.name}", + ), + row=1, + col=1, + ) + fig.add_trace( + go.Scatter( + x=dk.index, + y=pd.to_numeric(dk["consumption"], errors="coerce").astype("float64"), + name="consumption", + mode="lines", + line=dict(color="#636EFA"), + ), + row=2, + col=1, ) - fig["layout"]["yaxis3"].update( - { - "title": "SOC", - "titlefont": {"size": 12}, - "showgrid": True, - "showline": True, - "rangemode": "tozero", - "domain": [0.0, 0.35], - "tickformat": ".1%", - "tickfont": { - "family": "Arial, sans-serif", - "size": 12, - "color": "black", - }, - "linewidth": 2, - } + fig.add_trace( + go.Scatter( + x=dk.index, + y=pd.to_numeric(dk["charging_cap"], errors="coerce").astype("float64"), + name="charging_cap", + mode="lines", + line=dict(color="#EF553B"), + ), + row=2, + col=1, + ) + fig.add_trace( + go.Scatter( + x=dd.index, + y=dd, + name="soc", + mode="lines", + line=dict(color="#00CC96"), + ), + row=3, + col=1, + ) + fig.update_xaxes( + tickfont=dict(family="Arial, sans-serif", size=13, color="black"), + row=3, + col=1, + ) + fig.update_yaxes( + title=dict(text="Location", font=dict(size=12)), + showgrid=False, + showline=True, + rangemode="tozero", + zeroline=True, + tickformat=".1%", + tickfont=dict(family="Arial, sans-serif", size=12, color="black"), + linewidth=2, + row=1, + col=1, + ) + fig.update_yaxes( + title=dict(text="Grid Availability (kW)", font=dict(size=12)), + showgrid=True, + showline=True, + rangemode="tozero", + tickfont=dict(family="Arial, sans-serif", size=12, color="black"), + linewidth=2, + row=2, + col=1, + ) + fig.update_yaxes( + title=dict(text="SOC", font=dict(size=12)), + showgrid=True, + showline=True, + rangemode="tozero", + tickformat=".1%", + tickfont=dict(family="Arial, sans-serif", size=12, color="black"), + linewidth=2, + row=3, + col=1, + ) + fig.update_layout( + paper_bgcolor="white", + plot_bgcolor="white", + margin=dict(l=10, r=10, t=20, b=10, pad=0), ) - fig["layout"].update( - { - "paper_bgcolor": "white", - "plot_bgcolor": "white", - "margin": dict(l=10, r=10, t=20, b=10, pad=0), - } - ) # ,'width': 800,'height': 450,'showlegend': True - - fig = go.Figure(data=fig["data"], layout=fig["layout"]) if to_html: if path is None: raise Exception( @@ -255,89 +329,115 @@ def sgplot_ged(self, tscode, rng=None, to_html=False, path=None): .fillna(0) ) cn.columns = cn.columns.droplevel() - rr = (cn.T / cn.T.sum(axis=0)).T - figc = rr.iplot(kind="area", fill=True, asFigure=True) + rr = (cn.T / cn.T.sum(axis=0)).T.astype(float) dff = dt.pivot_table( index=dt.index, columns="option", values="actual_soc", aggfunc="sum" ) - figa = dff.iplot(asFigure=True) dg = dt.pivot_table( index=dt.index, columns="option", values="charge_grid", aggfunc="sum" ) - figb = dg.iplot(asFigure=True) - fig = cf.subplots([figa, figb, figc], shape=(3, 1), shared_xaxes=True) - fig["layout"]["xaxis"].update( - {"tickfont": {"family": "Arial, sans-serif", "size": 14, "color": "black"}} + palette = pc.qualitative.Plotly + fig = make_subplots( + rows=3, + cols=1, + shared_xaxes=True, + vertical_spacing=0.06, + row_heights=[0.32, 0.44, 0.24], ) - fig["layout"]["yaxis"].update( - { - "title": "SOC", - "titlefont": {"size": 14}, - "showgrid": False, - "showline": True, - "rangemode": "tozero", - "zeroline": True, - "domain": [0.7, 1.0], - "tickformat": ".1%", - "tickfont": { - "family": "Arial, sans-serif", - "size": 14, - "color": "black", - }, - "linewidth": 2, - } + for i, col in enumerate(dff.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=dff.index, + y=pd.to_numeric(dff[col], errors="coerce").astype("float64"), + name="{} (SOC)".format(col), + mode="lines", + line=dict(color=color), + ), + row=1, + col=1, + ) + for i, col in enumerate(dg.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=dg.index, + y=pd.to_numeric(dg[col], errors="coerce").astype("float64"), + name="{} (kW)".format(col), + mode="lines", + line=dict(color=color), + ), + row=2, + col=1, + ) + for i, col in enumerate(rr.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=rr.index, + y=rr[col], + name=str(col), + mode="lines", + stackgroup="ged_loc", + line=dict(width=0.5, color=color), + fillcolor=color, + hovertemplate="%{y:.1%}%{fullData.name}", + ), + row=3, + col=1, + ) + fig.update_xaxes( + tickfont=dict(family="Arial, sans-serif", size=14, color="black"), + row=3, + col=1, ) - fig["layout"]["yaxis2"].update( - { - "title": "Actual charge (kW)", - "titlefont": {"size": 14}, - "showgrid": True, - "showline": True, - "rangemode": "tozero", - "domain": [0.25, 0.65], - "tickfont": { - "family": "Arial, sans-serif", - "size": 12, - "color": "black", - }, - "linewidth": 2, - } + fig.update_yaxes( + title=dict(text="SOC", font=dict(size=14)), + showgrid=False, + showline=True, + rangemode="tozero", + zeroline=True, + tickformat=".1%", + tickfont=dict(family="Arial, sans-serif", size=14, color="black"), + linewidth=2, + row=1, + col=1, ) - fig["layout"]["yaxis3"].update( - { - "title": "Location", - "titlefont": {"size": 14}, - "showgrid": True, - "showline": True, - "rangemode": "tozero", - "domain": [0.0, 0.2], - "tickformat": ".1%", - "tickfont": { - "family": "Arial, sans-serif", - "size": 12, - "color": "black", - }, - "linewidth": 2, - } + fig.update_yaxes( + title=dict(text="Actual charge (kW)", font=dict(size=14)), + showgrid=True, + showline=True, + rangemode="tozero", + tickfont=dict(family="Arial, sans-serif", size=12, color="black"), + linewidth=2, + row=2, + col=1, + ) + fig.update_yaxes( + title=dict(text="Location", font=dict(size=14)), + showgrid=True, + showline=True, + rangemode="tozero", + tickformat=".1%", + tickfont=dict(family="Arial, sans-serif", size=12, color="black"), + linewidth=2, + row=3, + col=1, + ) + fig.update_layout( + paper_bgcolor="white", + plot_bgcolor="white", + margin=dict(l=10, r=10, t=20, b=10, pad=0), + showlegend=True, ) - fig["layout"].update( - { - "paper_bgcolor": "white", - "plot_bgcolor": "white", - "margin": dict(l=10, r=10, t=20, b=10, pad=0), - "showlegend": True, - } - ) # 'width': 800,'height': 450 - - FIG = go.Figure(data=fig["data"], layout=fig["layout"]) if to_html: if path is None: raise Exception( """when to_html is True then path must be given with .html extension""" ) else: - FIG.write_html(file=path) - return FIG + fig.write_html(file=path) + return fig def sankey(self, tscode, include=None, to_html=False, path=None): @@ -418,8 +518,22 @@ def overview(self, tscode, date_range=None, to_html=False, path=None, share_x=Tr dfs = include_weather(ts, cons['refdate'], temp_arr, pres_arr, dp_arr, hum_arr, r_ha) cdf = self.db.db[consumption_name]['profile'].copy() - dfg = pd.merge_asof(dfs, cdf[['datetime', 'speed km/h']], on="datetime", tolerance=pd.Timedelta("900s"), - direction="nearest").fillna(0.0).set_index('datetime') + _mg = pd.merge_asof( + dfs, + cdf[["datetime", "speed km/h"]], + on="datetime", + tolerance=pd.Timedelta("900s"), + direction="nearest", + ) + for _col in _mg.columns: + if _col == "datetime": + continue + _ser = _mg[_col] + if pd.api.types.is_numeric_dtype(_ser): + _mg[_col] = _ser.fillna(0.0) + else: + _mg[_col] = _ser.where(pd.notna(_ser), 0.0) + dfg = _mg.set_index("datetime") df = pd.DataFrame() availcode = self.db.db[tscode]["input"] for k in self.db.db.keys(): @@ -443,99 +557,204 @@ def overview(self, tscode, date_range=None, to_html=False, path=None, share_x=Tr .fillna(0) ) cn.columns = cn.columns.droplevel() - rr = (cn.T / cn.T.sum(axis=0)).T + rr = (cn.T / cn.T.sum(axis=0)).T.astype(float) # imput is the name of grid demand time series (charging class) and database 'db' # rr, dfg, dff, dg are dataframes resulting from a preprocessing step - fig1 = rr[start:end].iplot(kind="area", fill=True, asFigure=True) - fig2 = dfg[start:end][["distance", "consumption"]].iplot(colors=['green', 'pink'], asFigure=True) - fig3 = dfg[start:end][["temp_degC", "speed km/h"]].iplot(colors=['purple', '#9c8830'], asFigure=True) - fig4 = dg[start:end].iplot(yTitle='Power rating (kW)', asFigure=True) - fig5 = dff[start:end].iplot(yTitle='SOC', asFigure=True) - - for trace in fig5['data']: - trace['showlegend'] = True - - fig = make_subplots(rows=5, cols=1,shared_xaxes= True if share_x else False, - specs=[[{"secondary_y": True}], [{'secondary_y': True}], [{'secondary_y': True}], - [{'secondary_y': True}], [{'secondary_y': True}]]) - - [fig.add_trace(trace, secondary_y=False, row=1, col=1) for trace in fig1['data']] - fig.add_trace(fig2['data'][0], secondary_y=False, row=2, col=1) - fig.add_trace(fig2['data'][1], secondary_y=True, row=2, col=1) - fig.add_trace(fig3['data'][0], secondary_y=False, row=3, col=1) - fig.add_trace(fig3['data'][1], secondary_y=True, row=3, col=1) - [fig.add_trace(trace, secondary_y=False, row=4, col=1) for trace in fig4['data']] - [fig.add_trace(trace, secondary_y=False, row=5, col=1) for trace in fig5['data']] - - renames = {'distance': ('Distance', 2.2), - 'consumption': ('Consumption', 1.2), - 'temp_degC': ('Temperature', 2), - 'speed km/h': ('Average speed', 2), - # 'from_23_to_8_at_any': ('Charge at night', 2), - # 'immediate': ('Charge immediate', 1.5), - # 'home': ('Home', 0.6), 'driving': ('Driving', 0.6), 'workplace': ('Workplace', 0.6), - # 'errands': ('Errands', 0.6), 'leisure': ('Leisure', 0.6), 'shopping': ('Shopping', 0.6), - } - - for trace in fig['data']: - if trace['name'] in renames: - name = trace['name'] - trace['name'] = renames[name][0] - trace['line']['width'] = renames[name][1] - else: - trace['line']['width'] = 0.6 - - fig["layout"].update({'yaxis': dict(title="Location", - title_font=dict(color='black', - # size=18, - ), - showgrid=False, - zeroline=True, linecolor='black', gridcolor='#bdbdbd', tickformat=".1%", - # tickfont={"size": 12}, - ), - 'yaxis3': dict(title='Distance (km)', - title_font=dict(color='green', - # size=18, - ), - showgrid=True, zeroline=True, linecolor='black', gridcolor='#bdbdbd', - # tickfont={"size": 12}, - ), - 'yaxis4': dict(title='Consumption (kWh)', - title_font=dict(color='pink' - # size=18, - ), - showgrid=False, zeroline=True, linecolor='black', gridcolor='#bdbdbd', - # tickfont={"size": 12}, - ), - 'yaxis5': dict(title='Temp (C)', - title_font=dict(color='purple', - # size=18, - ), - showgrid=True, zeroline=True, linecolor='black', gridcolor='#bdbdbd', - zerolinecolor='black', - # tickfont={"size": 12}, - ), - 'yaxis6': dict(title='Speed (km/h)', title_font=dict(color='#9c8830' - # size=18, - ), - showgrid=False, zeroline=True, linecolor='black', gridcolor='#bdbdbd', - # tickfont={"size": 12}, - ), - 'yaxis7': dict(title='Power rating (kW)', title_font=dict(color='black', - # size=18, - ), - showgrid=True, zeroline=True, linecolor='black', gridcolor='#bdbdbd', - # tickfont={"size": 12}, - ), - 'yaxis9': dict(title='SOC', title_font=dict(color='black', - # size=18, - ), - showgrid=True, zeroline=True, linecolor='black', gridcolor='#bdbdbd', tickformat=".1%", - # tickfont={"size": 12}, - ), - }) + rr_s = rr.loc[start:end] + dfg_s = dfg.loc[start:end] + dg_s = dg.loc[start:end] + dff_s = dff.loc[start:end] + + palette = pc.qualitative.Plotly + fig = make_subplots( + rows=5, + cols=1, + shared_xaxes=True if share_x else False, + vertical_spacing=0.04, + specs=[[{"secondary_y": True}] for _ in range(5)], + ) + + for i, col in enumerate(rr_s.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=rr_s.index, + y=rr_s[col], + name=str(col), + mode="lines", + stackgroup="ov_row1", + line=dict(width=0.6, color=color), + fillcolor=color, + hovertemplate="%{y:.1%}%{fullData.name}", + ), + row=1, + col=1, + secondary_y=False, + ) + + fig.add_trace( + go.Scatter( + x=dfg_s.index, + y=pd.to_numeric(dfg_s["distance"], errors="coerce").astype("float64"), + name="Distance", + mode="lines", + line=dict(color="green", width=2.2), + ), + row=2, + col=1, + secondary_y=False, + ) + fig.add_trace( + go.Scatter( + x=dfg_s.index, + y=pd.to_numeric(dfg_s["consumption"], errors="coerce").astype("float64"), + name="Consumption", + mode="lines", + line=dict(color="pink", width=1.2), + ), + row=2, + col=1, + secondary_y=True, + ) + + fig.add_trace( + go.Scatter( + x=dfg_s.index, + y=pd.to_numeric(dfg_s["temp_degC"], errors="coerce").astype("float64"), + name="Temperature", + mode="lines", + line=dict(color="purple", width=2), + ), + row=3, + col=1, + secondary_y=False, + ) + fig.add_trace( + go.Scatter( + x=dfg_s.index, + y=pd.to_numeric(dfg_s["speed km/h"], errors="coerce").astype("float64"), + name="Average speed", + mode="lines", + line=dict(color="#9c8830", width=2), + ), + row=3, + col=1, + secondary_y=True, + ) + + for i, col in enumerate(dg_s.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=dg_s.index, + y=pd.to_numeric(dg_s[col], errors="coerce").astype("float64"), + name=str(col), + mode="lines", + line=dict(width=0.6, color=color), + ), + row=4, + col=1, + secondary_y=False, + ) + + for i, col in enumerate(dff_s.columns): + color = palette[i % len(palette)] + fig.add_trace( + go.Scatter( + x=dff_s.index, + y=pd.to_numeric(dff_s[col], errors="coerce").astype("float64"), + name=str(col), + mode="lines", + line=dict(width=0.6, color=color), + showlegend=True, + ), + row=5, + col=1, + secondary_y=False, + ) + + fig.update_yaxes( + title=dict(text="Location", font=dict(color="black")), + showgrid=False, + zeroline=True, + linecolor="black", + gridcolor="#bdbdbd", + tickformat=".1%", + rangemode="tozero", + row=1, + col=1, + secondary_y=False, + ) + fig.update_yaxes( + title=dict(text="Distance (km)", font=dict(color="green")), + showgrid=True, + zeroline=True, + linecolor="black", + gridcolor="#bdbdbd", + rangemode="tozero", + row=2, + col=1, + secondary_y=False, + ) + fig.update_yaxes( + title=dict(text="Consumption (kWh)", font=dict(color="pink")), + showgrid=False, + zeroline=True, + linecolor="black", + gridcolor="#bdbdbd", + rangemode="tozero", + row=2, + col=1, + secondary_y=True, + ) + fig.update_yaxes( + title=dict(text="Temp (C)", font=dict(color="purple")), + showgrid=True, + zeroline=True, + linecolor="black", + gridcolor="#bdbdbd", + zerolinecolor="black", + rangemode="tozero", + row=3, + col=1, + secondary_y=False, + ) + fig.update_yaxes( + title=dict(text="Speed (km/h)", font=dict(color="#9c8830")), + showgrid=False, + zeroline=True, + linecolor="black", + gridcolor="#bdbdbd", + rangemode="tozero", + row=3, + col=1, + secondary_y=True, + ) + fig.update_yaxes( + title=dict(text="Power rating (kW)", font=dict(color="black")), + showgrid=True, + zeroline=True, + linecolor="black", + gridcolor="#bdbdbd", + rangemode="tozero", + row=4, + col=1, + secondary_y=False, + ) + fig.update_yaxes( + title=dict(text="SOC", font=dict(color="black")), + showgrid=True, + zeroline=True, + linecolor="black", + gridcolor="#bdbdbd", + tickformat=".1%", + rangemode="tozero", + row=5, + col=1, + secondary_y=False, + ) fig.update_xaxes(showgrid=True, zeroline=True, linecolor='black', gridcolor='#bdbdbd') fig.update_yaxes(rangemode='tozero') diff --git a/emobpy/tools.py b/emobpy/tools.py index c24499f..8a6a2ba 100644 --- a/emobpy/tools.py +++ b/emobpy/tools.py @@ -96,39 +96,48 @@ def cmp(arg1, string_operator, arg2): operation = ops.get(string_operator) return operation(arg1, arg2) +# Progress-Bar-Throttling: nur alle N Schritte ausgeben (weniger I/O, schneller) +_MOBILITY_PROGRESS_STEP = 7 # Tage +_CONSUMPTION_PROGRESS_STEP = 10 # Trips + + def mobility_progress_bar(current, total): """ Prints actual progress in format: "Progress: 80% [8 / 10] days". + Updates only every _MOBILITY_PROGRESS_STEP days or on completion to reduce I/O. Args: current (int): Current day. total (int): Total number of days. """ + if current == total or current % _MOBILITY_PROGRESS_STEP == 0 or current == 1: + progress_message = "Progress: %d%% [%d / %d] days" % ( + current * 100 // total if total else 0, + current, + total, + ) + sys.stdout.write("\r" + progress_message) + sys.stdout.flush() - progress_message = "Progress: %d%% [%d / %d] days" % ( - current / total * 100, - current, - total, - ) - sys.stdout.write("\r" + progress_message) - sys.stdout.flush() def consumption_progress_bar(current, total): """ Prints message about consumption progress. + Updates only every _CONSUMPTION_PROGRESS_STEP trips or on completion to reduce I/O. Args: current (int): Current index. total (int): Total number of loops. width (int, optional): Not used. Defaults to 80. """ - progress_message = "Progress: %d%% [%d / %d] trips" % ( - current / total * 100, - current, - total, - ) - sys.stdout.write("\r" + progress_message) - sys.stdout.flush() + if current == total or current % _CONSUMPTION_PROGRESS_STEP == 0 or current == 1: + progress_message = "Progress: %d%% [%d / %d] trips" % ( + current * 100 // total if total else 0, + current, + total, + ) + sys.stdout.write("\r" + progress_message) + sys.stdout.flush() def wget_progress_bar(*args): """ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e26a47a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,46 @@ +[build-system] +requires = ["setuptools>=61", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "emobpy" +version = "0.6.3" +description = "Time series for battery electric vehicles modeling" +readme = "README.rst" +requires-python = ">=3.8" +license = { text = "MIT" } +authors = [ + { name = "Carlos Gaete-Morales", email = "cdgaete@gmail.com" } +] +classifiers = [ + "Intended Audience :: End Users/Desktop", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Scientific/Engineering :: Mathematics", + "Topic :: Scientific/Engineering :: Visualization" +] +dependencies = [ + "appdirs", + "plotly", + "pyyaml", + "pandas", + "wget", + "numba" +] + +[project.scripts] +emobpy = "emobpy.__main__:main" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.packages.find] +where = ["."] +include = ["emobpy*"] diff --git a/requirements.txt b/requirements.txt index c13d0a5..1dc5e64 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ appdirs plotly -cufflinks # zenodo-get pyyaml pandas diff --git a/setup.py b/setup.py deleted file mode 100644 index b2c9210..0000000 --- a/setup.py +++ /dev/null @@ -1,54 +0,0 @@ -from setuptools import setup -import os - -packages = [] -root_dir = os.path.dirname(__file__) -if root_dir: - os.chdir(root_dir) - -with open(os.path.join(root_dir, "README.rst"), encoding="utf-8") as f: - long_description = f.read() - -for dirpath, dirnames, filenames in os.walk("emobpy"): - # Ignore dirnames that start with '.' - if "__init__.py" in filenames: - pkg = dirpath.replace(os.path.sep, ".") - if os.path.altsep: - pkg = pkg.replace(os.path.altsep, ".") - packages.append(pkg) - -requirements = [req for req in open("requirements.txt").read().split("\n") if len(req) > 0] - -setup( - name="emobpy", - version="0.6.3", - packages=packages, - author="Carlos Gaete-Morales", - author_email="cdgaete@gmail.com", - maintainer="v0.5.7: Lukas Trippe, v0.6.0: Benedikt Tepe", - install_requires=requirements, - include_package_data=True, - entry_points={"console_scripts": ["emobpy = emobpy.__main__:main",],}, - url="https://gitlab.com/diw-evu/emobpy/emobpy", - long_description=long_description, - long_description_content_type="text/x-rst", - description="Time series for battery electric vehicles modeling", - classifiers=[ - "Intended Audience :: End Users/Desktop", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Topic :: Scientific/Engineering :: Information Analysis", - "Topic :: Scientific/Engineering :: Mathematics", - "Topic :: Scientific/Engineering :: Visualization", - ], -)