diff --git a/.gitignore b/.gitignore index 97a2b06..6747a97 100644 --- a/.gitignore +++ b/.gitignore @@ -157,3 +157,5 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + +node_modules/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 904a08b..8caf490 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,12 +1,18 @@ { "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter", - "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.organizeImports": "explicit" - } + }, + "editor.defaultFormatter": "ms-python.black-formatter", + "editor.formatOnSave": true }, - "isort.args": ["--profile", "black"], + "isort.args": [ + "--profile", + "black" + ], "jupyter.notebookFileRoot": "${workspaceFolder}", - "python.envFile": "${workspaceFolder}/.env" + "python.envFile": "${workspaceFolder}/.env", + "terminal.integrated.env.windows": { + "PYTHONPATH": "${workspaceFolder}" + } } diff --git a/README.md b/README.md index 0acd1e0..0a6002c 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,11 @@ Materials for MIT Campus Decarbonization Study ![Technology Overview](./figures/technology-overview.drawio.png) + +## Setup + +1. Install npm, conda (maybe docker) +2. npm i +3. npm run conda-setup +4. npx supabase init (?? maybe) && npx supabase login && npx supabase link +5. npm run db-refresh diff --git a/data/5out.hdf b/data/5out.hdf new file mode 100644 index 0000000..3db47fb Binary files /dev/null and b/data/5out.hdf differ diff --git a/data/mit_buildings_info.csv b/data/mit_buildings_info.csv new file mode 100644 index 0000000..a3bf21d --- /dev/null +++ b/data/mit_buildings_info.csv @@ -0,0 +1,133 @@ +,BUILDING_NUMBER,BUILDING_NAME_LONG,BUILDING_GROUP_LEVEL1,CLUSTER_NUM,BUILDING_TYPE,BUILDING_USE,SITE,CAMPUS_SECTOR,YEAR_CONST_BEGAN,YEAR_OCCUPIED,LATITUDE_WGS,LONGITUDE_WGS,OWNERSHIP_TYPE,BUILDING_HEIGHT,NUM_OF_ROOMS,EXT_GROSS_AREA,ASSIGNABLE_AREA,NON_ASSIGNABLE_AREA,BLDG_SRV,CIRCULAT,CLASSRMS,GENERAL,HEALTH,LABS,MECHANIC,OFFICES,RESIDENT,SPECIAL,STUDY,SUPPORT,UNCLASS,USEABLE_AREA,STRUCT_AREA,LEVEL3_CATEGORY,LEVEL2_CATEGORY,PI_CONNECTION,METER_STATUS,TotalUsable,SumZoneTypes +0,1,Henry L Pierce Engineering Laboratory,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1913.0,1917.0,42.3580859,-71.09235723,OWNED,81.4,403.0,116038.74,75943.9,29171.29,2154.71,19795.43,13107.48,147.58,0.0,28105.06,7221.15,34476.15,0.0,0.0,0.0,107.63,0.0,105115.19,10923.55,Chilled Water,Produced,Y,Chilled Water Only,105115.19,105115.19 +1,10,Richard Cockburn MacLaurin Buildings (10),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1913.0,1916.0,42.35967738,-71.09201647,OWNED,149.2,567.0,144463.46,85571.66,42925.24,1476.08,25779.02,5249.28,2419.93,0.0,8922.65,15670.14,46632.49,0.0,0.0,21986.92,360.39,0.0,128496.9,15966.56,Chilled Water,Produced,Y,Chilled Water Only,128496.9,128496.9 +2,11,Homberg Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1927.0,1928.0,42.35952201,-71.09277267,OWNED,72.5,189.0,26777.38,19086.24,4860.08,14.0,3277.76,0.0,214.59,0.0,0.0,1568.32,16056.74,0.0,0.0,0.0,2814.91,0.0,23946.32,2831.06,Chilled Water,Produced,N,No Individual Metering,23946.32,23946.32 +3,12,Lisa T. Su Building,Non-CUP,Office & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,,,,,OWNED,0.0,376.0,237776.9,94638.32,116713.3,2078.16,46431.53,0.0,0.0,0.0,82613.41,68203.61,10676.35,0.0,0.0,0.0,1348.56,0.0,211351.62,26425.28,Chilled Water,Produced,,,211351.62,211351.62 +4,13,Vannevar Bush Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1963.0,1965.0,42.35994386,-71.09255152,OWNED,69.1,578.0,183539.92,95795.57,72485.61,2522.57,42250.99,2578.22,0.0,0.0,60757.54,27712.05,31324.56,0.0,0.0,0.0,741.04,394.21,168281.18,15258.74,Chilled Water,Produced,Y,Fully Metered,168810.17,168810.17 +5,14,Charles Hayden Memorial Library,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1948.0,1951.0,42.35918261,-71.089304,OWNED,70.4,92.0,142706.51,89203.75,48792.34,3336.98,30325.77,4197.1,1078.3,0.0,5865.97,15129.59,32809.91,0.0,353.65,42976.29,1922.53,0.0,137996.09,4710.42,Chilled Water,Produced,Y,Chilled Water & Electric,137996.09,137996.09 +6,16,Dorrance Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1950.0,1952.0,42.36043478,-71.09059277,OWNED,122.9,374.0,116006.44,57891.59,46843.43,2877.56,28142.23,9231.58,315.74,0.0,26841.44,15823.64,21165.45,0.0,0.0,0.0,337.38,0.0,104735.02,11271.42,Chilled Water,Produced,Y,Steam Only,104822.52,104822.52 +7,17,Wright Brothers Wind Tunnel,Non-CUP,Lab Dominant,ACADEMIC,AER,MIT,MAIN GROUP,1937.0,1939.0,42.360113,-71.09349326,OWNED,22.0,14.0,6074.7,4861.22,263.41,29.75,232.4,0.0,0.0,0.0,4861.22,1.26,0.0,0.0,0.0,0.0,0.0,0.0,5124.63,950.07,Electricity,Produced,Y,No Individual Metering,10750.53,10750.53 +8,18,Camille Edouard Dreyfus Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1967.0,1969.0,42.36006975,-71.08982131,OWNED,82.5,529.0,133732.1,75653.17,41215.37,1290.79,21045.71,0.0,0.0,0.0,64331.73,18878.87,11321.44,0.0,0.0,0.0,0.0,0.0,116868.54,16863.56,Chilled Water,Produced,Y,Fully Metered,116875.37,116875.37 +9,2,THE SIMONS BUILDING,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1913.0,1916.0,42.35881273,-71.09018269,OWNED,82.6,384.0,133168.22,73699.9,43053.58,2369.95,26166.93,9760.72,0.0,0.0,22451.38,14516.7,41173.38,0.0,0.0,0.0,314.42,0.0,116753.48,16414.74,Chilled Water,Produced,Y,Chilled Water & Electric,116753.48,116753.48 +10,24,Building 24,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1941.0,1941.0,42.3606665,-71.09201464,OWNED,84.1,316.0,78022.39,48984.22,22154.34,1363.82,16328.18,6835.5,1011.35,0.0,8946.74,4462.34,29619.57,0.0,0.0,0.0,2571.06,0.0,71138.56,6883.83,Chilled Water,Produced,Y,Fully Metered,71138.56,71138.56 +11,26,Karl Taylor Compton Laboratories,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1955.0,1957.0,42.36085795,-71.09115294,OWNED,78.7,387.0,133479.58,80363.1,42700.18,2919.16,24971.12,17120.44,0.0,0.0,27643.78,14809.9,35219.3,0.0,0.0,0.0,379.58,0.0,123063.28,10416.3,Chilled Water,Produced,Y,Fully Metered,122979,122979 +12,3,Richard Cockburn MacLaurin Buildings (3),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1913.0,1916.0,42.35900694,-71.09239741,OWNED,85.5,544.0,160694.2,104693.45,40630.76,2517.73,28624.15,5999.82,0.0,0.0,47613.55,9488.88,49092.05,0.0,0.0,682.9,1305.13,0.0,145324.21,15369.99,Chilled Water,Produced,Y,Chilled Water Only,145324.21,145324.21 +13,31,Sloan Laboratories For Aircraft & Automotive Engineering,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1928.0,1928.0,42.36037362,-71.09306201,OWNED,46.2,334.0,76205.74,52864.96,15926.53,1099.15,5288.7,1958.52,181.44,0.0,31746.86,9538.68,18502.69,0.0,0.0,0.0,211.87,263.58,68791.49,7414.25,Chilled Water,Produced,Y,Fully Metered,69513.85,69513.85 +14,32,Ray and Maria Stata Center,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,2004.0,2004.0,42.36159672,-71.09056854,OWNED,140.0,1316.0,463889.51,286099.28,121910.35,7446.09,73834.0,20289.12,35710.12,0.0,35095.63,40630.26,155127.18,0.0,0.0,3720.96,36156.27,0.0,408009.63,55879.8799999999,Chilled Water,Produced,Y,Fully Metered,408009.63,408009.63 +15,32P,Ray and Maria Stata Center Garage,Non-CUP,Lab Dominant,SERVICE,GAR,MIT,MAIN GROUP,2003.0,2003.0,,,OWNED,0.0,33.0,239353.28,219250.33,10269.82,0.0,2432.82,0.0,0.0,0.0,0.0,7837.0,924.19,0.0,0.0,0.0,218326.14,0.0,229520.15,9833.12999999998,Electricity,Produced,N,No Individual Metering,229520.15,229520.15 +16,33,Daniel Guggenheim Aeronautical Laboratory,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1927.0,1928.0,42.36017838,-71.09374587,OWNED,56.5,155.0,47128.95,32180.64,11482.2,692.91,8859.81,2845.47,620.0,0.0,9227.7,1929.48,19487.47,0.0,0.0,0.0,0.0,0.0,43662.84,3466.11,Chilled Water,Produced,Y,Chilled Water Only,43662.84,43662.84 +17,34,EG&G Education Center,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1982.0,1983.0,42.36113825,-71.09195128,OWNED,81.3,62.0,25951.44,14472.14,10198.28,45.5,6745.54,6854.96,0.0,0.0,3972.19,3407.24,3644.99,0.0,0.0,0.0,0.0,0.0,24670.42,1281.02,Chilled Water,Produced,Y,Chilled Water Only,24670.42,24670.42 +18,35,Sloan Laboratory,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1950.0,1952.0,42.36038118,-71.09402814,OWNED,80.3,238.0,68012.32,41629.94,18920.47,1686.19,13112.98,2889.95,0.0,0.0,17723.55,4121.3,21016.44,0.0,0.0,0.0,0.0,0.0,60550.41,7461.91,Chilled Water,Produced,Y,Chilled Water & Steam,60550.41,60550.41 +19,36,Fairchild Buildings (36),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1971.0,1973.0,42.36143722,-71.09166758,OWNED,117.4,604.0,144920.44,72220.21,56625.06,5039.96,29362.67,4459.09,781.9,0.0,29862.45,22222.43,36982.89,0.0,0.0,0.0,133.88,0.0,128845.27,16075.17,Chilled Water,Produced,Y,Chilled Water & Steam,128845.27,128845.27 +20,37,Ronald E McNair Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1966.0,1969.0,42.36068424,-71.09324745,OWNED,89.7,411.0,102777.46,55558.61,32301.67,1741.83,15466.92,2691.41,0.0,0.0,21366.61,15092.92,31168.9,0.0,0.0,167.0,164.69,0.0,87860.28,14917.18,Chilled Water,Produced,Y,Chilled Water & Steam,87860.28,87860.28 +21,38,Fairchild Buildings (38),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1971.0,1973.0,42.36107393,-71.0923498,OWNED,91.4,321.0,84000.79,56499.53,19288.99,57.45,7228.62,558.61,0.0,0.0,38823.35,12002.92,16513.28,0.0,0.0,0.0,604.29,0.0,75788.52,8212.26999999999,Chilled Water,Produced,Y,Chilled Water & Steam,75788.52,75788.52 +22,39,Stanley Gordon Brown Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1966.0,1968.0,42.36085666,-71.09273098,OWNED,91.1,249.0,76639.87,39376.56,30723.19,674.07,13039.41,0.0,0.0,0.0,30639.96,17009.71,8736.6,0.0,0.0,0.0,0.0,0.0,70099.75,6540.12,Chilled Water,Produced,Y,Fully Metered,70099.75,70099.75 +23,4,Richard Cockburn MacLaurin Buildings (4),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1913.0,1916.0,42.35944306,-71.09108651,OWNED,79.7,495.0,162821.54,97550.05,47334.68,4010.57,30380.58,19215.12,203.83,0.0,32303.32,12943.53,42209.19,0.0,0.0,386.05,639.03,2593.51,144884.73,17936.81,Chilled Water,Produced,Y,Chilled Water Only,144930.25,144930.25 +24,41,Building 41,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1915.0,1917.0,42.36076007,-71.0941603,OWNED,61.2,107.0,26148.19,20055.87,4407.76,761.53,2948.28,0.0,0.0,0.0,13104.32,697.95,6812.88,0.0,0.0,0.0,138.67,0.0,24463.63,1684.56,Chilled Water,Produced,N,No Individual Metering,24463.63,24463.63 +25,42_43_N16_E40,Utility Production Buildings,CUP,Mechanical,,,MIT,,,,,,OWNED,,159.0,126283.75,13420.16,101941.31,104.49,6748.29,0.0,554.75,0.0,261.86,100034.04,4674.160000000001,0.0,0.0,0.0,7929.389999999999,42.0,120348.98,5934.77,Chilled Water,Produced,Only E40,No Individual Metering,119811.84,119853.84 +26,44,44,Non-CUP,Support Areas & Parking,ACADEMIC,AER,MIT,MAIN GROUP,1938.0,1939.0,42.36160679,-71.09247074,OWNED,29.5,51.0,16118.61,11649.47,2715.53,325.66,1010.49,0.0,0.0,0.0,7095.65,1379.38,4553.82,0.0,0.0,0.0,0.0,0.0,14365.0,1753.61,Electricity,Produced,N,No Individual Metering,, +27,46,Brain & Cognitive Sciences Complex,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,2003.0,2005.0,42.36232777,-71.09164294,OWNED,136.4,1419.0,418299.52,220004.09,151401.78,7057.88,83107.28,2214.84,757.11,0.0,125104.03,61236.62,70017.65,322.23,14991.43,0.0,6061.11,535.69,371405.87,46893.65,Chilled Water,Produced,Y,Fully Metered,373192.06,373192.06 +28,48,Ralph M Parsons Laboratory For Water Resources & Hydrodynamics,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1949.0,1951.0,42.36243249,-71.09066524,OWNED,64.0,156.0,57255.46,38949.64,11466.55,887.29,7675.46,2195.3,0.0,0.0,22902.59,2903.8,13054.04,0.0,0.0,0.0,797.71,0.0,50416.19,6839.27,Chilled Water,Produced,Y,Steam Only,50416.19,50416.19 +29,5,Pratt School Of Naval Architecture And Marine Engineering,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1919.0,1920.0,42.35870876,-71.09292347,OWNED,70.7,276.0,80942.35,55084.19,16638.18,1118.12,12045.79,4264.01,1811.86,0.0,15280.25,3474.27,33728.07,0.0,0.0,0.0,0.0,0.0,71722.37,9219.98,Chilled Water,Produced,Y,Chilled Water Only,71722.37,71722.37 +30,50,Walker Memorial,Non-CUP,Lab & Mixed Use,SERVICE,STAC,MIT,MAIN GROUP,1916.0,1917.0,42.35936241,-71.0883196,OWNED,80.5,201.0,74063.57,46679.01,20815.11,1770.71,13777.62,0.0,27484.93,0.0,0.0,5266.78,11284.11,0.0,2941.06,0.0,4968.91,0.0,67494.12,6569.45,Electricity,Produced,Y,Chilled Water & Electric,67494.12,67494.12 +31,51,Walter C Wood Sailing Pavilion,Non-CUP,Mechanical,SERVICE,STAC,MIT,MAIN GROUP,1936.0,1937.0,42.35851706,-71.08773035,OWNED,21.3,24.0,5889.33,4450.4,909.69,32.08,532.86,0.0,0.0,0.0,0.0,344.75,214.12,0.0,4236.28,0.0,0.0,0.0,5360.09,529.24,Electricity,Produced,N,No Individual Metering,5360.09,5360.09 +32,54,Cecil And Ida Green Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1962.0,1964.0,42.36032385,-71.08932613,OWNED,275.0,654.0,129448.04,68640.0,44148.72,1627.56,28140.77,7409.62,0.0,0.0,19195.05,14380.39,42014.91,0.0,0.0,0.0,20.42,0.0,112788.72,16659.32,Chilled Water,Produced,Y,Fully Metered,113326.22,113326.22 +33,56,Uncas A Whitaker Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1963.0,1965.0,42.36069953,-71.0898625,OWNED,118.8,471.0,143940.24,78380.88,50573.95,641.74,23326.22,6874.0,395.71,0.0,46858.59,26605.99,19891.37,0.0,1345.39,0.0,3015.82,0.0,128954.83,14985.41,Chilled Water,Produced,Y,Steam Only,128944.58,128944.58 +34,57,MIT Alumni Pool,Non-CUP,Mechanical,SERVICE,STAC,MIT,MAIN GROUP,1939.0,1940.0,42.36114229,-71.09014001,OWNED,41.1,52.0,39121.04,22725.98,10516.52,204.55,2774.07,0.0,116.99,0.0,0.0,7537.9,149.66,0.0,22459.33,0.0,0.0,0.0,33242.5,5878.54,Electricity,Produced,N,No Individual Metering,33242.5,33242.5 +35,62_64,Alumni House,Non-CUP,Residential,,,MIT,,,,,,OWNED,,675.0,150586.63,98620.43,36524.08,7905.610000000001,23192.34,0.0,12185.62,0.0,0.0,5426.13,644.3499999999999,84792.19,0.0,0.0,998.27,0.0,135144.51,15442.12000000001,Electricity,Produced,Y,Steam & Electric,135144.51,135144.51 +36,66,Ralph Landau Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1973.0,1976.0,42.36092016,-71.08902925,OWNED,74.3,322.0,133709.64,71189.31,46958.45,2560.65,26710.23,5398.95,1217.61,0.0,39387.27,17687.57,24506.34,0.0,0.0,0.0,679.14,0.0,118147.76,15561.88,Chilled Water,Produced,Y,Fully Metered,118192.74,118192.74 +37,68,David H. Koch Biology Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1991.0,1994.0,42.36162167,-71.08863856,OWNED,104.8,960.0,260390.37,155141.39,81485.49,3395.48,52340.18,750.76,1834.5,0.0,120204.95,25749.83,21144.66,0.0,10820.38,0.0,386.14,0.0,236626.88,23763.49,Chilled Water,Produced,Y,Fully Metered,236623.33,236623.33 +38,6C,PDSI,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,2007.0,2007.0,42.35967294,-71.09083617,OWNED,92.0,123.0,51288.87,16131.89,27823.8,628.83,17644.77,0.0,0.0,0.0,8373.34,9550.2,7472.32,0.0,0.0,0.0,286.23,0.0,43955.69,7333.18,Chilled Water,Produced,Y,Chilled Water & Steam,45442.29,45442.29 +39,6_6B,George Eastman Research,Non-CUP,Lab & Mixed Use,,,MIT,,,,,,OWNED,,316.0,91926.37,54532.3,24921.54,244.59,17651.48,1605.16,0.0,0.0,20964.51,7025.47,31129.7,0.0,0.0,0.0,832.93,0.0,79453.84,12472.53,Chilled Water,Produced,Only 6,Chilled Water Only,#VALUE!,#VALUE! +40,76,David H. Koch Institute For Integrative Cancer Research,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,2005.0,2010.0,42.36229582,-71.08927563,OWNED,0.0,932.0,367688.6,205329.56,124326.6,5146.07,62525.49,0.0,7133.71,0.0,142978.59,56655.04,35059.14,0.0,11406.13,0.0,8751.99,0.0,329656.16,38032.44,Chilled Water,Produced,Y,Fully Metered,329669.09,329669.09 +41,7_7A,William Barton Rogers Buildings,Non-CUP,Lab & Mixed Use,,,MIT,,,,,,OWNED,,401.0,119055.36,65380.47,39133.380000000005,796.45,25877.16,950.01,2977.13,0.0,14039.92,12459.77,29113.03,0.0,0.0,16691.43,1608.95,0.0,104513.85,14541.51,Chilled Water,Produced,Only 7,Chilled Water Only,104359.99,104359.99 +42,8,Building 8,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1913.0,1916.0,42.35999279,-71.09086392,OWNED,64.0,253.0,66165.06,36941.33,21070.43,1386.26,13873.54,1146.17,16.5,0.0,14741.25,5810.63,20519.83,0.0,0.0,0.0,517.58,0.0,58011.76,8153.3,Chilled Water,Produced,Y,Chilled Water Only,58011.76,58011.76 +43,9,Samuel Tak Lee Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,MAIN GROUP,1966.0,1967.0,42.35974993,-71.09356175,OWNED,83.9,277.0,77414.0,38796.37,28428.83,1757.25,18453.34,8162.06,2174.68,0.0,2778.65,8218.24,24491.32,0.0,906.54,0.0,283.12,0.0,67225.2,10188.8,Chilled Water,Produced,Y,Fully Metered,67225.2,67225.2 +44,Briggs Field Operating,Briggs Field Operating,Non-CUP,Support Areas & Parking,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Electricity,Produced,,,#VALUE!,#VALUE! +45,E1,Gray House (Formerly President's House),Non-CUP,Lab & Mixed Use,RESIDENT,AER,MIT,EAST,1913.0,1917.0,42.3596025,-71.08696429,OWNED,52.0,139.0,18642.53,11190.61,4967.95,275.94,3395.22,0.0,4810.28,0.0,0.0,1296.79,1632.65,3099.31,0.0,264.12,1384.25,0.0,16158.56,2483.97,Chilled Water,Produced,N,Chilled Water & Electric,16158.56,16158.56 +46,E14,Building E14,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,,,42.36046359,-71.08733249,OWNED,0.0,360.0,173875.21,77946.22,80319.92,3062.62,32041.13,1574.07,1535.18,0.0,50568.44,45216.17,23084.26,0.0,0.0,0.0,1184.27,0.0,158266.14,15609.07,Chilled Water,Produced,Y,Fully Metered,158266.14,158266.14 +47,E15,Wiesner Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1982.0,1984.0,42.36083844,-71.08763489,OWNED,68.5,463.0,120331.42,79233.13,32098.06,2030.13,17313.64,5310.45,6833.04,0.0,34458.14,12754.29,32257.97,0.0,0.0,175.61,197.92,0.0,111331.19,9000.23,Chilled Water,Produced,Y,Fully Metered,111331.19,111331.19 +48,E17,Seely G Mudd Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1932.0,1975.0,42.36148439,-71.08788625,OWNED,82.8,326.0,80477.33,51159.04,21083.46,2179.81,7995.01,1475.04,0.0,0.0,8476.33,10908.64,38427.16,0.0,2530.82,0.0,249.69,0.0,72242.5,8234.82999999999,Chilled Water,Produced,Y,No Individual Metering,72242.5,72242.5 +49,E18,Horace Sayford Ford Building (E18),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1920.0,1964.0,42.361767,-71.08779281,OWNED,88.3,408.0,115069.29,70945.79,34660.11,1209.09,15274.65,0.0,568.96,0.0,18591.89,18176.37,37053.07,0.0,2721.39,0.0,12010.48,0.0,105605.9,9463.39,Chilled Water,Produced,Y,No Individual Metering,111617.28,111617.28 +50,E19,Horace Sayford Ford Building (E19),Non-CUP,Lab & Mixed Use,SERVICE,AER,MIT,EAST,1920.0,1964.0,42.36212904,-71.08795245,OWNED,81.0,735.0,150661.42,100290.65,39382.78,3163.58,22228.92,585.21,1290.76,0.0,11579.41,13990.28,78753.1,0.0,0.0,0.0,7992.61,89.56,139673.43,10987.99,Chilled Water,Produced,Y,Steam & Electric,139673.43,139673.43 +51,E2,70 AMHERST,Non-CUP,Special,RESIDENT,DHOA,MIT,EAST,1913.0,1916.0,42.35995565,-71.08686701,OWNED,63.7,312.0,64847.33,35759.29,18752.08,2693.94,12254.9,0.0,3625.92,0.0,289.69,3803.24,450.48,30862.04,0.0,144.0,387.16,0.0,54511.37,10335.96,Chilled Water,Produced,Y,Chilled Water & Electric,54511.37,54511.37 +52,E23,Health Services,Non-CUP,Lab & Mixed Use,SERVICE,AER,MIT,EAST,1979.0,1982.0,42.36102212,-71.08663216,OWNED,71.1,574.0,103338.41,63196.25,27193.31,1248.32,17218.92,0.0,2412.2,29200.81,81.54,8726.07,30987.86,0.0,0.0,0.0,513.84,0.0,90389.56,12948.85,Chilled Water,Produced,Y,No Individual Metering,90389.56,90389.56 +53,E25,Whitaker College Of Health Sciences & Technology,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1979.0,1982.0,42.36166876,-71.08694971,OWNED,92.3,565.0,156676.36,90476.81,47723.7,2137.71,30255.58,4562.75,0.0,0.0,46981.23,15330.41,33798.89,0.0,3626.77,0.0,1125.1,382.07,138200.51,18475.85,Chilled Water,Produced,Y,No Individual Metering,139358.64,139358.64 +54,E38,BUILDING E38,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1920.0,1968.0,,,OWNED,0.0,341.0,124448.22,46734.26,45653.55,3523.02,26354.9,3872.26,1858.28,0.0,1208.58,15775.63,38319.12,0.0,0.0,0.0,1476.02,0.0,92387.81,32060.41,Chilled Water,Produced,Y,Chilled Water & Steam,92387.81,92387.81 +55,E40,The Muckley Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1930.0,1969.0,42.36116319,-71.08485302,OWNED,64.5,517.0,106747.05,69809.38,26466.46,2508.54,10582.49,2255.57,73.42,0.0,1776.86,13375.43,63175.37,0.0,0.0,0.0,2528.16,0.0,96275.84,10471.21,Chilled Water,Produced,Y,Fully Metered,96275.84,96275.84 +56,E51,Jack C Tang Center For Management Education,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1944.0,1980.0,42.36055421,-71.08449242,OWNED,60.0,302.0,107990.76,52916.5,42550.6,3009.96,21865.36,27898.25,2415.5,0.0,0.0,17675.28,21258.03,0.0,0.0,0.0,1344.72,0.0,95467.1,12523.66,Chilled Water,Produced,Y,Fully Metered,95467.1,95467.1 +57,E52,MORRIS & SOPHIE CHANG BUILDING,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1938.0,1952.0,42.36073592,-71.08367668,OWNED,97.4,576.0,161974.43,95849.81,47622.65,4109.67,30520.29,2228.46,10326.83,0.0,0.0,12992.69,83123.0,0.0,0.0,0.0,171.52,0.0,143472.46,18501.97,Chilled Water,Produced,Y,Fully Metered,143472.46,143472.46 +58,E53,Grover M Hermann Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1964.0,1965.0,42.36118818,-71.08359227,OWNED,72.2,290.0,84984.92,53347.04,25085.55,2025.07,13592.74,574.88,0.0,0.0,0.0,9467.74,28587.28,0.0,0.0,24010.08,174.8,0.0,78432.59,6552.32999999999,Chilled Water,Produced,Y,Chilled Water & Steam,78432.59,78432.59 +59,E55,E55,Non-CUP,Support Areas & Parking,RESIDENT,DHOA,MIT,EAST,1965.0,1967.0,42.36173608,-71.08390876,OWNED,272.8,466.0,172309.33,120517.81,28758.1,345.93,22095.17,0.0,3206.29,0.0,0.0,6317.0,480.37,116679.8,0.0,0.0,151.35,0.0,149275.91,23033.42,Electricity,Produced,Y,Steam Only,, +60,E60,Arthur D Little Building,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,1917.0,1994.0,42.36117731,-71.08217568,OWNED,,141.0,30130.11,12961.15,12858.51,1280.76,8111.08,0.0,0.0,0.0,0.0,3466.67,12875.72,0.0,0.0,0.0,85.43,0.0,25819.66,4310.45,Chilled Water,Produced,Y,Fully Metered,25819.66,25819.66 +61,E62,Building E62,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,EAST,,,42.36134747,-71.08265495,OWNED,0.0,604.0,213581.39,113768.08,76842.54,4095.74,57146.61,23672.82,15877.94,0.0,0.0,15600.19,74121.76,0.0,0.0,0.0,95.56,0.0,190610.62,22970.77077,Chilled Water,Produced,Y,Fully Metered,190610.62,190610.62 +62,E62P,E62 Garage,Non-CUP,Lab Dominant,SERVICE,GAR,MIT,EAST,,,42.36134747,-71.08265495,OWNED,,41.0,53611.11,38285.6,11295.24,481.0,3973.17,0.0,0.0,0.0,0.0,6841.07,182.53,0.0,0.0,0.0,38103.07,0.0,49580.84,4030.269226,Electricity,Produced,,,49580.84,49580.84 +63,E94,BUILDING E94,Leased Buildings,Office,ACADEMIC,AER,MIT,EAST,,,,,LEASED,0.0,104.0,15506.61,14101.34,205.19,0.0,0.0,0.0,0.0,0.0,0.0,205.19,14101.34,0.0,0.0,0.0,0.0,0.0,14306.53,1200.08,Electricity,Purchased,,,14306.53,14306.53 +64,KS,KS,FSILGs,Support Areas & Parking,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Electricity,Purchased,,,#VALUE!,#VALUE! +65,Main Campus Area,Main Campus Area,Non-CUP,Support Areas & Parking,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Electricity,Purchased,,,, +66,N10,High Voltage Research Laboratory,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTH,1964.0,1965.0,42.3608633,-71.09545096,OWNED,33.0,53.0,10084.86,8101.7,637.89,134.82,131.54,0.0,0.0,0.0,6962.46,371.53,1139.24,0.0,0.0,0.0,0.0,0.0,8739.59,1345.27,Electricity,Produced,N,No Individual Metering,8739.59,8739.59 +67,N4,Albany Street Parking Garage,Non-CUP,Lab Dominant,SERVICE,GAR,MIT,NORTH,,1966.0,42.36203429,-71.09278036,OWNED,56.3,36.0,143032.14,129868.34,5780.48,2162.59,2848.78,0.0,0.0,0.0,0.0,769.11,0.0,0.0,0.0,0.0,129868.34,0.0,135648.82,7383.32,Electricity,Produced,N,No Individual Metering,135648.82,135648.82 +68,N51,Building N51,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTH,1924.0,1964.0,42.36228442,-71.09762771,OWNED,50.9,126.0,44980.93,32692.59,8432.78,1210.99,5570.18,2301.57,11317.51,0.0,4806.77,1651.61,13926.33,0.0,0.0,0.0,340.41,0.0,41125.37,3855.56,Electricity,Purchased,N,No Individual Metering,41125.37,41125.37 +69,N52,Building N52,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTH,1924.0,1964.0,42.36227273,-71.09718823,OWNED,56.8,320.0,103874.44,71730.92,21208.21,923.84,14050.5,2674.29,24879.47,0.0,14390.09,6233.87,28206.81,0.0,0.0,0.0,1580.26,0.0,92939.13,10935.31,Electricity,Purchased,N,No Individual Metering,92939.13,92939.13 +70,N57,Building N57,Non-CUP,Lab & Mixed Use,SERVICE,AER,MIT,NORTH,1922.0,1964.0,42.3630114,-71.09882964,OWNED,78.2,54.0,46882.29,41521.21,3021.22,0.0,2436.87,0.0,0.0,0.0,0.0,584.35,1752.79,0.0,0.0,37423.88,2344.54,0.0,44542.43,2339.86,Electricity,Purchased,N,No Individual Metering,44542.43,44542.43 +71,N9,Superconducting Generator Test Facility,Non-CUP,Lab Dominant,ACADEMIC,AER,MIT,NORTH,,1978.0,42.36095321,-71.09519377,OWNED,32.7,16.0,5882.04,5345.17,160.86,0.0,0.0,0.0,0.0,0.0,5280.64,160.86,64.53,0.0,0.0,0.0,0.0,0.0,5506.03,376.009999999999,Electricity,Produced,N,No Individual Metering,5506.03,5506.03 +72,NE45,300 Technology Square,Leased Buildings,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHEAST,,,,,LEASED,0.0,25.0,8049.06,4444.31,137.96,0.0,0.0,0.0,0.0,0.0,3444.84,137.96,999.47,0.0,0.0,0.0,0.0,0.0,4582.27,3466.79,Electricity,Purchased,,,4582.27,4582.27 +73,NE46,400 Technology Square,Leased Buildings,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHEAST,,,,,LEASED,0.0,42.0,9215.4,8138.76,239.41,0.0,0.0,0.0,0.0,0.0,3127.6,239.41,5011.16,0.0,0.0,0.0,0.0,0.0,8378.17,837.23,Electricity,Purchased,,,#VALUE!,#VALUE! +74,NE47,500 Technology Square,Leased Buildings,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHEAST,,,42.36346458,-71.09258101,LEASED,148.0,267.0,73631.09,63249.26,2218.01,0.0,0.0,0.0,0.0,0.0,35055.93,2218.01,28193.33,0.0,0.0,0.0,0.0,0.0,65467.27,8163.81999999999,Electricity,Purchased,,,65467.27,65467.27 +75,NE48,700 Technology Square,Leased Buildings,Office,ACADEMIC,AER,MIT,NORTHEAST,,,42.3640312,-71.09272747,LEASED,84.4,141.0,18156.59,15217.35,797.4,0.0,750.73,0.0,395.91,0.0,205.03,46.67,14112.74,0.0,0.0,402.46,101.21,0.0,16014.75,2141.84,Electricity,Purchased,,,15994.23,15994.23 +76,NE49,600 Technology Square,Leased Buildings,Office,SERVICE,AER,MIT,NORTHEAST,,,42.36339002,-71.09311895,LEASED,84.9,651.0,93671.28,87560.08,647.75,0.0,0.0,0.0,119.79,0.0,0.0,647.75,87440.29,0.0,0.0,0.0,0.0,0.0,88207.83,5463.45000000001,Electricity,Purchased,,,91951.31,91951.31 +77,NW10,Edgerton House,Non-CUP,Residential,RESIDENT,DHOA,MIT,NORTHWEST,1922.0,,42.36032016,-71.09813729,OWNED,56.5,261.0,132529.78,82590.37,31474.13,864.17,24541.91,0.0,3937.21,0.0,0.0,6068.05,512.77,77693.07,0.0,0.0,447.32,0.0,114064.5,18465.28,Electricity,Purchased,N,No Individual Metering,114064.5,114064.5 +78,NW12_NW12A,Nuclear Reactor Laboratory,Non-CUP,Lab & Mixed Use,,,MIT,,,,,,OWNED,,168.0,50695.060000000005,35326.59,9761.49,827.45,6695.7,1155.63,0.0,0.0,21732.45,2238.34,10360.98,0.0,0.0,0.0,2077.53,0.0,45088.08,5606.98,Chilled Water,Produced,N,No Individual Metering,45087.77,45087.77 +79,NW13,Building NW13,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHWEST,,1963.0,42.3598849,-71.09736187,OWNED,28.3,144.0,61937.11,46938.1,9916.4,622.1,7283.31,0.0,0.0,0.0,40738.43,2010.99,3522.25,0.0,0.0,0.0,2677.42,0.0,56854.5,5082.61,Chilled Water,Produced,N,No Individual Metering,56854.5,56854.5 +80,NW14,Francis Bitter Magnet Laboratory (NW14),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHWEST,1913.0,1962.0,42.35963208,-71.09789884,OWNED,75.7,402.0,144673.42,101485.34,34011.23,2493.97,20447.62,1541.11,0.0,0.0,77479.91,11069.64,20389.43,0.0,0.0,0.0,2074.89,0.0,135496.57,9176.85000000001,Chilled Water,Produced,Y,No Individual Metering,135469.26,135469.26 +81,NW15,Francis Bitter Magnet Laboratory (NW15),Non-CUP,Lab Dominant,ACADEMIC,AER,MIT,NORTHWEST,1961.0,1962.0,42.35934903,-71.0982566,OWNED,34.2,12.0,16137.29,14355.21,695.29,0.0,0.0,0.0,0.0,0.0,14355.21,695.29,0.0,0.0,0.0,0.0,0.0,0.0,15050.5,1086.79,Chilled Water,Produced,N,No Individual Metering,15083.87,15083.87 +82,NW16,Plasma Science And Fusion Center (NW16),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHWEST,1980.0,1981.0,42.3600321,-71.09871532,OWNED,34.0,171.0,50148.39,31109.74,14770.8,900.49,11410.3,0.0,0.0,0.0,12421.45,2460.01,17803.84,0.0,0.0,0.0,245.19,639.26,45880.54,4267.85,Electricity,Purchased,N,No Individual Metering,45880.54,45880.54 +83,NW17,Plasma Science And Fusion Center (NW17),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHWEST,,,42.35985638,-71.09914244,OWNED,33.8,152.0,45542.35,28512.58,12693.63,916.0,9025.91,0.0,0.0,0.0,13451.36,2751.72,14913.37,0.0,0.0,0.0,147.85,0.0,41206.21,4336.14,Electricity,Purchased,N,No Individual Metering,41206.21,41206.21 +84,NW21,Plasma Science And Fusion Center (NW21),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHWEST,1899.0,1980.0,42.3590636,-71.09914629,OWNED,43.6,145.0,124096.66,64826.08,44998.01,788.6,7145.28,0.0,0.0,0.0,57197.75,37064.13,7050.86,0.0,0.0,0.0,577.47,0.0,109824.09,14272.57,Chilled Water,Produced,Y,Chilled Water Only,109824.09,109824.09 +85,NW22,Plasma Science And Fusion Center (NW22),Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,NORTHWEST,,1992.0,42.35963862,-71.09972313,OWNED,33.7,158.0,49002.27,39630.57,5649.71,642.22,2983.95,0.0,0.0,0.0,20612.01,2023.54,18609.94,0.0,0.0,0.0,408.62,0.0,45280.28,3721.99,Electricity,Purchased,N,No Individual Metering,45280.28,45280.28 +86,NW23,BUILDING NW23,Non-CUP,Office,SERVICE,(NULL),MIT,NORTHWEST,1925.0,2016.0,,,OWNED,0.0,312.0,51156.85,39138.86,7114.11,1362.42,2332.49,0.0,125.16,0.0,0.0,3419.2,39013.7,0.0,0.0,0.0,0.0,0.0,46252.97,4903.88,Electricity,Purchased,N,Fully Metered,46252.97,46252.97 +87,NW30,BUILDING NW30,Non-CUP,Residential,RESIDENT,DHOA,MIT,NORTHWEST,1904.0,1958.0,42.35864725,-71.09997287,OWNED,75.0,253.0,85812.19,50037.19,23321.62,588.17,17124.49,0.0,3854.54,0.0,0.0,5608.96,744.69,43169.45,0.0,383.86,1884.65,0.0,73358.81,12453.38,Chilled Water,Produced,Y,Chilled Water & Steam,73358.81,73358.81 +88,NW32,BUILDING NW32,Non-CUP,Lab & Mixed Use,ACADEMIC,(NULL),MIT,NORTHWEST,1918.0,,,,OWNED,0.0,97.0,30052.65,18918.81,6731.79,1328.91,4855.09,0.0,0.0,0.0,0.0,547.79,0.0,0.0,0.0,0.0,0.0,18918.81,25650.6,4402.05,Electricity,Purchased,N,No Individual Metering,25650.6,25650.6 +89,NW35,Ashdown House,Non-CUP,Residential,RESIDENT,DHOA,MIT,NORTHWEST,2008.0,2008.0,42.35879785,-71.10143928,OWNED,60.0,578.0,252747.43,158044.01,57551.98,772.65,41835.4,0.0,2306.19,0.0,0.0,14943.93,759.62,154635.17,0.0,0.0,343.03,0.0,215595.99,37151.44,Chilled Water,Produced,Y,Chilled Water & Steam,215595.99,215595.99 +90,NW36,BUILDING NW36,Non-CUP,Lab Dominant,SERVICE,OTH,MIT,NORTHWEST,,,,,OWNED,0.0,4.0,2045.25,1559.82,209.87,45.0,0.0,0.0,0.0,0.0,0.0,164.87,0.0,0.0,0.0,0.0,1559.82,0.0,1769.69,275.56,Electricity,Purchased,,,1769.69,1769.69 +91,NW61,Random Hall,Non-CUP,Residential,RESIDENT,DHOA,MIT,NORTHWEST,1899.0,1968.0,42.36184456,-71.0982858,OWNED,48.3,201.0,39469.53,25201.69,7821.4,1142.95,5548.38,0.0,8086.23,0.0,0.0,1130.07,225.6,16600.05,0.0,0.0,289.81,0.0,33023.09,6446.44,Electricity,Purchased,N,No Individual Metering,33023.09,33023.09 +92,NW86,70 Pacific Street Dormitory,Non-CUP,Residential,RESIDENT,DHOA,MIT,NORTHWEST,2001.0,2002.0,42.35972041,-71.10221874,OWNED,106.4,723.0,362686.82,251186.9,63816.25,1022.13,52510.35,0.0,19809.13,0.0,0.0,10283.77,2924.89,223831.64,0.0,1481.43,3139.81,0.0,315003.15,47683.67,Electricity,Purchased,Y,No Individual Metering,315003.15,315003.15 +93,Northwest Campus Area,Northwest Campus Area,Non-CUP,Support Areas & Parking,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Electricity,Purchased,,,, +94,OC19_ABCDEFGHJKLMNQ,Bates LINAC,Off Campus Buildings,Lab & Mixed Use,,,MIT,,,,,,OWNED,,269.0,188458.83000000005,134759.33000000002,17193.03,828.4,11178.55,0.0,0.0,0.0,120600.75,5186.080000000001,14158.579999999998,0.0,0.0,0.0,0.0,0.0,151952.36000000002,36506.47000000001,Electricity,Purchased,,,150036.92,150036.92 +95,OC22,Westford Optics Facility (Haystack),Off Campus Buildings,Lab Dominant,ACADEMIC,AER,HAY,OFFCAMPUS,,,42.61185877,-71.48467394,OWNED,0.0,3.0,881.78,794.16,0.03,0.0,0.0,0.0,0.0,0.0,764.13,0.03,30.03,0.0,0.0,0.0,0.0,0.0,794.19,87.59,Electricity,Purchased,,,, +96,OC23,Wallace Geophysical Observatory,Off Campus Buildings,Lab Dominant,ACADEMIC,AER,HAY,OFFCAMPUS,,1970.0,42.61006145,-71.48988791,OWNED,0.0,6.0,2034.38,1617.25,0.0,0.0,0.0,0.0,0.0,0.0,1499.97,0.0,117.28,0.0,0.0,0.0,0.0,0.0,1617.25,417.13,Electricity,Purchased,,,1617.25,1617.25 +97,Parking Areas,Parking Areas,Non-CUP,Support Areas & Parking,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Electricity,Purchased,,,#VALUE!,#VALUE! +98,W1,Fariborz Maseeh Hall,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,1900.0,1939.0,42.35761763,-71.0935107,OWNED,74.5,558.0,189941.11,107518.76,43591.64,1509.19,33098.63,0.0,14094.47,0.0,0.0,8983.82,11622.36,81285.63,0.0,0.0,516.3,0.0,151110.4,38830.71,Electricity,Produced,Y,Steam Only,151110.4,151110.4 +99,W11,Religious Activities Center,Non-CUP,Lab & Mixed Use,SERVICE,STAC,MIT,WEST,1936.0,1967.0,42.35826109,-71.09353578,OWNED,16.4,63.0,13590.41,7922.29,4152.3,539.28,2766.4,0.0,4160.51,0.0,0.0,846.62,3761.78,0.0,0.0,0.0,0.0,0.0,12074.59,1515.82,Electricity,Purchased,N,No Individual Metering,12074.59,12074.59 +100,W15,MIT Chapel,Non-CUP,Lab & Mixed Use,SERVICE,STAC,MIT,WEST,1954.0,1955.0,42.35832688,-71.09412494,OWNED,33.2,26.0,5339.35,2815.91,1959.77,105.2,986.24,0.0,2607.98,0.0,0.0,868.33,0.0,0.0,0.0,0.0,207.93,0.0,4775.68,563.67,Chilled Water,Produced,Y,No Individual Metering,4775.68,4775.68 +101,W16,Kresge Auditorium,Non-CUP,Lab & Mixed Use,SERVICE,STAC,MIT,WEST,1953.0,1956.0,42.35813383,-71.09505791,OWNED,50.2,95.0,42145.98,20406.21,18201.3,1389.86,10146.47,11335.4,728.89,0.0,0.0,6664.97,6790.5,0.0,817.8,0.0,733.62,0.0,38607.51,3538.47,Chilled Water,Produced,Y,Fully Metered,38607.51,38607.51 +102,W20,Julius Adams Stratton Student Center,Non-CUP,Lab & Mixed Use,SERVICE,STAC,MIT,WEST,1963.0,1965.0,42.3590424,-71.09477464,OWNED,75.0,435.0,183162.0,115330.5,56425.62,3039.62,35924.34,0.0,68329.06,0.0,4307.33,17461.66,31052.56,0.0,267.54,9075.06,1689.4,609.55,171756.12,11405.88,Chilled Water,Produced,Y,Fully Metered,171756.12,171756.12 +103,W2_W4,W2_W4,Non-CUP,Residential,,,MIT,,,,,,OWNED,,629.0,138588.88,72039.78,46162.86,7698.049999999999,29630.12,0.0,7264.5,0.0,0.0,8834.689999999999,2545.1800000000003,61000.08,0.0,235.08,994.94,0.0,118202.64,20386.24,Electricity,Produced,Only W2,No Individual Metering,118202.64,118202.64 +104,W31,David Flett du Pont Athletic Gymnasium,Non-CUP,Mechanical,SERVICE,STAC,MIT,WEST,1902.0,1957.0,42.35963776,-71.09516824,OWNED,52.6,146.0,71443.5,53401.65,9744.51,1054.2,6287.56,1493.72,3973.37,0.0,0.0,2402.75,10545.3,0.0,37322.78,0.0,66.48,0.0,63146.16,8297.34,Electricity,Produced,N,Steam Only,63146.16,63146.16 +105,W32,David Flett du Pont Athletic Center,Non-CUP,Mechanical,SERVICE,STAC,MIT,WEST,1958.0,1959.0,42.35936841,-71.09513369,OWNED,36.1,90.0,46578.52,26366.32,15073.3,868.16,8999.7,0.0,0.0,0.0,0.0,5205.44,3058.89,0.0,23307.43,0.0,0.0,0.0,41439.62,5138.9,Electricity,Produced,N,No Individual Metering,41439.62,41439.62 +106,W33,Rockwell Athletic Cage,Non-CUP,Mechanical,SERVICE,STAC,MIT,WEST,1947.0,1948.0,42.35920175,-71.09597193,OWNED,22.8,7.0,34427.72,32379.24,594.57,0.0,0.0,0.0,0.0,0.0,0.0,594.57,72.19,0.0,32070.31,0.0,236.74,0.0,32973.81,1453.91,Electricity,Produced,N,No Individual Metering,32973.81,32973.81 +107,W34,Johnson Athletics Center,Non-CUP,Mechanical,SERVICE,STAC,MIT,WEST,1979.0,1980.0,42.35859572,-71.09652993,OWNED,37.9,74.0,109397.67,82217.92,20743.24,603.13,9472.45,0.0,0.0,0.0,0.0,10667.66,758.36,0.0,79009.39,0.0,2450.17,0.0,102961.16,6436.51,Chilled Water,Produced,Y,Chilled Water Only,102961.16,102961.16 +108,W35,Zesiger Sports & Fitness Center,Non-CUP,Mechanical,SERVICE,STAC,MIT,WEST,2000.0,2002.0,42.35871563,-71.09575051,OWNED,65.7,220.0,122080.04,76369.95,36482.32,2135.89,21172.24,0.0,326.56,0.0,0.0,13174.19,7680.01,0.0,67475.67,0.0,887.71,0.0,112852.27,9227.76999999999,Chilled Water,Produced,Y,Chilled Water Only,112852.27,112852.27 +109,W41,W41,Non-CUP,Support Areas & Parking,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Electricity,Purchased,,,#VALUE!,#VALUE! +110,W45,W45,Non-CUP,Support Areas & Parking,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Electricity,Purchased,N,No Individual Metering,, +111,W46,New Vassar Residence Hall,Non-CUP,Lab & Mixed Use,RESIDENT,DHOA,MIT,WEST,,,,,OWNED,0.0,515.0,177607.67,85047.66,69862.78,9851.76,47493.6,0.0,18920.44,0.0,0.0,12517.42,1403.26,55094.67,1098.03,2931.85,5599.41,0.0,154910.44,22697.23,Chilled Water,Produced,,,154910.44,154910.44 +112,W5,Ida Flansburgh Green Hall,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,1901.0,1970.0,42.35691893,-71.09510104,OWNED,53.2,106.0,19010.96,9825.59,5593.55,1411.69,3501.9,0.0,287.27,0.0,0.0,679.96,25.4,9336.41,0.0,0.0,176.51,0.0,15419.14,3591.82,Electricity,Produced,N,No Individual Metering,15419.14,15419.14 +113,W51,Burton-Conner House,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,1927.0,1948.0,42.35596941,-71.09812434,OWNED,72.0,690.0,167922.77,104357.88,38420.93,8640.93,23623.94,0.0,9067.24,0.0,633.83,6156.06,3340.31,89432.54,0.0,1217.46,666.5,0.0,142778.81,25143.96,Electricity,Produced,N,No Individual Metering,142339.26,142339.26 +114,W51C,405 Memorial Drive - Pi Phi,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,,,42.35618661,-71.09724199,OWNED,0.0,86.0,17286.8,10693.24,3958.47,32.49,3387.66,0.0,2285.18,0.0,0.0,538.32,15.86,8150.44,0.0,241.76,0.0,0.0,14651.71,2635.09,Steam,Produced,N,No Individual Metering,14651.71,14651.71 +115,W53_W53A_W53B_W53C_W53D,J B Carr Indoor Tennis Facility Buildings,Non-CUP,Mechanical,,,MIT,,,,,,OWNED,,15.0,27387.85,25848.58,540.0699999999999,60.31,94.01,0.0,0.0,0.0,0.0,385.75,299.88,0.0,25548.7,0.0,0.0,0.0,26388.65,999.2,Electricity,Produced,N,No Individual Metering,26388.65,26388.65 +116,W59,Heinz Building,Non-CUP,Lab & Mixed Use,SERVICE,AER,MIT,WEST,1915.0,1979.0,42.35810548,-71.09955089,OWNED,33.5,157.0,36051.39,24915.19,6977.47,1183.93,4441.78,3077.49,434.19,0.0,0.0,1351.76,20956.26,0.0,0.0,0.0,447.25,0.0,31892.66,4158.73,Chilled Water,Produced,N,No Individual Metering,31892.66,31892.66 +117,W61,Frank S MacGregor House,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,1968.0,1970.0,42.35546182,-71.09954663,OWNED,167.5,138.0,168261.25,96219.08,42357.74,8022.66,20532.07,0.0,10128.89,0.0,0.0,13803.01,12717.37,72950.4,0.0,0.0,422.42,0.0,138576.82,29684.43,Electricity,Produced,Y,Steam & Electric,138576.82,138576.82 +118,W64,Building W64,Non-CUP,Lab & Mixed Use,SERVICE,OTH,MIT,WEST,2013.0,2013.0,,,OWNED,0.0,62.0,13367.83,9321.57,2817.74,0.0,2336.55,0.0,8487.1,0.0,0.0,481.19,834.47,0.0,0.0,0.0,0.0,0.0,12139.31,1228.52,Electricity,Purchased,Y,No Individual Metering,12139.31,12139.31 +119,W7,Everett Moore Baker House,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,1947.0,1949.0,42.35669783,-71.09579218,OWNED,76.4,492.0,133099.42,76877.31,42711.09,5633.69,28707.16,0.0,14523.37,0.0,433.89,8370.24,2320.76,57311.4,0.0,0.0,2287.89,0.0,119588.4,13511.02,Electricity,Produced,N,No Individual Metering,119588.4,119588.4 +120,W70,New West Campus Houses,Non-CUP,Support Areas & Parking,RESIDENT,DHOA,MIT,WEST,1974.0,1976.0,42.35516109,-71.10053232,OWNED,46.9,508.0,126147.84,60920.98,40018.4,,,,,,,,,,,,,,,,Electricity,Produced,Y,Steam & Electric,100939.38,#VALUE! +121,W71,Next House,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,1979.0,1981.0,42.35470475,-71.10192118,OWNED,57.5,523.0,132006.46,81297.25,34825.26,7197.21,23305.3,0.0,17735.95,0.0,0.0,4322.75,1496.19,61091.16,0.0,0.0,973.95,0.0,116122.51,15883.95,Electricity,Produced,N,No Individual Metering,116233.58,116233.58 +122,W79,Simmons Hall,Non-CUP,Lab & Mixed Use,RESIDENT,DHOA,MIT,WEST,2000.0,2002.0,42.35710862,-71.1015208,OWNED,100.6,913.0,191189.7,93938.82,68095.76,7956.93,43741.07,0.0,17031.09,0.0,0.0,16397.76,3488.13,59436.21,0.0,10446.01,3537.38,0.0,162034.58,29155.12,Chilled Water,Produced,Y,Fully Metered,162034.58,162034.58 +123,W8,Harold Whitworth Pierce Boathouse,Non-CUP,Special,SERVICE,STAC,MIT,WEST,1965.0,1967.0,42.35531243,-71.09682721,OWNED,24.1,32.0,21710.72,17122.24,3226.99,429.9,1858.77,0.0,0.0,0.0,0.0,938.32,557.14,0.0,16565.1,0.0,0.0,0.0,20349.23,1361.49,Electricity,Produced,N,No Individual Metering,27447.04,27447.04 +124,W84,Tang Residence Hall,Non-CUP,Residential,RESIDENT,DHOA,MIT,WEST,1970.0,1973.0,42.35435175,-71.10347949,OWNED,240.4,387.0,152378.32,109244.79,25905.79,596.87,17749.99,0.0,1305.05,0.0,128.6,7558.93,258.95,106654.75,0.0,0.0,897.44,0.0,135150.58,17227.74,Electricity,Produced,N,No Individual Metering,135281.43,135281.43 +125,W85_W85ABC_W85DE_W85FG_W85HJK,Westgate,Non-CUP,Residential,,,MIT,,,,,,OWNED,,466.0,162224.82,121037.35,28938.070000000003,833.01,19331.33,0.0,1822.14,0.0,0.0,8773.73,175.68,118857.55,0.0,0.0,181.98,0.0,149975.42,12249.40000000001,Electricity,Produced,Y,No Individual Metering,150009.4,150009.4 +126,W89,MIT Police,Non-CUP,Office & Mixed Use,SERVICE,AER,MIT,WEST,1948.0,2006.0,42.35553858,-71.10467329,OWNED,27.9,82.0,14909.35,7808.8,4724.43,403.18,3500.37,0.0,0.0,0.0,0.0,820.88,7808.8,0.0,0.0,0.0,0.0,0.0,12533.23,2376.12,Electricity,Purchased,N,No Individual Metering,#VALUE!,#VALUE! +127,W91,Building W91,Non-CUP,Lab & Mixed Use,SERVICE,AER,MIT,WEST,1947.0,1949.0,42.35432356,-71.10442611,OWNED,40.7,116.0,35748.48,16886.53,15094.12,724.8,5194.15,0.0,359.56,0.0,0.0,9175.17,7255.16,0.0,1704.48,535.87,7031.46,0.0,31980.65,3767.83,Electricity,Produced,Y,No Individual Metering,31980.65,31980.65 +128,W92,Building W92,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,WEST,,1999.0,42.35492043,-71.1046169,OWNED,32.1,193.0,86521.66,74299.91,8317.61,1661.14,3269.39,0.0,0.0,0.0,0.0,3387.08,48805.66,0.0,0.0,0.0,25494.25,0.0,82617.52,3904.14,Electricity,Purchased,N,No Individual Metering,82617.52,82617.52 +129,W97,BUILDING W97,Non-CUP,Lab & Mixed Use,ACADEMIC,(NULL),MIT,WEST,,,,,OWNED,0.0,60.0,30550.79,18065.62,5821.34,745.7,3834.88,0.0,2172.97,0.0,13576.99,1240.76,1970.53,0.0,0.0,0.0,345.13,0.0,23886.96,6663.83,Electricity,Purchased,,,23886.96,23886.96 +130,W98,600 Memorial Drive,Non-CUP,Lab & Mixed Use,ACADEMIC,AER,MIT,WEST,,,42.35395541,-71.10664515,OWNED,91.0,553.0,82624.13,47561.94,25282.27,2322.09,18305.49,0.0,391.74,0.0,0.0,4654.69,47056.69,0.0,0.0,0.0,113.51,0.0,72844.21,9779.92,Electricity,Purchased,N,No Individual Metering,72844.21,72844.21 +131,WW15,Building WW15,Non-CUP,Lab Dominant,SERVICE,AER,MIT,WESTWEST,1969.0,,42.35536136,-71.10946972,OWNED,16.0,108.0,42145.75,37522.58,2797.37,652.34,1311.81,0.0,6507.45,0.0,0.0,833.22,5487.52,0.0,0.0,0.0,25527.61,0.0,40319.95,1825.8,Electricity,Purchased,N,No Individual Metering,40319.95,40319.95 diff --git a/data/seed.py b/data/seed.py new file mode 100644 index 0000000..5a98e73 --- /dev/null +++ b/data/seed.py @@ -0,0 +1,112 @@ +import math + +import numpy as np +import pandas as pd +from sqlmodel import Session + +from lib.models import ( + Building, + BuildingSimulationResult, + DemandScenario, + DemandScenarioBuilding, + DesignVector, + PowerPlant, + PowerPlantScenario, + engine, +) + +df = pd.read_csv("data/mit_buildings_info.csv") +results_df = pd.read_hdf("data/5out.hdf", key="results") +with Session(engine) as session: + ds = DemandScenario( + name="Test Data Scenario", description="Test Data Scenario", year_available=2030 + ) + dv = DesignVector(name="Test Design Vector") + bsrs = [] + + for i, row in df.iterrows(): + building = Building( + name=row["BUILDING_NAME_LONG"], + building_number=row["BUILDING_NUMBER"], + group_level_1=row["BUILDING_GROUP_LEVEL1"], + usage=row["CLUSTER_NUM"], + gfa=( + row["EXT_GROSS_AREA"] if not math.isnan(row["EXT_GROSS_AREA"]) else None + ), + height=( + row["BUILDING_HEIGHT"] + if not math.isnan(row["BUILDING_HEIGHT"]) + else None + ), + year=( + row["YEAR_CONST_BEGAN"] + if not math.isnan(row["YEAR_CONST_BEGAN"]) + else None + ), + ) + bsr = BuildingSimulationResult( + demand_scenario_building=DemandScenarioBuilding( + building=building, demand_scenario=ds, design_vector=dv + ), + heating=results_df[ + f"Zone Ideal Loads Supply Air Total Heating Energy" + ].values.tolist(), + cooling=results_df[ + f"Zone Ideal Loads Supply Air Total Cooling Energy" + ].values.tolist(), + lighting=results_df[f"Zone Lights Electricity Energy"].values.tolist(), + equipment=results_df[ + f"Zone Electric Equipment Electricity Energy" + ].values.tolist(), + ) + bsrs.append(bsr) + session.add_all(bsrs) + + pv = PowerPlant( + name="Photovoltaics", + description="Photovoltaic Panels on the roof", + nominal_capacity=100, + nominal_cost=0.01, + nominal_emissions_factor=0, + ) + grid = PowerPlant( + name="Grid", + description="The municipal power grid", + nominal_capacity=99999, + nominal_cost=0.24, + nominal_emissions_factor=23, + ) + cup = PowerPlant( + name="CUP", + description="The campus combined utility plant", + nominal_capacity=40000, # 40 MW + nominal_cost=0.01, + nominal_emissions_factor=0, + ) + session.add_all([pv, grid, cup]) + + t = np.linspace(0, 365 * 2 * np.pi, 8761) + t = t[:-1] + ts = pd.date_range(start="2020-01-01", end="2020-12-31", freq="h")[:-1] + y = np.sin(t - 2 * np.pi / 3).clip(0, 1) * ((-np.cos(t / 365) + 1) / 4 + 0.5) + + pv_50 = PowerPlantScenario( + power_plant=pv, + name="50% PV Coverage", + description="50% of the available roof space is covered in PV panels", + year_available=2030, + capacities=y * 500, + emissions_factors=np.zeros(8760), + cost_factors=np.zeros(8760), + ) + pv_70 = PowerPlantScenario( + power_plant=pv, + name="75% PV Coverage", + description="75% of the available roof space is covered in PV panels", + year_available=2040, + capacities=y * 75, + emissions_factors=np.zeros(8760), + cost_factors=np.zeros(8760), + ) + session.add_all([pv_50, pv_70]) + session.commit() diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000..b60837c --- /dev/null +++ b/environment.yml @@ -0,0 +1,6 @@ +name: mit-campus-decarbonization +dependencies: + - python=3.9 + - pip + - pip: + - -r requirements.txt \ No newline at end of file diff --git a/frontend/app.py b/frontend/app.py index b037e0c..cde4b69 100644 --- a/frontend/app.py +++ b/frontend/app.py @@ -1,5 +1,6 @@ import logging import sys +from typing import Optional logger = logging.getLogger(__name__) logging.basicConfig() @@ -17,6 +18,7 @@ import pandas as pd import plotly.express as px import streamlit as st +from sqlalchemy.orm import selectinload from sqlmodel import Session, select from frontend import frontend_settings as settings @@ -26,11 +28,11 @@ BuildingSimulationResult, DemandScenario, DemandScenarioBuilding, + PowerPlant, + PowerPlantScenario, engine, ) -# from lib.supa import Building - st.set_page_config(layout="wide", page_title="MIT Decarbonization") @@ -93,7 +95,31 @@ def create_demand_scenario(name: str): session.add(scenario) session.commit() st.cache_data.clear() - st.experimental_rerun() + st.rerun() + + +def create_power_plant(name: str): + with Session(engine) as session: + scenario = PowerPlant(name=name) + session.add(scenario) + session.commit() + get_power_plants.clear() + st.rerun() + + +def create_power_plant_scenario(name: str, power_plant_id: int, df: pd.DataFrame): + with Session(engine) as session: + scenario = PowerPlantScenario( + name=name, + power_plant_id=power_plant_id, + emissions_factors=df["emissions_factors"].values, + cost_factors=df["cost_factors"].values, + capacities=df["capacities"].values, + ) + session.add(scenario) + session.commit() + get_power_plant_scenarios.clear() + st.rerun() @st.cache_data @@ -179,6 +205,28 @@ def get_scenario_building_result(scenario_id: int, building_id: int): return df, df_melted +@st.cache_data +def get_power_plants() -> list[PowerPlant]: + with Session(engine) as session: + stmt = select(PowerPlant).options( + selectinload(PowerPlant.power_plant_scenarios) + ) + power_plants = session.exec(stmt).all() + + return [(p.model_dump()) for p in power_plants] + + +@st.cache_data +def get_power_plant_scenarios(power_plant_id: int) -> list[PowerPlantScenario]: + with Session(engine) as session: + stmt = select(PowerPlantScenario).where( + PowerPlantScenario.power_plant_id == power_plant_id + ) + power_plant_scenarios = session.exec(stmt).all() + + return [(p.model_dump(), p.to_df()) for p in power_plant_scenarios] + + ENDUSE_PASTEL_COLORS = { "Heating": "#FF7671", "Cooling": "#6D68E6", @@ -252,7 +300,7 @@ def render_building_scenarios(): df, df_melted, df_buildings = get_scenario_results(scenario["id"]) if df is None: st.warning("No results found for this scenario!") - render_create_scenario() + render_create_demand_scenario() return l, r = st.columns(2) @@ -283,17 +331,177 @@ def render_building_scenarios(): color_discrete_map=ENDUSE_PASTEL_COLORS, ) st.plotly_chart(fig, use_container_width=True) - render_create_scenario() + render_create_demand_scenario() -def render_create_scenario(): +def render_create_demand_scenario(): st.divider() st.markdown("### Create a new demand scenario") - name = st.text_input("Name") - if st.button("Create", disabled=name == ""): + name = st.text_input( + "Name", key="create_demand_scenario_name", help="Name of the scenario" + ) + if st.button("Create", disabled=name == "", key="create_demand_scenario_button"): create_demand_scenario(name) +def render_create_power_plant(): + st.divider() + st.markdown("### New Power Plant") + st.markdown("Create a new power plant type.") + name = st.text_input( + "Name", key="create_power_plant_name", help="Name of the power plant type" + ) + if st.button( + "Create", + disabled=name == "", + key="create_power_plant_button", + type="primary", + use_container_width=True, + ): + create_power_plant(name) + + +# TODO: use pandera, import UploadedFile type annotation +@st.cache_data +def validate_power_plant_scenario_csv(csv_file) -> Optional[pd.DataFrame]: + try: + df = pd.read_csv(csv_file) + # assert "Timestamp" in df.columns + assert "capacities" in df.columns + assert "emissions_factors" in df.columns + assert "cost_factors" in df.columns + assert len(df) == 8760 + assert df["capacities"].dtype in [int, float] + assert df["emissions_factors"].dtype in [int, float] + assert df["cost_factors"].dtype in [int, float] + # assert df["Timestamp"].dtype == "datetime64[ns]" + return df + except Exception as e: + return None + + +def render_create_power_plant_scenario(pp: PowerPlant): + st.divider() + st.markdown("### New Power Plant Scenario") + st.markdown(f"Create a new scenario for `{pp.name}` power plant type") + name = st.text_input( + "Name", key="create_power_plant_scenario_name", help="Name of the scenario" + ) + csv_file = st.file_uploader( + "Upload a CSV file with the scenario data", + type=["csv"], + accept_multiple_files=False, + key="upload_power_plant_scenario_data", + ) + df = None + if csv_file: + df = validate_power_plant_scenario_csv(csv_file) + if df is None: + st.error( + "Invalid CSV file. Please check the file format and try again. The CSV must have three columns: 'capacities', 'emissions_factors', and 'cost_factors' and 8760 rows." + ) + + disabled = name == "" or df is None + if st.button( + "Create", + disabled=disabled, + key="create_power_plant_scenario_button", + use_container_width=True, + type="primary", + ): + create_power_plant_scenario(name, pp.id, df) + + +def render_power_plants(): + l, r = st.columns(2) + chart_container = st.container() + create_plant_container, create_plant_scenario_container = st.columns(2) + + with create_plant_container: + render_create_power_plant() + + # get the power plants + power_plants = [PowerPlant.model_validate(p) for p in get_power_plants()] + + # early return if no power plants + if len(power_plants) == 0: + st.warning("No power plants found!") + return + + # select a plant + with l: + pp = st.selectbox( + "Power Plant", + power_plants, + format_func=lambda x: x.name, + help="Select a power plant to view its data", + ) + + with create_plant_scenario_container: + render_create_power_plant_scenario(pp) + + # get scenarios + pp_scenarios = [ + (PowerPlantScenario.model_validate(p)) + for p, df in get_power_plant_scenarios(pp.id) + ] + + # early return if no scenarios + if len(pp_scenarios) == 0: + with r: + st.warning("No scenarios found for this power plant!") + return + + # create a combined dataframe of all scenarios + pp_scenarios_dfs = [df for p, df in get_power_plant_scenarios(pp.id)] + stacked_scenarios = pd.concat(pp_scenarios_dfs, axis=0) + + # downloader for all scenarios + with l: + st.download_button( + f"Download {pp.name} power plant scenarios", + encode_csv(stacked_scenarios), + f"{pp.name}_scenarios.csv", + "Download all scenarios for power plant type.", + use_container_width=True, + type="primary", + ) + + # selector for single scenario + with r: + s = st.selectbox( + "Power Plant Scenario", + list(range(len(pp_scenarios))), + format_func=lambda x: pp_scenarios[x].name, + help="Select a power plant scenario to view its data", + ) + + # select scenario data + scenario_df = pp_scenarios_dfs[s] + scenario = pp_scenarios[s] + + # downloader for single scenario + with r: + st.download_button( + f"Download {pp.name} {scenario.name} scenario", + encode_csv(scenario_df), + f"{pp.name}_{scenario.name}_scenario.csv", + "Download scenario data", + use_container_width=True, + type="primary", + ) + + with chart_container: + fig = px.line( + scenario_df.reset_index(), + x="Timestamp", + y="capacities", + title=f"{pp.name} {scenario.name} Scenario", + labels={"capacities": "Capacity [kW]"}, + ) + st.plotly_chart(fig, use_container_width=True) + + def password_protect(): if settings.env == "dev": return True @@ -313,8 +521,12 @@ def password_protect(): render_title() logged_in = password_protect() if logged_in: - buildings_tab, scenarios_tab = st.tabs(["Buildings", "Scenarios"]) + buildings_tab, scenarios_tab, power_plants_tab = st.tabs( + ["Buildings", "Scenarios", "Power Plants"] + ) with buildings_tab: render_buildings() with scenarios_tab: render_building_scenarios() + with power_plants_tab: + render_power_plants() diff --git a/lib/models.py b/lib/models.py index 9707a67..6bb0cc8 100644 --- a/lib/models.py +++ b/lib/models.py @@ -86,6 +86,8 @@ class DemandScenario(SQLModel, table=True): Attributes: id (Optional[int]): The ID of the demand scenario. name (str): The name of the demand scenario. + description (Optional[str]): The description of the demand scenario. + year_available (Optional[int]): The year the demand scenario is available. buildings (list[Building]): The list of buildings associated with the demand scenario. demand_scenario_designs (list[DemandScenarioBuilding]): The list of demand scenario designs associated with the demand scenario. """ @@ -93,6 +95,12 @@ class DemandScenario(SQLModel, table=True): __tablename__ = "DemandScenario" id: Optional[int] = Field(default=None, primary_key=True) name: str = Field(..., description="Name of the demand scenario") + description: Optional[str] = Field( + None, description="Description of the demand scenario" + ) + year_available: Optional[int] = Field( + ..., description="Year the demand scenario is available" + ) buildings: list["Building"] = Relationship( back_populates="demand_scenarios", link_model=DemandScenarioBuilding ) @@ -178,3 +186,95 @@ def to_df(self) -> pd.DataFrame: class Config: arbitrary_types_allowed = True + + +class PowerPlant(SQLModel, table=True): + """ + Represents a power plant in the decarbonization model. + + Attributes: + id (Optional[int]): The ID of the power plant. + name (str): The name of the power plant. + description (Optional[str]): The description of the power plant. + nominal_capacity (Optional[float]): The nominal capacity of the power plant in kW. + nominal_cost (Optional[float]): The nominal cost of the power plant in $/kWh. + nominal_emissions_factor (Optional[float]): The nominal emissions factor of the power plant in kgCO2/kWh. + power_plant_scenarios (list[PowerPlantScenario]): The list of power plant scenarios associated with the power plant. + """ + + __tablename__ = "PowerPlant" + id: Optional[int] = Field(default=None, primary_key=True) + name: str = Field(..., description="Name of the power plant") + description: Optional[str] = Field( + None, description="Description of the power plant" + ) + nominal_capacity: Optional[float] = Field( + None, description="Nominal capacity of the power plant [kW]" + ) + nominal_cost: Optional[float] = Field( + None, description="Nominal cost of the power plant [$/kWh]" + ) + nominal_emissions_factor: Optional[float] = Field( + None, description="Nominal emissions factor of the power plant [kgCO2/kWh]" + ) + power_plant_scenarios: list["PowerPlantScenario"] = Relationship( + back_populates="power_plant" + ) + + +class PowerPlantScenario(SQLModel, table=True): + """ + Represents a power plant scenario in the decarbonization model. + + Attributes: + id (Optional[int]): The ID of the power plant scenario. + power_plant_id (int): The ID of the associated power plant. + power_plant (PowerPlant): The associated power plant. + name (str): The name of the power plant scenario. + description (Optional[str]): The description of the power plant scenario. + year_available (Optional[int]): The year the power plant scenario is available. + emissions_factors (Optional[np.ndarray]): The emissions factors for the power plant scenario. + cost_factors (Optional[np.ndarray]): The cost factors for the power plant scenario. + capacities (Optional[np.ndarray]): The capacities for the power plant scenario. + """ + + __tablename__ = "PowerPlantScenario" + id: Optional[int] = Field(default=None, primary_key=True) + power_plant_id: int = Field(..., foreign_key="PowerPlant.id") + power_plant: PowerPlant = Relationship(back_populates="power_plant_scenarios") + name: str = Field(..., description="Name of the power plant scenario") + description: Optional[str] = Field( + None, description="Description of the power plant scenario" + ) + year_available: Optional[int] = Field( + ..., description="Year the power plant scenario is available" + ) + emissions_factors: np.ndarray = Field(None, sa_column=Column(Vector(8760))) + cost_factors: np.ndarray = Field(None, sa_column=Column(Vector(8760))) + capacities: np.ndarray = Field(None, sa_column=Column(Vector(8760))) + + def to_df(self) -> pd.DataFrame: + df = pd.DataFrame( + { + "emissions_factors": self.emissions_factors, + "cost_factors": self.cost_factors, + "capacities": self.capacities, + } + ) + df.index = pd.date_range(start="1/1/2024", periods=8760, freq="h") + df.index.name = "Timestamp" + df = df.set_index( + pd.Series([self.power_plant.id] * 8760, name="power_plant_id"), append=True + ) + df = df.set_index( + pd.Series([self.power_plant.name] * 8760, name="power_plant_name"), + append=True, + ) + df = df.set_index( + pd.Series([self.name] * 8760, name="scenario_name"), append=True + ) + df = df.set_index(pd.Series([self.id] * 8760, name="scenario_id"), append=True) + return df + + class Config: + arbitrary_types_allowed = True diff --git a/notebooks/.gitkeep b/notebooks/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/notebooks/supa.ipynb b/notebooks/supa.ipynb deleted file mode 100644 index 638c931..0000000 --- a/notebooks/supa.ipynb +++ /dev/null @@ -1,295 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from supabase import create_client\n", - "from supabase.lib.client_options import ClientOptions\n", - "import os\n", - "\n", - "client_options = ClientOptions(postgrest_client_timeout=60)\n", - "client = create_client(supabase_url=os.getenv('SUPABASE_URL'), supabase_key=os.getenv('SUPABASE_SERVICE_ROLE_KEY'), options=client_options)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "client.table('Building').insert({\"name\": \"test\", \"gfa\": 1000,}).execute()\n", - "client.table(\"DesignVector\").insert({\"name\": \"testdesign\"}).execute()\n", - "client.table(\"DemandScenario\").insert({\"name\": \"testdemand\"}).execute()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "client.table(\"DemandScenarioBuilding\").insert({\"demand_scenario_id\": 1, \"building_id\": 1, \"design_vector_id\": 1}).execute()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "client.table(\"BuildingSimulationResult\").insert({\n", - "\t\"id\": 1,\n", - "\t\"heating\": np.random.rand(8760).tolist(),\n", - "\t\"cooling\": np.random.rand(8760).tolist(),\n", - "\t\"lighting\": np.random.rand(8760).tolist(),\n", - "\t\"equipment\": np.random.rand(8760).tolist(),\n", - "\t\"pumps\": np.random.rand(8760).tolist(),\n", - "\t\"fans\": np.random.rand(8760).tolist(),\n", - "\t\"water\": np.random.rand(8760).tolist(),\n", - "\t\"misc\": np.random.rand(8760).tolist(),\n", - "\n", - "}).execute()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "res = client.table(\"BuildingSimulationResult\").select(\"*\").execute()\n", - "import json\n", - "np.array(json.loads(res.data[0][\"heating\"])).shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pydantic import BaseModel, Field, validate_call\n", - "from datetime import datetime\n", - "\n", - "class BuildingBase(BaseModel, extra=\"forbid\"):\n", - " name: str = Field(..., description=\"Name of the building\")\n", - " gfa: float = Field(..., gt=100, description=\"Gross Floor Area of the building, m2\")\n", - "\n", - "class Building(BuildingBase):\n", - " id: int = Field(..., description=\"Unique identifier for the building\")\n", - " created_at: str = Field(..., description=\"Timestamp of the creation of the building\")\n", - "\n", - " @classmethod\n", - " def get(cls, id: int):\n", - " building = client.table(\"Building\").select(\"*\").eq(\"id\", id).execute()\n", - " if len(building.data) == 0:\n", - " raise ValueError(f\"Building with id {id} not found\")\n", - "\n", - " return cls(**building.data[0])\n", - " \n", - " @classmethod\n", - " @validate_call()\n", - " def create(cls, building: BuildingBase):\n", - " building = client.table(\"Building\").insert(building.model_dump()).execute()\n", - " return cls(**building.data[0])\n", - "\n", - " \n", - " def commit(self):\n", - " client.table(\"Building\").upsert(self.model_dump()).execute()\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - " \n", - "\n", - "building = Building.get(1)\n", - "building.gfa = 2000\n", - "building.commit()\n", - "\n", - "building = Building.create({\"name\": \"test2\", \"gfa\": 3000})\n", - "building.id" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pydantic import model_validator\n", - "from typing import Optional\n", - "import pandas as pd\n", - "import numpy as np\n", - "class BuildingSimulationResult(BaseModel, arbitrary_types_allowed=True, extra=\"forbid\"):\n", - " id: int\n", - " created_at: Optional[str] = Field(None, description=\"Timestamp of the creation of the record\")\n", - " heating: np.ndarray\n", - " cooling: np.ndarray\n", - " lighting: np.ndarray\n", - " equipment: np.ndarray\n", - " pumps: np.ndarray\n", - " fans: np.ndarray\n", - " water: np.ndarray\n", - " misc: np.ndarray\n", - "\n", - " # set up all np.ndarrays to serialize to list\n", - " class Config:\n", - " json_encoders = {\n", - " np.ndarray: lambda v: v.tolist()\n", - " }\n", - " \n", - " \n", - " @property\n", - " def building_id(self):\n", - " res = client.table(\"DemandScenarioBuilding\").select(\"building_id\").eq(\"id\", self.id).execute()\n", - " return res.data[0].get(\"building_id\")\n", - " \n", - " @property\n", - " def demand_scenario_id(self):\n", - " res = client.table(\"DemandScenarioBuilding\").select(\"demand_scenario_id\").eq(\"id\", self.id).execute()\n", - " return res.data[0].get(\"demand_scenario_id\")\n", - " \n", - " @property\n", - " def design_vector_id(self):\n", - " res = client.table(\"DemandScenarioBuilding\").select(\"design_vector_id\").eq(\"id\", self.id).execute()\n", - " return res.data[0].get(\"design_vector_id\")\n", - " \n", - "\n", - "\n", - " @model_validator(mode=\"before\")\n", - " def cast_fields_to_numpy(cls, v):\n", - " for key in v:\n", - " if cls.model_fields[key].annotation == np.ndarray:\n", - " if type(v[key]) == list:\n", - " v[key] = np.array(v[key])\n", - " elif type(v[key]) == str:\n", - " v[key] = np.array(json.loads(v[key]))\n", - " elif type(v[key]) == pd.Series:\n", - " v[key] = v[key].values\n", - " else:\n", - " pass\n", - "\n", - " assert v[key].shape == (8760,), f\"Field {key} must have shape (8760,) but has shape {v[key].shape}\"\n", - " return v\n", - "\n", - " @classmethod\n", - " def get(cls, id: int):\n", - " res = client.table(\"BuildingSimulationResult\").select(\"*\").eq(\"id\", id).execute()\n", - " if len(res.data) == 0:\n", - " raise ValueError(f\"BuildingSimulationResult with id {id} not found\")\n", - "\n", - " return cls(**res.data[0])\n", - " \n", - " def to_df(self) -> pd.DataFrame:\n", - " df = pd.DataFrame({\n", - " \"heating\": self.heating,\n", - " \"cooling\": self.cooling,\n", - " \"lighting\": self.lighting,\n", - " \"equipment\": self.equipment,\n", - " \"pumps\": self.pumps,\n", - " \"fans\": self.fans,\n", - " \"water\": self.water,\n", - " \"misc\": self.misc,\n", - " }, index=pd.date_range(start=\"2024-01-01 00:00:00\", periods=8760, freq=\"H\", name=\"timestep\") )\n", - " df = df.set_index(pd.Series([self.id]*8760, name=\"building_id\"), append=True, )\n", - " raise ValueError(\"Not finished implementing; decide on multiindex!\")\n", - " df = df.unstack(level=\"timestep\")\n", - " return df\n", - " \n", - " # def from_df(self, df: pd.DataFrame):\n", - " # series = df.loc[self.id]\n", - " # self.heating = series.heating.values\n", - " # self.cooling = series.cooling.values\n", - " # self.lighting = series.lighting.values\n", - " # self.equipment = series.equipment.values\n", - " # self.pumps = series.pumps.values\n", - " # self.fans = series.fans.values\n", - " # self.water = series.water.values\n", - " # self.misc = series.misc.values\n", - "\n", - " def commit(self):\n", - " client.table(\"BuildingSimulationResult\").upsert(self.model_dump(mode=\"json\", exclude=[\"created_at\"])).execute()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "building_result = BuildingSimulationResult.get(1).to_df()\n", - "building_result[\"heating\"] = 1\n", - "building_r = BuildingSimulationResult.get(1)\n", - "building_r.from_df(building_result)\n", - "building_r.commit()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# create 200 buildings\n", - "for i in range(2, 201):\n", - "\tbuilding = Building.create({\"name\": f\"test{i}\", \"gfa\": 1000})\n", - "\tres = client.table(\"DemandScenarioBuilding\").insert({\"demand_scenario_id\": 1, \"building_id\": building.id, \"design_vector_id\": 1}).execute()\n", - "\tds_id = res.data[0][\"id\"]\n", - "\tsim_result = BuildingSimulationResult(id=building.id, heating=np.random.rand(8760), cooling=np.random.rand(8760), lighting=np.random.rand(8760), equipment=np.random.rand(8760), pumps=np.random.rand(8760), fans=np.random.rand(8760), water=np.random.rand(8760), misc=np.random.rand(8760))\n", - "\tsim_result.commit()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "res = client.table(\"BuildingSimulationResult\").select(\"*\").execute()\n", - "buildings = []\n", - "for row in res.data:\n", - "\tbuilding = BuildingSimulationResult(**row)\n", - "\tbuildings.append(building.to_df())\n", - "buildings = pd.concat(buildings,axis=0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "campus-decarb", - "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.9.18" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4d3947c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,347 @@ +{ + "name": "mit-campus-decarbonization", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "supabase": "^1.142.2" + } + }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/bin-links": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-4.0.3.tgz", + "integrity": "sha512-obsRaULtJurnfox/MDwgq6Yo9kzbv1CPTk/1/s7Z/61Lezc8IKkFCOXNeVLXz0456WRzBQmSsDWlai2tIhBsfA==", + "dev": true, + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/cmd-shim": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.2.tgz", + "integrity": "sha512-+FFYbB0YLaAkhkcrjkyNLYDiOsFSfRjwjY19LXk/psmMx1z00xlCv7hhQoTGXXIKi+YXHL/iiFo8NqMVQX9nOw==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-cmd-shim": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supabase": { + "version": "1.142.2", + "resolved": "https://registry.npmjs.org/supabase/-/supabase-1.142.2.tgz", + "integrity": "sha512-CWe6+WIGnWg8rHXngDwlJX1A3DyEpZLD2EMnA0YKUU1WdnpbdUQsu5vVWbiybFxOC2SPdbylzEyV5iFy6qa7Nw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bin-links": "^4.0.3", + "https-proxy-agent": "^7.0.2", + "node-fetch": "^3.3.2", + "tar": "6.2.0" + }, + "bin": { + "supabase": "bin/supabase" + }, + "engines": { + "npm": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", + "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3cb6459 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "devDependencies": { + "supabase": "^1.142.2" + }, + "scripts": { + "conda-setup": "conda env create -f environment.yml", + "conda-update": "conda env update -f environment.yml", + "db-reset": "npx supabase db reset", + "db-seed": "conda activate mit-campus-decarbonization && python data/seed.py", + "db-refresh": "npm run reset-db && npm run db-refresh", + "fe-start": "conda activate mit-campus-decarbonization && streamlit run frontend/app.py" + } +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 3f1eca1..96dfe07 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -r requirements/base-requirements.txt --r requirements/fe-requirements.txt \ No newline at end of file +-r requirements/fe-requirements.txt +-r requirements/api-requirements.txt \ No newline at end of file diff --git a/requirements/base-requirements.txt b/requirements/base-requirements.txt index 8081724..e730293 100644 --- a/requirements/base-requirements.txt +++ b/requirements/base-requirements.txt @@ -4,4 +4,5 @@ pandera supabase psycopg2-binary pgvector -sqlmodel \ No newline at end of file +sqlmodel +tables \ No newline at end of file diff --git a/supabase/.gitignore b/supabase/.gitignore new file mode 100644 index 0000000..a3ad880 --- /dev/null +++ b/supabase/.gitignore @@ -0,0 +1,4 @@ +# Supabase +.branches +.temp +.env diff --git a/supabase/config.toml b/supabase/config.toml new file mode 100644 index 0000000..33c4ac9 --- /dev/null +++ b/supabase/config.toml @@ -0,0 +1,159 @@ +# A string used to distinguish different Supabase projects on the same host. Defaults to the +# working directory name when running `supabase init`. +project_id = "mit-campus-decarbonization" + +[api] +enabled = true +# Port to use for the API URL. +port = 54321 +# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API +# endpoints. public and storage are always included. +schemas = ["public", "storage", "graphql_public"] +# Extra schemas to add to the search_path of every request. public is always included. +extra_search_path = ["public", "extensions"] +# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size +# for accidental or malicious requests. +max_rows = 1000 + +[db] +# Port to use for the local database URL. +port = 54322 +# Port used by db diff command to initialize the shadow database. +shadow_port = 54320 +# The database major version to use. This has to be the same as your remote database's. Run `SHOW +# server_version;` on the remote database to check. +major_version = 15 + +[db.pooler] +enabled = false +# Port to use for the local connection pooler. +port = 54329 +# Specifies when a server connection can be reused by other clients. +# Configure one of the supported pooler modes: `transaction`, `session`. +pool_mode = "transaction" +# How many server connections to allow per user/database pair. +default_pool_size = 20 +# Maximum number of client connections allowed. +max_client_conn = 100 + +[realtime] +enabled = true +# Bind realtime via either IPv4 or IPv6. (default: IPv6) +# ip_version = "IPv6" +# The maximum length in bytes of HTTP request headers. (default: 4096) +# max_header_length = 4096 + +[studio] +enabled = true +# Port to use for Supabase Studio. +port = 54323 +# External URL of the API server that frontend connects to. +api_url = "http://127.0.0.1" + +# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they +# are monitored, and you can view the emails that would have been sent from the web interface. +[inbucket] +enabled = true +# Port to use for the email testing server web interface. +port = 54324 +# Uncomment to expose additional ports for testing user applications that send emails. +# smtp_port = 54325 +# pop3_port = 54326 + +[storage] +enabled = true +# The maximum file size allowed (e.g. "5MB", "500KB"). +file_size_limit = "50MiB" + +[auth] +enabled = true +# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used +# in emails. +site_url = "http://127.0.0.1:3000" +# A list of *exact* URLs that auth providers are permitted to redirect to post authentication. +additional_redirect_urls = ["https://127.0.0.1:3000"] +# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week). +jwt_expiry = 3600 +# If disabled, the refresh token will never expire. +enable_refresh_token_rotation = true +# Allows refresh tokens to be reused after expiry, up to the specified interval in seconds. +# Requires enable_refresh_token_rotation = true. +refresh_token_reuse_interval = 10 +# Allow/disallow new user signups to your project. +enable_signup = true +# Allow/disallow testing manual linking of accounts +enable_manual_linking = false + +[auth.email] +# Allow/disallow new user signups via email to your project. +enable_signup = true +# If enabled, a user will be required to confirm any email change on both the old, and new email +# addresses. If disabled, only the new email is required to confirm. +double_confirm_changes = true +# If enabled, users need to confirm their email address before signing in. +enable_confirmations = false + +# Uncomment to customize email template +# [auth.email.template.invite] +# subject = "You have been invited" +# content_path = "./supabase/templates/invite.html" + +[auth.sms] +# Allow/disallow new user signups via SMS to your project. +enable_signup = true +# If enabled, users need to confirm their phone number before signing in. +enable_confirmations = false +# Template for sending OTP to users +template = "Your code is {{ .Code }} ." + +# Use pre-defined map of phone number to OTP for testing. +[auth.sms.test_otp] +# 4152127777 = "123456" + +# This hook runs before a token is issued and allows you to add additional claims based on the authentication method used. +[auth.hook.custom_access_token] +# enabled = true +# uri = "pg-functions:////" + + +# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`. +[auth.sms.twilio] +enabled = false +account_sid = "" +message_service_sid = "" +# DO NOT commit your Twilio auth token to git. Use environment variable substitution instead: +auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)" + +# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`, +# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin_oidc`, `notion`, `twitch`, +# `twitter`, `slack`, `spotify`, `workos`, `zoom`. +[auth.external.apple] +enabled = false +client_id = "" +# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead: +secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)" +# Overrides the default auth redirectUrl. +redirect_uri = "" +# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure, +# or any other third-party OIDC providers. +url = "" + +[analytics] +enabled = false +port = 54327 +vector_port = 54328 +# Configure one of the supported backends: `postgres`, `bigquery`. +backend = "postgres" + +# Experimental features may be deprecated any time +[experimental] +# Configures Postgres storage engine to use OrioleDB (S3) +orioledb_version = "" +# Configures S3 bucket URL, eg. .s3-.amazonaws.com +s3_host = "env(S3_HOST)" +# Configures S3 bucket region, eg. us-east-1 +s3_region = "env(S3_REGION)" +# Configures AWS_ACCESS_KEY_ID for S3 bucket +s3_access_key = "env(S3_ACCESS_KEY)" +# Configures AWS_SECRET_ACCESS_KEY for S3 bucket +s3_secret_key = "env(S3_SECRET_KEY)" diff --git a/supabase/migrations/20240211215240_remote_schema.sql b/supabase/migrations/20240211215240_remote_schema.sql new file mode 100644 index 0000000..cc954f7 --- /dev/null +++ b/supabase/migrations/20240211215240_remote_schema.sql @@ -0,0 +1,368 @@ +create extension if not exists "vector" with schema "extensions"; + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +CREATE SCHEMA IF NOT EXISTS "public"; + +ALTER SCHEMA "public" OWNER TO "pg_database_owner"; + +CREATE OR REPLACE FUNCTION "public"."get_buildings_in_scenario"(id bigint) RETURNS bigint + LANGUAGE "plpgsql" + AS $$ +BEGIN + RETURN (SELECT building_id FROM "DemandScenarioBuilding" WHERE demand_scenario_id = id); +END; +$$; + +ALTER FUNCTION "public"."get_buildings_in_scenario"(id bigint) OWNER TO "postgres"; + +CREATE OR REPLACE FUNCTION "public"."get_demand_scenario_id"(building_simulation_result_id bigint) RETURNS bigint + LANGUAGE "plpgsql" + AS $$ +BEGIN + RETURN (SELECT demand_scenario_id FROM "DemandScenarioBuilding" WHERE id = building_simulation_result_id); +END; +$$; + +ALTER FUNCTION "public"."get_demand_scenario_id"(building_simulation_result_id bigint) OWNER TO "postgres"; + +SET default_tablespace = ''; + +SET default_table_access_method = "heap"; + +CREATE TABLE IF NOT EXISTS "public"."Building" ( + "id" bigint NOT NULL, + "name" text, + "gfa" real, + "building_number" text, + "group_level_1" text, + "usage" text, + "height" real, + "year" smallint +); + +ALTER TABLE "public"."Building" OWNER TO "postgres"; + +CREATE TABLE IF NOT EXISTS "public"."BuildingSimulationResult" ( + "id" bigint NOT NULL, + "heating" extensions.vector(8760), + "cooling" extensions.vector(8760), + "lighting" extensions.vector(8760), + "equipment" extensions.vector(8760), + "fans" extensions.vector(8760), + "pumps" extensions.vector(8760), + "misc" extensions.vector(8760), + "water" extensions.vector(8760) +); + +ALTER TABLE "public"."BuildingSimulationResult" OWNER TO "postgres"; + +ALTER TABLE "public"."Building" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."Building_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +CREATE TABLE IF NOT EXISTS "public"."DemandScenario" ( + "id" bigint NOT NULL, + "name" text +); + +ALTER TABLE "public"."DemandScenario" OWNER TO "postgres"; + +CREATE TABLE IF NOT EXISTS "public"."DemandScenarioBuilding" ( + "id" bigint NOT NULL, + "building_id" bigint, + "design_vector_id" bigint, + "demand_scenario_id" bigint +); + +ALTER TABLE "public"."DemandScenarioBuilding" OWNER TO "postgres"; + +ALTER TABLE "public"."DemandScenarioBuilding" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."DemandScenarioBuilding_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +ALTER TABLE "public"."DemandScenario" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."DemandScenario_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +CREATE TABLE IF NOT EXISTS "public"."DesignVector" ( + "id" bigint NOT NULL, + "name" text +); + +ALTER TABLE "public"."DesignVector" OWNER TO "postgres"; + +ALTER TABLE "public"."DesignVector" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."DesignVector_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +CREATE TABLE IF NOT EXISTS "public"."PowerPlant" ( + "id" bigint NOT NULL, + "name" text, + "nominal_capacity" real, + "nominal_cost" real, + "nominal_emissions_factor" real +); + +ALTER TABLE "public"."PowerPlant" OWNER TO "postgres"; + +CREATE TABLE IF NOT EXISTS "public"."PowerPlantScenario" ( + "id" bigint NOT NULL, + "power_plant_id" bigint, + "name" text, + "emissions_factors" extensions.vector(8760), + "cost_factors" extensions.vector(8760), + "capacities" extensions.vector(8760) +); + +ALTER TABLE "public"."PowerPlantScenario" OWNER TO "postgres"; + +ALTER TABLE "public"."PowerPlantScenario" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."PowerPlantScenario_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +ALTER TABLE "public"."PowerPlant" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."PowerPlant_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +CREATE TABLE IF NOT EXISTS "public"."SupplyScenario" ( + "id" bigint NOT NULL, + "name" text +); + +ALTER TABLE "public"."SupplyScenario" OWNER TO "postgres"; + +CREATE TABLE IF NOT EXISTS "public"."SupplyScenarioPlant" ( + "id" bigint NOT NULL, + "plant_scenario_id" bigint, + "supply_scenario_id" bigint +); + +ALTER TABLE "public"."SupplyScenarioPlant" OWNER TO "postgres"; + +ALTER TABLE "public"."SupplyScenarioPlant" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."SupplyScenarioPlant_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +ALTER TABLE "public"."SupplyScenario" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."SupplyScenario_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + +ALTER TABLE ONLY "public"."BuildingSimulationResult" + ADD CONSTRAINT "BuildingSimulationResult_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."Building" + ADD CONSTRAINT "Building_building_number_key" UNIQUE ("building_number"); + +ALTER TABLE ONLY "public"."Building" + ADD CONSTRAINT "Building_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."DemandScenarioBuilding" + ADD CONSTRAINT "DemandScenarioBuilding_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."DemandScenario" + ADD CONSTRAINT "DemandScenario_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."DesignVector" + ADD CONSTRAINT "DesignVector_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."PowerPlantScenario" + ADD CONSTRAINT "PowerPlantScenario_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."PowerPlant" + ADD CONSTRAINT "PowerPlant_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."SupplyScenarioPlant" + ADD CONSTRAINT "SupplyScenarioPlant_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."SupplyScenario" + ADD CONSTRAINT "SupplyScenario_pkey" PRIMARY KEY ("id"); + +ALTER TABLE ONLY "public"."DemandScenarioBuilding" + ADD CONSTRAINT "unique_building_demand_scenario_combination" UNIQUE ("building_id", "demand_scenario_id"); + +ALTER TABLE ONLY "public"."BuildingSimulationResult" + ADD CONSTRAINT "BuildingSimulationResult_id_fkey" FOREIGN KEY (id) REFERENCES public."DemandScenarioBuilding"(id); + +ALTER TABLE ONLY "public"."DemandScenarioBuilding" + ADD CONSTRAINT "DemandScenarioBuilding_building_id_fkey" FOREIGN KEY (building_id) REFERENCES public."Building"(id); + +ALTER TABLE ONLY "public"."DemandScenarioBuilding" + ADD CONSTRAINT "DemandScenarioBuilding_demand_scenario_id_fkey" FOREIGN KEY (demand_scenario_id) REFERENCES public."DemandScenario"(id); + +ALTER TABLE ONLY "public"."DemandScenarioBuilding" + ADD CONSTRAINT "DemandScenarioBuilding_design_vector_id_fkey" FOREIGN KEY (design_vector_id) REFERENCES public."DesignVector"(id); + +ALTER TABLE ONLY "public"."PowerPlantScenario" + ADD CONSTRAINT "PowerPlantScenario_power_plant_id_fkey" FOREIGN KEY (power_plant_id) REFERENCES public."PowerPlant"(id); + +ALTER TABLE ONLY "public"."SupplyScenarioPlant" + ADD CONSTRAINT "SupplyScenarioPlant_plant_scenario_id_fkey" FOREIGN KEY (plant_scenario_id) REFERENCES public."PowerPlantScenario"(id); + +ALTER TABLE ONLY "public"."SupplyScenarioPlant" + ADD CONSTRAINT "SupplyScenarioPlant_supply_scenario_id_fkey" FOREIGN KEY (supply_scenario_id) REFERENCES public."SupplyScenario"(id); + +ALTER TABLE "public"."Building" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."BuildingSimulationResult" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."DemandScenario" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."DemandScenarioBuilding" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."DesignVector" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."PowerPlant" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."PowerPlantScenario" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."SupplyScenario" ENABLE ROW LEVEL SECURITY; + +ALTER TABLE "public"."SupplyScenarioPlant" ENABLE ROW LEVEL SECURITY; + +GRANT USAGE ON SCHEMA "public" TO "postgres"; +GRANT USAGE ON SCHEMA "public" TO "anon"; +GRANT USAGE ON SCHEMA "public" TO "authenticated"; +GRANT USAGE ON SCHEMA "public" TO "service_role"; + +GRANT ALL ON FUNCTION "public"."get_buildings_in_scenario"(id bigint) TO "anon"; +GRANT ALL ON FUNCTION "public"."get_buildings_in_scenario"(id bigint) TO "authenticated"; +GRANT ALL ON FUNCTION "public"."get_buildings_in_scenario"(id bigint) TO "service_role"; + +GRANT ALL ON FUNCTION "public"."get_demand_scenario_id"(building_simulation_result_id bigint) TO "anon"; +GRANT ALL ON FUNCTION "public"."get_demand_scenario_id"(building_simulation_result_id bigint) TO "authenticated"; +GRANT ALL ON FUNCTION "public"."get_demand_scenario_id"(building_simulation_result_id bigint) TO "service_role"; + +GRANT ALL ON TABLE "public"."Building" TO "anon"; +GRANT ALL ON TABLE "public"."Building" TO "authenticated"; +GRANT ALL ON TABLE "public"."Building" TO "service_role"; + +GRANT ALL ON TABLE "public"."BuildingSimulationResult" TO "anon"; +GRANT ALL ON TABLE "public"."BuildingSimulationResult" TO "authenticated"; +GRANT ALL ON TABLE "public"."BuildingSimulationResult" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."Building_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."Building_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."Building_id_seq" TO "service_role"; + +GRANT ALL ON TABLE "public"."DemandScenario" TO "anon"; +GRANT ALL ON TABLE "public"."DemandScenario" TO "authenticated"; +GRANT ALL ON TABLE "public"."DemandScenario" TO "service_role"; + +GRANT ALL ON TABLE "public"."DemandScenarioBuilding" TO "anon"; +GRANT ALL ON TABLE "public"."DemandScenarioBuilding" TO "authenticated"; +GRANT ALL ON TABLE "public"."DemandScenarioBuilding" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."DemandScenarioBuilding_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."DemandScenarioBuilding_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."DemandScenarioBuilding_id_seq" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."DemandScenario_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."DemandScenario_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."DemandScenario_id_seq" TO "service_role"; + +GRANT ALL ON TABLE "public"."DesignVector" TO "anon"; +GRANT ALL ON TABLE "public"."DesignVector" TO "authenticated"; +GRANT ALL ON TABLE "public"."DesignVector" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."DesignVector_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."DesignVector_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."DesignVector_id_seq" TO "service_role"; + +GRANT ALL ON TABLE "public"."PowerPlant" TO "anon"; +GRANT ALL ON TABLE "public"."PowerPlant" TO "authenticated"; +GRANT ALL ON TABLE "public"."PowerPlant" TO "service_role"; + +GRANT ALL ON TABLE "public"."PowerPlantScenario" TO "anon"; +GRANT ALL ON TABLE "public"."PowerPlantScenario" TO "authenticated"; +GRANT ALL ON TABLE "public"."PowerPlantScenario" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."PowerPlantScenario_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."PowerPlantScenario_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."PowerPlantScenario_id_seq" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."PowerPlant_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."PowerPlant_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."PowerPlant_id_seq" TO "service_role"; + +GRANT ALL ON TABLE "public"."SupplyScenario" TO "anon"; +GRANT ALL ON TABLE "public"."SupplyScenario" TO "authenticated"; +GRANT ALL ON TABLE "public"."SupplyScenario" TO "service_role"; + +GRANT ALL ON TABLE "public"."SupplyScenarioPlant" TO "anon"; +GRANT ALL ON TABLE "public"."SupplyScenarioPlant" TO "authenticated"; +GRANT ALL ON TABLE "public"."SupplyScenarioPlant" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."SupplyScenarioPlant_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."SupplyScenarioPlant_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."SupplyScenarioPlant_id_seq" TO "service_role"; + +GRANT ALL ON SEQUENCE "public"."SupplyScenario_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."SupplyScenario_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."SupplyScenario_id_seq" TO "service_role"; + +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "postgres"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "anon"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "authenticated"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "service_role"; + +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "postgres"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "anon"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "authenticated"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "service_role"; + +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "postgres"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "anon"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "authenticated"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "service_role"; + +RESET ALL; diff --git a/supabase/migrations/20240212191502_add_description_cols.sql b/supabase/migrations/20240212191502_add_description_cols.sql new file mode 100644 index 0000000..16b0a94 --- /dev/null +++ b/supabase/migrations/20240212191502_add_description_cols.sql @@ -0,0 +1,5 @@ +alter table "public"."DemandScenario" add column "description" text; + +alter table "public"."PowerPlant" add column "description" text; + + diff --git a/supabase/migrations/20240212193422_add_year_available.sql b/supabase/migrations/20240212193422_add_year_available.sql new file mode 100644 index 0000000..3dccfe0 --- /dev/null +++ b/supabase/migrations/20240212193422_add_year_available.sql @@ -0,0 +1,13 @@ +alter table "public"."DemandScenario" add column "year_available" smallint; + +alter table "public"."PowerPlantScenario" add column "year_available" smallint; + +alter table "public"."DemandScenario" add constraint "DemandScenario_year_available_check" CHECK ((year_available > 2023)) not valid; + +alter table "public"."DemandScenario" validate constraint "DemandScenario_year_available_check"; + +alter table "public"."PowerPlantScenario" add constraint "PowerPlantScenario_year_available_check" CHECK ((year_available > 2023)) not valid; + +alter table "public"."PowerPlantScenario" validate constraint "PowerPlantScenario_year_available_check"; + + diff --git a/supabase/migrations/20240212195858_add_desc_to_pp_scenario.sql b/supabase/migrations/20240212195858_add_desc_to_pp_scenario.sql new file mode 100644 index 0000000..fe833e7 --- /dev/null +++ b/supabase/migrations/20240212195858_add_desc_to_pp_scenario.sql @@ -0,0 +1,3 @@ +alter table "public"."PowerPlantScenario" add column "description" text; + + diff --git a/supabase/seed.sql b/supabase/seed.sql new file mode 100644 index 0000000..e69de29