Created
April 9, 2025 11:18
-
-
Save jmarrec/38782cd213c06241293b028dbf9367c3 to your computer and use it in GitHub Desktop.
Comparing models and prototyping space_set_ach
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"id": "cb7b226f", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'3.8.0+f953b6fcaf'" | |
] | |
}, | |
"execution_count": 1, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"#Import modules\n", | |
"import pandas as pd\n", | |
"import numpy as np\n", | |
"import json\n", | |
"import re\n", | |
"\n", | |
"from pathlib import Path\n", | |
"\n", | |
"import sys\n", | |
"sys.path.insert(0, '/usr/local/openstudio-3.8.0/Python')\n", | |
"import openstudio\n", | |
"sys.path.pop(0)\n", | |
"openstudio.openStudioLongVersion()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"id": "a73f62cd", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"DATA_DIR = Path('../test/data/simulation')\n", | |
"ORI_INPUT_PATH = DATA_DIR / 'base/input_data_office.json'\n", | |
"NEW_INPUT_PATH = DATA_DIR / 'dynamic_attributes/input_data_office_custom-lpd.json'\n", | |
"assert ORI_INPUT_PATH.is_file()\n", | |
"assert NEW_INPUT_PATH.is_file()\n", | |
"ori_input = json.loads(ORI_INPUT_PATH.read_text())\n", | |
"new_input = json.loads(NEW_INPUT_PATH.read_text())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"id": "28c57d8c", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def compare_other(ori_o, new_o, do_print=False) -> bool:\n", | |
" result = ori_o == new_o\n", | |
" if do_print and not result:\n", | |
" print(\"{ori_o} - {new_o}\")\n", | |
" return result\n", | |
"\n", | |
"def compare_list(ori_l, new_l):\n", | |
" result = True\n", | |
" assert isinstance(ori_l, list)\n", | |
" assert isinstance(new_l, list)\n", | |
" if len(ori_l) != len(new_l):\n", | |
" print(f\"Diff in List size: {ori_l} versus {new_l}\")\n", | |
" for i, (ori_o, new_o) in enumerate(zip(ori_l, new_l)):\n", | |
" if not compare_object(ori_o, new_o):\n", | |
" print(f\"Diff at element {i}\")\n", | |
" result = False\n", | |
" return result\n", | |
" \n", | |
"def compare_dict(ori_dict, new_dict):\n", | |
" assert isinstance(ori_dict, dict)\n", | |
" assert isinstance(new_dict, dict)\n", | |
" \n", | |
" result = True\n", | |
" ori_keys = set(ori_dict.keys())\n", | |
" new_keys = set(new_dict.keys())\n", | |
" deleted_keys = ori_keys - new_keys\n", | |
" if deleted_keys:\n", | |
" print(\"Some keys were deleted\")\n", | |
" print(json.dumps({k: ori_dict[k] for k in deleted_keys}, indent=2))\n", | |
" added_keys = new_keys - ori_keys\n", | |
" if added_keys:\n", | |
" print(\"Some keys were added\")\n", | |
" print(json.dumps({k: new_dict[k] for k in added_keys}, indent=2))\n", | |
" common_keys = ori_keys.intersection(new_keys)\n", | |
" for k in common_keys:\n", | |
" if not compare_object(ori_dict[k], new_dict[k]):\n", | |
" print(f\"Diff at key={k}\")\n", | |
" result = False\n", | |
" return result\n", | |
" \n", | |
"def compare_object(ori_o, new_o):\n", | |
" if isinstance(ori_o, dict):\n", | |
" return compare_dict(ori_o, new_o)\n", | |
" elif isinstance(ori_o, list):\n", | |
" return compare_list(ori_o, new_o)\n", | |
" else:\n", | |
" return compare_other(ori_o, new_o)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"id": "49a4d421", | |
"metadata": { | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Some keys were added\n", | |
"{\n", | |
" \"heritage_designation\": \"https://mapmortar.io/#heritage-none\",\n", | |
" \"heating_source\": \"https://mapmortar.io/#gas-boiler\",\n", | |
" \"lighting_power_density\": 10.0,\n", | |
" \"longitude\": -0.07984748653345086,\n", | |
" \"latitude\": 51.5478814,\n", | |
" \"natural_gas_is_available\": true,\n", | |
" \"occupancy_classification\": \"https://bedes.lbl.gov/bedes-online/office\",\n", | |
" \"simulation_engine_version\": \"2024-06-18-A\",\n", | |
" \"epcs\": []\n", | |
"}\n", | |
"Some keys were deleted\n", | |
"{\n", | |
" \"equipment_power_density\": null\n", | |
"}\n", | |
"Diff at key=lighting_power_density\n", | |
"Diff at element 1\n", | |
"Some keys were deleted\n", | |
"{\n", | |
" \"equipment_power_density\": null\n", | |
"}\n", | |
"Diff at key=lighting_power_density\n", | |
"Diff at element 2\n", | |
"Some keys were deleted\n", | |
"{\n", | |
" \"equipment_power_density\": null\n", | |
"}\n", | |
"Diff at key=lighting_power_density\n", | |
"Diff at element 5\n", | |
"Diff at key=sections\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"False" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"compare_object(ori_input, new_input)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"id": "04e21a70", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from copy import deepcopy" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"id": "4418fb7c", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"ori_sections = []\n", | |
"for x in deepcopy(ori_input['sections']):\n", | |
" x.pop('resources')\n", | |
" x.pop('fenestration_system')\n", | |
" x.pop('occupancy_classification')\n", | |
" ori_sections.append(x)\n", | |
" \n", | |
"new_sections = []\n", | |
"for x in deepcopy(new_input['sections']):\n", | |
" x.pop('resources')\n", | |
" x.pop('fenestration_system')\n", | |
" x.pop('occupancy_classification')\n", | |
" new_sections.append(x)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"id": "48c3982b", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"df_input = pd.concat({\n", | |
" 'ori': pd.DataFrame(ori_sections).set_index('story'),\n", | |
" 'new': pd.DataFrame(new_sections).set_index('story'),\n", | |
"}, axis=1) #.swaplevel(0, 1, axis=1).sort_index(axis=1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"id": "60eab8b3", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"df_input = df_input.fillna('-')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"id": "e36de620", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"OccupancyLevels False\n", | |
"wwr False\n", | |
"people_per_floor_area False\n", | |
"lighting_power_density True\n", | |
"equipment_power_density False\n", | |
"dtype: bool" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"diffs = (df_input['ori'] != df_input['new']).any()\n", | |
"diffs" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "f7dbbf45", | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"id": "cf87821a", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead tr th {\n", | |
" text-align: left;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead tr:last-of-type th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr>\n", | |
" <th></th>\n", | |
" <th colspan=\"2\" halign=\"left\">OccupancyLevels</th>\n", | |
" <th colspan=\"2\" halign=\"left\">equipment_power_density</th>\n", | |
" <th colspan=\"2\" halign=\"left\">lighting_power_density</th>\n", | |
" <th colspan=\"2\" halign=\"left\">people_per_floor_area</th>\n", | |
" <th colspan=\"2\" halign=\"left\">wwr</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th></th>\n", | |
" <th>new</th>\n", | |
" <th>ori</th>\n", | |
" <th>new</th>\n", | |
" <th>ori</th>\n", | |
" <th>new</th>\n", | |
" <th>ori</th>\n", | |
" <th>new</th>\n", | |
" <th>ori</th>\n", | |
" <th>new</th>\n", | |
" <th>ori</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>story</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>0.3</td>\n", | |
" <td>0.3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>10.0</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>0.3</td>\n", | |
" <td>0.3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>20.0</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>0.3</td>\n", | |
" <td>0.3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>0.3</td>\n", | |
" <td>0.3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>0.3</td>\n", | |
" <td>0.3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>34.0</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" <td>0.3</td>\n", | |
" <td>0.3</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" OccupancyLevels equipment_power_density lighting_power_density \\\n", | |
" new ori new ori new \n", | |
"story \n", | |
"0 - - - - - \n", | |
"1 - - - - 10.0 \n", | |
"2 - - - - 20.0 \n", | |
"3 - - - - - \n", | |
"4 - - - - - \n", | |
"5 - - - - 34.0 \n", | |
"\n", | |
" people_per_floor_area wwr \n", | |
" ori new ori new ori \n", | |
"story \n", | |
"0 - - - 0.3 0.3 \n", | |
"1 - - - 0.3 0.3 \n", | |
"2 - - - 0.3 0.3 \n", | |
"3 - - - 0.3 0.3 \n", | |
"4 - - - 0.3 0.3 \n", | |
"5 - - - 0.3 0.3 " | |
] | |
}, | |
"execution_count": 10, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df_input = df_input.swaplevel(0, 1, axis=1).sort_index(axis=1)\n", | |
"df_input" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"id": "bcb11eed", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead tr th {\n", | |
" text-align: left;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead tr:last-of-type th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr>\n", | |
" <th></th>\n", | |
" <th colspan=\"2\" halign=\"left\">lighting_power_density</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th></th>\n", | |
" <th>new</th>\n", | |
" <th>ori</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>story</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>10.0</td>\n", | |
" <td>-</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>20.0</td>\n", | |
" <td>-</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>-</td>\n", | |
" <td>-</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>34.0</td>\n", | |
" <td>-</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" lighting_power_density \n", | |
" new ori\n", | |
"story \n", | |
"0 - -\n", | |
"1 10.0 -\n", | |
"2 20.0 -\n", | |
"3 - -\n", | |
"4 - -\n", | |
"5 34.0 -" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df_input.loc[:, diffs.index[diffs].tolist()].sort_index(axis=1)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "8da70deb", | |
"metadata": {}, | |
"source": [ | |
"# Model compare" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"id": "a7239833", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"ORI_DIR = Path('office')\n", | |
"NEW_DIR = Path('office_custom-lpd')\n", | |
"\n", | |
"RUN_DIRS = {\n", | |
" 'ori': ORI_DIR,\n", | |
" 'new': NEW_DIR,\n", | |
"}\n", | |
"\n", | |
"def get_file(test_case: str, rel_p: Path | str) -> Path:\n", | |
" p = RUN_DIRS[test_case] / rel_p\n", | |
" assert p.is_file()\n", | |
" return p" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"id": "6e2840ad", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"m_ori = openstudio.model.Model.load(get_file(test_case='ori', rel_p='run/in.osm')).get()\n", | |
"m_new = openstudio.model.Model.load(get_file(test_case='new', rel_p='run/in.osm')).get()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "17f6806a", | |
"metadata": {}, | |
"source": [ | |
"## Object Counts" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"id": "62aba69f", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"OBJECTS = [\n", | |
" 'SpaceType',\n", | |
" 'Space',\n", | |
" 'People',\n", | |
" 'PeopleDefinition',\n", | |
" 'Lights',\n", | |
" 'LightsDefinition',\n", | |
" 'ElectricEquipment',\n", | |
" 'ElectricEquipmentDefinition'\n", | |
"]\n", | |
"def object_counts(m: openstudio.model.Model):\n", | |
" count = {'Total': len(m.objects())}\n", | |
" for o in OBJECTS:\n", | |
" count[o] = len(getattr(m, f\"get{o}s\")())\n", | |
" return count" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"id": "9ed81c7f", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>ori</th>\n", | |
" <th>new</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>Total</th>\n", | |
" <td>575</td>\n", | |
" <td>593</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>SpaceType</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Space</th>\n", | |
" <td>6</td>\n", | |
" <td>6</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>People</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>PeopleDefinition</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Lights</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>LightsDefinition</th>\n", | |
" <td>2</td>\n", | |
" <td>5</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>ElectricEquipment</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>ElectricEquipmentDefinition</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" ori new\n", | |
"Total 575 593\n", | |
"SpaceType 1 4\n", | |
"Space 6 6\n", | |
"People 1 4\n", | |
"PeopleDefinition 2 2\n", | |
"Lights 1 4\n", | |
"LightsDefinition 2 5\n", | |
"ElectricEquipment 1 4\n", | |
"ElectricEquipmentDefinition 2 2" | |
] | |
}, | |
"execution_count": 15, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df_counts = pd.DataFrame({\n", | |
" 'ori': object_counts(m_ori),\n", | |
" 'new': object_counts(m_new),\n", | |
"})\n", | |
"df_counts" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"id": "4a3ff427", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>ori</th>\n", | |
" <th>new</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>Total</th>\n", | |
" <td>575</td>\n", | |
" <td>593</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>SpaceType</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>People</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Lights</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>LightsDefinition</th>\n", | |
" <td>2</td>\n", | |
" <td>5</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>ElectricEquipment</th>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" ori new\n", | |
"Total 575 593\n", | |
"SpaceType 1 4\n", | |
"People 1 4\n", | |
"Lights 1 4\n", | |
"LightsDefinition 2 5\n", | |
"ElectricEquipment 1 4" | |
] | |
}, | |
"execution_count": 16, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df_counts.loc[df_counts['ori'] != df_counts['new']]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "5a87b97d", | |
"metadata": {}, | |
"source": [ | |
"## Space Loads" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"id": "b279fd06", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def space_loads(s: openstudio.model.Space, absolute: bool = False) -> dict[str, float]:\n", | |
" if absolute:\n", | |
" return {\n", | |
" 'name': s.nameString(),\n", | |
" 'area': s.floorArea(),\n", | |
" 'people': s.numberOfPeople(),\n", | |
" 'light': s.lightingPower(),\n", | |
" 'elec': s.electricEquipmentPower(),\n", | |
" 'ach': s.infiltrationDesignFlowRate(),\n", | |
" }\n", | |
" else:\n", | |
" return {\n", | |
" 'name': s.nameString(),\n", | |
" 'area': s.floorArea(),\n", | |
" 'people': s.peoplePerFloorArea(),\n", | |
" 'light': s.lightingPowerPerFloorArea(),\n", | |
" 'elec': s.electricEquipmentPowerPerFloorArea(),\n", | |
" 'ach': s.infiltrationDesignAirChangesPerHour(),\n", | |
" }\n", | |
"\n", | |
"def model_space_loads(m: openstudio.model.Model) -> pd.DataFrame:\n", | |
" df = pd.DataFrame([space_loads(s) for s in m.getSpaces()])\n", | |
" df.set_index('name', inplace=True)\n", | |
" df.sort_index(axis=0, inplace=True)\n", | |
" return df" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"id": "951f40a3", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead tr th {\n", | |
" text-align: left;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead tr:last-of-type th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr>\n", | |
" <th></th>\n", | |
" <th colspan=\"5\" halign=\"left\">ori</th>\n", | |
" <th colspan=\"5\" halign=\"left\">new</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th></th>\n", | |
" <th>area</th>\n", | |
" <th>people</th>\n", | |
" <th>light</th>\n", | |
" <th>elec</th>\n", | |
" <th>ach</th>\n", | |
" <th>area</th>\n", | |
" <th>people</th>\n", | |
" <th>light</th>\n", | |
" <th>elec</th>\n", | |
" <th>ach</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>name</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>Level 0</th>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Level 1</th>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>10.000000</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Level 2</th>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>20.000000</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Level 3</th>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Level 4</th>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Level 5</th>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>8.826407</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" <td>1968.713084</td>\n", | |
" <td>0.05382</td>\n", | |
" <td>34.000000</td>\n", | |
" <td>8.072933</td>\n", | |
" <td>0.25</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" ori new \\\n", | |
" area people light elec ach area people \n", | |
"name \n", | |
"Level 0 1968.713084 0.05382 8.826407 8.072933 0.25 1968.713084 0.05382 \n", | |
"Level 1 1968.713084 0.05382 8.826407 8.072933 0.25 1968.713084 0.05382 \n", | |
"Level 2 1968.713084 0.05382 8.826407 8.072933 0.25 1968.713084 0.05382 \n", | |
"Level 3 1968.713084 0.05382 8.826407 8.072933 0.25 1968.713084 0.05382 \n", | |
"Level 4 1968.713084 0.05382 8.826407 8.072933 0.25 1968.713084 0.05382 \n", | |
"Level 5 1968.713084 0.05382 8.826407 8.072933 0.25 1968.713084 0.05382 \n", | |
"\n", | |
" \n", | |
" light elec ach \n", | |
"name \n", | |
"Level 0 8.826407 8.072933 0.25 \n", | |
"Level 1 10.000000 8.072933 0.25 \n", | |
"Level 2 20.000000 8.072933 0.25 \n", | |
"Level 3 8.826407 8.072933 0.25 \n", | |
"Level 4 8.826407 8.072933 0.25 \n", | |
"Level 5 34.000000 8.072933 0.25 " | |
] | |
}, | |
"execution_count": 18, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df_loads = pd.concat({\n", | |
" 'ori': model_space_loads(m_ori),\n", | |
" 'new': model_space_loads(m_new),\n", | |
"}, axis=1)\n", | |
"\n", | |
"df_loads" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"id": "d9825043", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"df_loads = df_loads.stack(future_stack=True)\n", | |
"df_loads = df_loads[df_loads['ori'] != df_loads['new']]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"id": "3d81b37f", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th>ori</th>\n", | |
" <th>new</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>name</th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>Level 1</th>\n", | |
" <th>light</th>\n", | |
" <td>8.826407</td>\n", | |
" <td>10.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Level 2</th>\n", | |
" <th>light</th>\n", | |
" <td>8.826407</td>\n", | |
" <td>20.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>Level 5</th>\n", | |
" <th>light</th>\n", | |
" <td>8.826407</td>\n", | |
" <td>34.0</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" ori new\n", | |
"name \n", | |
"Level 1 light 8.826407 10.0\n", | |
"Level 2 light 8.826407 20.0\n", | |
"Level 5 light 8.826407 34.0" | |
] | |
}, | |
"execution_count": 20, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df_loads" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "b69190f9", | |
"metadata": {}, | |
"source": [ | |
"# Prototype space_set_ach" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"id": "7868b065", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def space_get_all_spis(s: openstudio.model.Space) -> float:\n", | |
" \"\"\"Returns both the SpaceInfiltrationDesignFlowRates defined on the Space and the SpaceType if any.\"\"\"\n", | |
" all_spis = list(s.spaceInfiltrationDesignFlowRates())\n", | |
" if sp_ := s.spaceType():\n", | |
" all_spis += sp_.get().spaceInfiltrationDesignFlowRates()\n", | |
" return all_spis" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"id": "457a9dc3", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def space_set_ach(s: openstudio.model.Space, ach: float) -> bool:\n", | |
" if ach < 0:\n", | |
" return False\n", | |
" \n", | |
" # First thing first: if the SpaceType already has SpaceInfiltrationDesignFlowRates, \n", | |
" # AND that SpaceType is used by more than 1 ParentObject (Space, Building)\n", | |
" # we must clone it or we'll double count infiltration\n", | |
" if (sp_ := s.spaceType()).is_initialized():\n", | |
" sp = sp_.get()\n", | |
" sp_spis = sp.spaceInfiltrationDesignFlowRates()\n", | |
" if len(sp_spis) > 0:\n", | |
"\n", | |
" sp_sources = (\n", | |
" list(sp.getSources(openstudio.IddObjectType(\"OS:Space\"))) +\n", | |
" list(sp.getSources(openstudio.IddObjectType(\"OS:Building\")))\n", | |
" )\n", | |
" if len(sp_sources) > 1:\n", | |
" print(f\"Cloning SpaceType because it has {len(sp_spis)} spis and is used by {len(sp_sources) } sources\")\n", | |
" sp_clone = sp.clone(s.model()).to_SpaceType().get()\n", | |
" sp_clone.setName(f\"{sp.nameString()} - {s.nameString()}\")\n", | |
" s.setSpaceType(sp_clone)\n", | |
" # Remove all spis\n", | |
" [spi.remove() for spi in sp_clone.spaceInfiltrationDesignFlowRates()]\n", | |
" \n", | |
" \n", | |
" spis = s.spaceInfiltrationDesignFlowRates()\n", | |
" spi = None\n", | |
" if not spis:\n", | |
" spi = openstudio.model.SpaceInfiltrationDesignFlowRate(s.model())\n", | |
" else:\n", | |
" spi = spis[0]\n", | |
" if len(spis) > 1:\n", | |
" # Remove all but the one we keep\n", | |
" [spi.remove() for spi in spis[1:]]\n", | |
" \n", | |
" spi.setName(f\"{s.nameString()} Infiltration {round(ach, 2)} ach\")\n", | |
" spi.setAirChangesperHour(ach)\n", | |
" spi.setSpace(s)\n", | |
" return True" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"id": "6bd09595", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"m = openstudio.model.Model.load(get_file(test_case='ori', rel_p='run/in.osm')).get()\n", | |
"s = m.getSpaceByName(\"Level 5\").get()\n", | |
"sp = s.spaceType().get()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"id": "88b22445", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[]" | |
] | |
}, | |
"execution_count": 24, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"[print(x) for x in s.spaceInfiltrationDesignFlowRates()]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"id": "f6331083", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"OS:SpaceInfiltration:DesignFlowRate,\n", | |
" {ae86a43d-074c-444d-a699-2cac6fd4d2de}, !- Handle\n", | |
" MediumOffice Whole Building Infiltration, !- Name\n", | |
" {13ca7a79-9cf4-4621-aa24-a53079804e7f}, !- Space or SpaceType Name\n", | |
" , !- Schedule Name\n", | |
" AirChanges/Hour, !- Design Flow Rate Calculation Method\n", | |
" , !- Design Flow Rate {m3/s}\n", | |
" , !- Flow per Space Floor Area {m3/s-m2}\n", | |
" , !- Flow per Exterior Surface Area {m3/s-m2}\n", | |
" 0.25, !- Air Changes per Hour {1/hr}\n", | |
" , !- Constant Term Coefficient\n", | |
" , !- Temperature Term Coefficient\n", | |
" , !- Velocity Term Coefficient\n", | |
" ; !- Velocity Squared Term Coefficient\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"[None]" | |
] | |
}, | |
"execution_count": 25, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"[print(x) for x in sp.spaceInfiltrationDesignFlowRates()]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"id": "1cac271d", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Cloning SpaceType because it has 1 spis and is used by 7 sources\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"True" | |
] | |
}, | |
"execution_count": 26, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"space_set_ach(s=s, ach=0.6)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"id": "19af4043", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'MediumOffice Whole Building - Level 5'" | |
] | |
}, | |
"execution_count": 27, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"s.spaceType().get().nameString()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"id": "eae13a86", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"OS:SpaceType,\n", | |
" {3202b9d5-020b-4059-99e5-6b80a3c692d4}, !- Handle\n", | |
" MediumOffice Whole Building - Level 5, !- Name\n", | |
" , !- Default Construction Set Name\n", | |
" {419906fd-f6da-4473-907a-c4577d2ad291}, !- Default Schedule Set Name\n", | |
" , !- Group Rendering Name\n", | |
" {c594eb71-8d2b-4d09-9773-7d31c73107a1}, !- Design Specification Outdoor Air Object Name\n", | |
" , !- Standards Template\n", | |
" Office, !- Standards Building Type\n", | |
" WholeBuilding - Md Office; !- Standards Space Type\n", | |
"\n", | |
"\n", | |
"OS:SpaceType,\n", | |
" {13ca7a79-9cf4-4621-aa24-a53079804e7f}, !- Handle\n", | |
" MediumOffice Whole Building, !- Name\n", | |
" , !- Default Construction Set Name\n", | |
" {419906fd-f6da-4473-907a-c4577d2ad291}, !- Default Schedule Set Name\n", | |
" , !- Group Rendering Name\n", | |
" {c594eb71-8d2b-4d09-9773-7d31c73107a1}, !- Design Specification Outdoor Air Object Name\n", | |
" , !- Standards Template\n", | |
" Office, !- Standards Building Type\n", | |
" WholeBuilding - Md Office; !- Standards Space Type\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"[None, None]" | |
] | |
}, | |
"execution_count": 28, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"[print(x) for x in m.getSpaceTypes()]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"id": "62539099", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"OS:SpaceInfiltration:DesignFlowRate,\n", | |
" {dcbf3d92-44cf-4ae4-be49-1149401069fc}, !- Handle\n", | |
" Level 5 Infiltration 0.6 ach, !- Name\n", | |
" {daa2d921-33c2-472c-91b9-c05c9a8a013d}, !- Space or SpaceType Name\n", | |
" , !- Schedule Name\n", | |
" AirChanges/Hour, !- Design Flow Rate Calculation Method\n", | |
" , !- Design Flow Rate {m3/s}\n", | |
" , !- Flow per Space Floor Area {m3/s-m2}\n", | |
" , !- Flow per Exterior Surface Area {m3/s-m2}\n", | |
" 0.6, !- Air Changes per Hour {1/hr}\n", | |
" , !- Constant Term Coefficient\n", | |
" , !- Temperature Term Coefficient\n", | |
" , !- Velocity Term Coefficient\n", | |
" ; !- Velocity Squared Term Coefficient\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"[None]" | |
] | |
}, | |
"execution_count": 29, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"[print(x) for x in s.spaceInfiltrationDesignFlowRates()]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"id": "881c2e94", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[]" | |
] | |
}, | |
"execution_count": 30, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"[print(x) for x in s.spaceType().get().spaceInfiltrationDesignFlowRates()]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"id": "41935439", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Ori is untouched\n", | |
"OS:SpaceInfiltration:DesignFlowRate,\n", | |
" {ae86a43d-074c-444d-a699-2cac6fd4d2de}, !- Handle\n", | |
" MediumOffice Whole Building Infiltration, !- Name\n", | |
" {13ca7a79-9cf4-4621-aa24-a53079804e7f}, !- Space or SpaceType Name\n", | |
" , !- Schedule Name\n", | |
" AirChanges/Hour, !- Design Flow Rate Calculation Method\n", | |
" , !- Design Flow Rate {m3/s}\n", | |
" , !- Flow per Space Floor Area {m3/s-m2}\n", | |
" , !- Flow per Exterior Surface Area {m3/s-m2}\n", | |
" 0.25, !- Air Changes per Hour {1/hr}\n", | |
" , !- Constant Term Coefficient\n", | |
" , !- Temperature Term Coefficient\n", | |
" , !- Velocity Term Coefficient\n", | |
" ; !- Velocity Squared Term Coefficient\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"[None]" | |
] | |
}, | |
"execution_count": 31, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"print(\"Ori is untouched\")\n", | |
"[print(x) for x in sp.spaceInfiltrationDesignFlowRates()]" | |
] | |
} | |
], | |
"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.12.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment