Indicators are built as subclasses of the :class”brix.Indicator class, with three functions that need to be defined: brix.Indicator.setup(), brix.Indicator.load_module(), and brix.Indicator.return_indicator(). The function brix.Indicator.setup() acts like an init. It can take any argument and runs when the object is instantiated. The function brix.Indicator.load_module() is also run when the indicator in initialized, but it cannot take any arguments. Any inputs needed to run brix.Indicator.load_module() should be passed to brix.Indicator.setup() and defined as class attributes. The function brix.Indicator.return_indicator() is the only required one and should take in a geogrid_data object (returned from brix.Handler.get_geogrid_data() or from brix.Indicator.get_geogrid_data()) and return the value of the indicator either as a number, a dictionary, or a list of dictionaries/numbers. Sometimes, the indicator requires geographic information from the table to calculate it. To get geographic information from the table, set the property brix.Indicator.requires_geometry to True (see Noise heatmap as an example).
-
The following example implements a diversity-of-land-use indicator
-
from brix import Indicator from brix import Handler from numpy import log from collections import Counter class Diversity(Indicator): def setup(self): self.name = 'Entropy' def load_module(self): pass def return_indicator(self, geogrid_data): uses = [cell['land_use'] for cell in geogrid_data] uses = [use for use in uses if use != 'None'] frequencies = Counter(uses) total = sum(frequencies.values(), 0.0) entropy = 0 for key in frequencies: p = frequencies[key]/total entropy += -p*log(p) return entropy div = Diversity() H = Handler('dungeonmaster', quietly=False) H.add_indicator(div) H.listen()
In some settings, it might be useful to aggregate different indicators to get a average feel of what the neighborhood looks like. For this use case, brix provides a simplified CompositeIndicator class that only needs an aggregation function.
-
Let’s create an indicator that averages Innovation Potential, Mobility Inmpact, and Economic Impact. We use the brix.CompositeIndicator class for this. This class takes an aggregate function as input. This function should take the result of brix.Handler.get_indicator_values() as input and returns a number. If you want to have more control over what the brix.CompositeIndicator does you can always extend the class.
-
Here is the simplest example that averages the values of three indicators:
-
from brix import Handler, CompositeIndicator from brix.examples import RandomIndicator def innovation_average(indicator_values): avg = (indicator_values['Innovation Potential']+indicator_values['Mobility Impact']+indicator_values['Economic Impact'])/3 return avg H = Handler('dungeonmaster') R = RandomIndicator() avg_I = CompositeIndicator(innovation_average,name='Composite') H.add_indicators([R,avg_I])
-
In some cases, the aggregation function is too simple to write it again. In the example before, you can also pass it a pre-existing function, such as np.mean, making sure that you select the indicators that will be passed as input, by their name.
-
from brix import Handler, CompositeIndicator from brix.examples import RandomIndicator import numpy as np H = Handler('dungeonmaster') R = RandomIndicator() avg_I = CompositeIndicator(np.mean,selected_indicators=['Innovation Potential','Mobility Impact','Economic Impact'],name='Composite') H.add_indicators([R,avg_I])
The same class can be used to define a heatmap or accessiblity indicator, as opposed to a numeric indicator. First, set the class property brix.Indicator.indicator_type equal to heatmap or to access. This will flag the indicator as a heatmap and will tell the Handler class what to do with it.
-Second, make sure that the brix.Indicator.return_indicator() function returns a list of features or a geojson.
-The example below shows an indicator that returns noise for every point in the center of a grid cell. Because this indicator needs the coordinates of table to return the geojson, it sets the property brix.Indicator.requires_geometry to True.
-
from brix import Indicator class Noise(Indicator): ''' Example of Noise heatmap indicator for points centered in each grid cell. Note that this class requires the geometry of the table as input, which is why it sets: requires_geometry = True in the setup. ''' def setup(self): self.indicator_type = 'heatmap' self.requires_geometry = True def load_module(self): pass def return_indicator(self, geogrid_data): features = [] for cell in geogrid_data: feature = {} lat,lon = zip(*cell['geometry']['coordinates'][0]) lat,lon = mean(lat),mean(lon) feature['geometry'] = {'coordinates': [lat,lon],'type': 'Point'} feature['properties'] = {self.name:random()} features.append(feature) out = {'type':'FeatureCollection','features':features} return out
The example below annotates two randomly chosen cells with yes! and no!.
-
from brix import Indicator import random class RandomFlag(Indicator): ''' Example of textual indicator that annotates two random cells. ''' def setup(self): self.indicator_type = 'textual' self.requires_geometry = True self.name = 'Yes/No' def return_indicator(self, geogrid_data): cells = random.sample(geogrid_data,2) out = [ {'id':cells[0]['id'],'info':'yes!'}, {'id':cells[1]['id'],'info':'no!'}, ] return out
The following examples instantiates three brix.Handler objects for three different tables (dungeonA, dungeonB, and dungeonC) and adds a diversity of land use indicator to each. It then runs brix.Handler.listen() for each table in its own separate thread.
-
from brix import Handler from brix.examples import Diversity, RandomIndicator table_list = ['dungeona','dungeonb','dungeonc'] handler_list = [] for table_name in table_list: H = Handler(table_name) div = Diversity() rand = RandomIndicator() H.add_indicators([div,rand]) handler_list.append(H) for h in handler_list: h.listen()
For more complex uses cases, where a module runs a big simulation and wants to show both a heatmap and a numeric indicator, you can use a hybrid indicator. To start, set:
-
self.indicator_type = 'hybrid'
-
If you set your indicator as hybrid you need to define a numeric and a heatmap part. The following example generates a heatmap with noise and the average noise as a numeric indicator.
-
from brix import Indicator from numpy import mean import random class HybridNoise(Indicator): def setup(self): self.indicator_type = 'hybrid' self.name = 'noise' self.requires_geometry = True self.mynoise = None def return_indicator_heatmap(self, geogrid_data): features = [] for cell in geogrid_data: feature = {} lat,lon = zip(*cell['geometry']['coordinates'][0]) lat,lon = mean(lat),mean(lon) feature['geometry'] = {'coordinates': [lat,lon],'type': 'Point'} feature['properties'] = {self.name:random.random()} features.append(feature) self.mynoise = features out = {'type':'FeatureCollection','features':features} return out def return_indicator_numeric(self, geogrid_data): mean_noise = mean([cell['properties'][self.name] for cell in self.mynoise]) return mean_noise
-
By default, brix will run the heatmap indicator first, followed by the numeric indicator. If you need more control over how these functions interact with each other, you can always re-define the return_indicator function. If you choose to do so, make sure that it returns a dictionary with two keys (‘heatmap’ and ‘numeric’):
As an example, we’ll build a diversity of land use indicator for the test table. The process is the same for any table, provided that it has a GEOGRID variable. Indicators are built as subclasses of the brix.Indicator class, with three functions that need to be defined: brix.Indicator.setup(), brix.Indicator.load_module(), and brix.Indicator.return_indicator(). The function brix.Indicator.setup() acts like an init. It can take any argument and runs when the object is instantiated. The function brix.Indicator.load_module() is also run when the indicator in initialized, but it cannot take any arguments. Any inputs needed to run brix.Indicator.load_module() should be passed to brix.Indicator.setup() and defined as class attributes. The function brix.Indicator.return_indicator() is the only required one and should take in a geogrid_data object (returned from brix.Handler.get_geogrid_data() or from brix.Indicator.get_geogrid_data()) and return the value of the indicator either as a number, a dictionary, or a list of dictionaries/numbers.
-
To start developing the diversity indicator, you can use the Handler class to get the geogrid_data that is an input of the brix.Indicator.return_indicator() function.
-
from brix import Handler H = Handler('dungeonmaster') geogrid_data = H.geogrid_data()
-
The returned geogrid_data object depends on the table, but for dungeonmaster it looks like this:
We build the diversity indicator by delecting the land_use variable in each cell and calculating the Shannon Entropy for this:
-
from numpy import log from collections import Counter uses = [cell['land_use'] for cell in geogrid_data] uses = [use for use in uses if use != 'None'] frequencies = Counter(uses) total = sum(frequencies.values(), 0.0) entropy = 0 for key in frequencies: p = frequencies[key]/total entropy += -p*log(p)
-
Now, we wrap this calculation in the brix.Indicator.return_indicator() in a Diversity class that inherits the properties from the brix.Indicator class:
-
from brix import Indicator from numpy import log from collections import Counter class Diversity(Indicator): def setup(self): self.name = 'Entropy' def load_module(self): pass def return_indicator(self, geogrid_data): uses = [cell['land_use'] for cell in geogrid_data] uses = [use for use in uses if use != 'None'] frequencies = Counter(uses) total = sum(frequencies.values(), 0.0) entropy = 0 for key in frequencies: p = frequencies[key]/total entropy += -p*log(p) return entropy
-
Because this indicator is very simple, it does not need any parameters or data to calculate the value, which is why the load_module function is empty. The setup function defines the properties of the module, which in this case is just the name.
-
Finally, we run the indicator by instantiating the new class and passing it to a Handler object:
-
from brix import Handler div = Diversity() H = Handler('dungeonmaster', quietly=False) H.add_indicator(div) H.listen()
Let’s create an indicator that averages Innovation Potential, Mobility Inmpact, and Economic Impact.
-First, we load the RandomIndicator and pass it to a Handler.
-
from brix import Handler, CompositeIndicator from brix.examples import RandomIndicator H = Handler('dungeonmaster') R = RandomIndicator() H.add_indicator(R)
-
To develop the aggregate function, we use the brix.Handler.get_indicator_values function from the handler class. We need to make sure our aggregate function works with that the Handler is returning:
-
indicator_values = H.get_indicator_values()
-
In this case, the indicator_values is a dictionary with the following elements:
We do not need to use all of the values returned by the Handler for our indicator.
-
Next, we write our simple average function that takes indicator_values as input and returns a value, and pass it as an argument to the brix.CompositeIndicator class constructor.
This section will show you step by step how to build a proximity to parks indicator.
-
Let’s start by setting up a simple subclass of the Indicator class, give it a name, and set it as a heatmap indicator:
-
from brix import Indicator class ProximityIndicator(Indicator): def setup(self): self.name = 'Parks' self.indicator_type = 'heatmap' def return_indicator(self, geogrid_data): pass
-
Next, we link it to the table. This step is only for building the indicator as we use a brix.Handler object when deploying it.
-
P = ProximityIndicator() P.link_table('dungeonmaster') P.get_geogrid_data()
-
When running brix.Indicator.get_geogrid_data() we see that every cell has a name property and some cells are classified as Park. You’ll also notice that by default, when building a heatmap indicator, geogrid_data returns the geometries. You can change this behavior by setting self.requires_geometry=False in your setup.
-
Next, we define the return_indicator function. For debugging and testing you can define this function as stand alone function before adding it as a method to the ProximityIndicator. Some useful functions for debugging are brix.Indicator.get_geogrid_data() and brix.Indicator.get_table_properties() that will list general properties of the linked table.
-
In this example, the proximity indicator is defined as one over the distance to the closest park. When the cell is a park, we define the proximity as 1/(half size of each cell) to avoid dividing by zero.
-
import numpy as np from geopy.distance import distance as geodistance # Function for distance between coordinates def return_indicator(self,geogrid_data): parks = [cell for cell in geogrid_data if cell['name']=='Park'] # Find all parks parks_locations = [np.mean(cell['geometry']['coordinates'][0],0) for cell in parks] # Filter out the center of all park locations (locations are lon,lat format) features = [] for cell in geogrid_data: # Calculate a value for the indicator for each cell cell_coords = np.mean(cell['geometry']['coordinates'][0],0) # Calculate center of cell (locations are lon,lat format) if cell['name']=='Park': # If cell is park, set distance to zero park_distance = 25 # This is based on half the cell size (see P.get_table_properties()) else: distances = [geodistance(cell_coords[::-1],park_loc[::-1]).m for park_loc in parks_locations] # Distance between cell and each park. Notice that we reverse the coordinates for geodistance. park_distance = min(distances) # get distance to closest park proximity = 1/park_distance scaled_proximity = (proximity-0.002)/(0.03-0.002) # this ensures the indicator is between zero and one # Generate feature with points (lon,lat format) and properties. feature = {} feature['geometry'] = {'coordinates': list(cell_coords),'type': 'Point'} # cell_coords should be a list feature['properties'] = {self.name: scaled_proximity} # Use the indicator name to tag the value features.append(feature) # add to features list for export out = {'type':'FeatureCollection','features':features} return out
-
You can test your function by running: return_indicator(P,geogrid_data).
-
Finally, let’s put it all together:
-
from brix import Indicator import numpy as np from geopy.distance import distance as geodistance class ProximityIndicator(Indicator): def setup(self): self.name = 'Parks' self.indicator_type = 'heatmap' def return_indicator(self,geogrid_data): parks = [cell for cell in geogrid_data if cell['name']=='Park'] parks_locations = [np.mean(cell['geometry']['coordinates'][0],0) for cell in parks] features = [] for cell in geogrid_data: cell_coords = list(np.mean(cell['geometry']['coordinates'][0],0) ) if cell['name']=='Park': park_distance = 45 else: distances = [geodistance(cell_coords[::-1],park_loc[::-1]).m for park_loc in parks_locations] park_distance = min(distances) proximity = 1/park_distance scaled_proximity = (proximity-0.002)/(0.03-0.002) feature = {} feature['geometry'] = {'coordinates': cell_coords,'type': 'Point'} feature['properties'] = {self.name: scaled_proximity} features.append(feature) out = {'type':'FeatureCollection','features':features} return out
-
And to deploy it:
-
from brix import Handler H = Handler('dungeonmaster') P = ProximityIndicator() H.add_indicator(P) H.listen()
The brix.Indicator class provides a flexible way to define any type of indicator. In some cases, a simple approach is needed. Let’s assume we want to build a simple heatmap indicator that just visualizes a given shapefile, and does not react to changes in geogriddata. We can use brix.StaticHeatmap to build that.
-
In this example, we will use the number of houses by block in Guadalajara, Mexico. You can download the shapefile from HERE. We will not be using our trusted dungeonmaster table, as it does not overlap with the data. Instead we will use jalisco.
-
The first step will be to “griddify” our shapefile, meaning we will transform it from polygons to sampling points. Please note that you can use any sampling method for this, and that the sampling points do not need to match the grid. To make things easier, we have provided brix.griddify(), which uses the centroids of the grid to sample the values of the heatmap.
-
We start by loading the shapefile and removing the missing values:
Since the VIVTOT column that we are interested in visualizing has a skewed distribution, we will log-transform it.
-
::
-
import numpy as np
-shapefile[‘log_VIVTOT’] = np.log(shapefile[‘VIVTOT’]+1)
-
Next, we load a table and use its grid to sample the heatmap.
-
from brix import Handler H = Handler('jalisco') geogrid_data = H.get_geogrid_data()
-
The next step is to use the grid to sample the values of the heatmap. We will use the log_VIVTOT column, and save the resulting heatmap to a file so we can load it later. We will also remove the missing values.
This shapefile is a table of points and their properties. To build your indicator you can either load the file and pass it to the :class:brix.StaticHeatmap` constructor, or have the constructor load it for you.
-
from brix import StaticHeatmap N = StaticHeatmap('/Users/username/Downloads/14_Manzanas_INV2016_shp/HEATMAP.shp',columns=['log_VIVTOT'])
-
Finally, we add it to a Handler class and check the update package:
-
H = Handler('jalisco') H.add_indicator(N) H.update_package()
-
To sum up, to preprocess the data:
-
import geopandas as gpd import numpy as np from brix import Handler from brix import griddify shapefile = gpd.read_file('/Users/username/Downloads/14_Manzanas_INV2016_shp/14_Manzanas_INV2016.shp') shapefile = shapefile[shapefile['VIVTOT']!='N.D.'] shapefile['VIVTOT'] = shapefile['VIVTOT'].astype(float) shapefile['log_VIVTOT'] = np.log(shapefile['VIVTOT']+1) H = Handler('jalisco') geogrid_data = H.get_geogrid_data() heatmap = griddify(geogrid_data,shapefile,columns=['log_VIVTOT'],buffer_percent=3) heatmap = heatmap[~heatmap['log_VIVTOT'].isna()] heatmap.to_file('/Users/username/Downloads/14_Manzanas_INV2016_shp/HEATMAP.shp')
-
And once the heatmap file has been saved, all you need to do deploy the indicator is:
-
from brix import Handler, StaticHeatmap N = StaticHeatmap('/Users/username/Downloads/14_Manzanas_INV2016_shp/HEATMAP.shp',columns=['log_VIVTOT']) H = Handler('jalisco') H.add_indicator(N) H.listen()
What is this library for? If you have never heard of a CityScope before, you might want to stop reading and learn about them here. CityScope is an awesome way to interact, explore, and co-create urban interventions in a way that can be accessed by multiple people with different background. If you know what they are, please keep reading.
-
What is a CityScope table? a ‘table’ is our way of describing a CityScope project. Why table then? Since historically, most CityScope instances were composed of a mesh between a physical table-top 3D model of a city, augmented with projections, software, and other interface hardware. So a table => project.
-
What is an indicator? An indicator is the result of running a module for CityScope. Indicators work by listening for updated from the CityScope table they are linked to, calculating some values by using a model, some function of the data, or a simulation, and then post the result of the calculations to CityIO to be displayed in the table.
-
What are the types of indicators you can build? Indicators can be anything that could be displayed on a CityScope table, including the supporting screens associated to it. For the purpose of this library, we distinguish three types of indicator: numeric, heatmap, simulation.
-
-
-
Numeric: Numeric indicators are just a number or set of numbers. They are usually displayed in a chart (bar chart, radar chart, etc) next to the table. The most common numeric indicator are the numbers that go in the radar plot, which display information about density, diversity, and proximity.
-
-
-
Heatmap: These indicators are geodata. They are made up of geometries (points, lines, or polygons) and properties associated to them. These indicators are displayed as layers directly on the CityScope table.
-
-
-
Agent: These type of indicators are also displayed on the table but they are the result of an agent based simulation and are therefore displayed as a dynamic layer. They change over time like a short movie.
-
-
-
Setup
-
To setup GAMABrix copy the file GAMABrix.gaml into your model directory and import it into your model. You can download GAMABrix.gaml from here Right after declaring your model, import the necessary species and functions by running:
-
import "GAMABrix.gaml"
-
This will add to global the necessary functions to communicate with CityIO and two very important species that you will use to give your agents the properties they need to also live in CityIO: cityio_numeric_indicator and cityio_agent. Additionally, it sets up a series of brix agents that will ensure your world is a copy of the world in the table you have selected.
Let’s get to it. First, what table are you building for? If you don’t have a specific table, that is totally okay and you can create one here. Note: by the time you read this, CityScope might pose some limitations on new projects (tables). Please follow instructions in the link above.
-
For this tutorial, we crated one called dungeonmaster.
-
An indicator will basically take in the properties of the brix agents in the world or the properties of any other simulated agent and produce a result. Each new indicator is built as an subclass of the cityio_agent class. cityio_agent is your friend, so we'll spend some time discussing it here.
-
When you setup a model by importing GAMABrix, the model will run for one whole day of simulation, then posts the results of this simulation to cityio, and then stay idle waiting for an update from the table. This can be a bit annoying when you are only starting to build your model, so you can turn off this behavior and just keep the local grid update.
-
Think of each indicator as an observer in your model that will report information back to CityIO. When it's a numeric indicator, the agent will just report a number that it calculates based on the brixs, when it's a heatmap indicator, the agent will report some numbers along with its location, and when it's an agent, the agent will report it's location over time. cityio_agent is used as the parent class of any species that you want to visualize in CityIO. There are some specific parameters your sub-species needs to define to set the agent as a numeric, heatmap, or agent indicator.
If you are familiar with the python library cs-brix, keep reading. Otherwise, skip to the next section of the tutorial. brix is relies on defining classes that contain functions that take geogrid_data as an input. For GAMABrix this is not necessary. Since GAMA relies on setting up a world with agents, the input data is already in the world in the form of brix. Therefore, when building urban indicators in GAMA you do not need to worry about input, and you can just get the necessary information from the brix agents that will be automatically created in your world.
-
In terms of output, brix relies on a series of return functions passed to a Handler class. In GAMA, the world itself acts as the Handler class, so there is no need to explicitly add your indicators to the Handler as they are already contained in the global species. The way to flag your indicators to be sent to cityIO is to define them as a subclass of cityio_agent.
-
While brix can handle multiple tables at the same time by creating multiple threads for each Handler, GAMA is constrained to one table per model.
To connect your world to a table you need to declare the table name inside your global and set the geometry of your world based on this table. For example, we named our table dungeonmaster:
While you are building your model, we recommend turning off GAMABrix to speed up the process (the default). By setting post_on<-false, the model will only update your local grid without posting any of the indicators to cityio. In other words, you will only be getting from cityIO not posting. This will reduce your bandwidth usage and allow you to debug your model faster. By doing this, the model will still keep track of the day and enter idle mode once the day is over.
-
For early stages of model building, you might also want to set pull_only<-true. This will tell turn off most of the functionality of the module and just make sure you are updating the local grid by pulling from your table. The simulation will not enter idle mode and the day will never reset.
-
Once you are done and want to deploy, change:
-
bool post_on<-true;
-
Additionally, the following variables can be defined in the global and allow for a finer control of how the global communicates with cityIO. You do not need to set them up now, as the default should work fine.
-
-
city_io_table: String, name of the table to connect to.
-
post_on: Boolean, used to turn the posting feature on or off. Keep it off while building the model and turn it on to post to the table.
-
update_frequency: Intenger, frequency, in number of simulation ticks, by which to update local grid by checking for changes in gridhash. This is not the posting frequency. Optional, and defaults to 10.
-
send_first_batch: Boolean, if false it will only send the results of the simulation once the full day has run. Optional and defaults to true.
-
cycle_first_batch: Integer, simulation tick in which to send the first batch of data to the server. Optional and defaults to 100.
-
step: Float, time between two simulation ticks. Defaults to 60 #sec.
-
saveLocationInterval: Float, frequency in second by which to save locally the location of agents. This is not the post frequency. Optional and defaults to 10 steps.
-
totalTimeInSec: Integer, total time in seconds that the simulation will run for. Defaults to a whole day. Please note that CityIO will not render more than 1 day of simulation.
-
idle_update_frequency: Float, time in real world seconds (not simulation seconds) between two get requests to check hash when in idle mode.
-
pull_only: Boolean, used to use GAMABrix only to update the local grid. This is very useful for the early stages of model building.
-
-
When you import GAMABrix you will also see an additional experiment called CityScopeHeadless. This experiment is used to run your model as a headless process in a server.
-
By default, GAMABrix will run its init (which creates the grid) right after your model's init. This means that you will not have access to any brix object inside your init. You can always change this behavior by forcing GAMABrix to run its init earlyer by adding do brix_init where needed.
GAMA will keep a copy of the cityIO grid locally by creating the necessary brix agents. This makes all the grid information accessible to all the agents by interacting with the brix agents.
-
The main properties that brix agents have are:
-
-
type: String that identifies the type of the block. This is editable (e.g. Residential).
-
height: Float, height of the block.
-
color: RGB object.
-
block_lbcs: map<string, float> Map that connects strings (LBCS codes) and float (proportion of the block in each code).
-
block_naics: map<string, float> Map that connects strings (NAICS codes) and float (proportion of the block in each code).
-
-
Note that block_lbcs and block_naics are the same for each type and are defined when you create the table.
Now, we'll turn some agents into observers that will report information to cityIO. All three different types of indicators report different types of information, and an agent can be reporting any type of information to cityIO.
-
-
Numeric: Reports numbers (e.g. average commuting time, total energy consumption, etc.). Turn this on by setting is_numeric<-true.
-
Heatmap: Reports numbers with location (e.g. traffic in a particular intersection, total sunlight in a specific location). Turn this on by setting is_heatmap<-true.
-
Agent: Report all their locations during one whole day of simulation. Turn this on by setting is_visible<-true. Note that the variable is_visible refers only to wether you'll see the agent in your CityScope table. You still need to display them in your local GAMA interfase if you want to see them.
-
-
When creating a numeric indicator you need to write a reflex for your agent that updates either numeric_values or heatmap_values. These two variables should be map<string,float>. Here is a simple example that numeric_values with the number of blocks.
-
reflex update_numeric { numeric_values<-[]; numeric_values<+"Number of blocks"::length(brix); }
-
Similarly, here is another example that updates heatmap_values with two layers, heat and map defined as random numbers:
For an agent indicator there is no value to be updated, as the indicator just reports its location. However, if your agent does not move, you will get a very boring dot so you might want to update the location. Here is a simple reflex that updates the location:
-
reflex move{ do wander; }
-
Additionally, GAMABrix provides a shortcut to create numeric indicators that do not require you to define a subspecies. This is meant for straightforward indicators that can be calculated in one line of code. To create a simple numeric indicator, just create and agent of the cityio_numeric_indicator species and pass your function as a string to indicator_value. For example, a numeric indicator that returns the average height of blocks:
Let's say you finished writing your model and are ready to leave it running forever (in a server with ssh access, for example).
-
We highly recommend using a docker container to run headless GAMA on a server. This will take care of compatibility issues between platforms.
-
First, pull the image from dockerhub. This step only needs to be performed once per server. We will be using this image.
-
> docker pull gamaplatform/gama
-
Second, we will build the xml file with the model meta parameters. You will only need to do this once for each model. Ensure you model directory (the folder that contains models, results, etc) contains a headless folder, and then run the following command adding the name of your gama file (model_file.gaml) where needed:
This creates a file called myHeadlessModel.xml in your headless folder. If you know how to edit this file, feel free to modify it now. For more information about this file, check the documentation. Please note that by default the simulation will only run 1000 steps. If you wish to change this, edit the xml and change the finalStep property to a higher number or just delete if you wish the model to run continuosly.
-
Finally, we will run this model inside a container. This final step is what you will repeat everytime you modify your model. Run the following command, again from your model director:
-
> docker run --rm -v "$(pwd)":/usr/lib/gama/headless/my_model gamaplatform/gama my_model/headless/myHeadlessModel.xml my_model/results/
To create a numeric indicator, the recommended way is to define a species of agents that will act as observers that will report the information to cityIO. This species needs to have cityio_agent as parent species.
-
You need to define four things:
-
-
Set is_numeric to true.
-
Define a reflex that updates the numeric_values map (map<string,float>).
-
Define an indicator_name either in the species definition or in the create statement.
-
Set the viz_type to either bar or radar (defaults to bar if you don't change it).
To create a heatmap indicator, define a species of agents that will act as observers that will report the information to cityIO. These agents need to have a location assigned to them. This species needs to have cityio_agent as parent species.
-
You need to define three things:
-
-
Set is_heatmap to true.
-
Define a reflex that updates the heatmap_values map (map<string,float>).
-
Define an indicator_name either in the species definition or in the create statement.
Finally, you can easily add agents to be displayed in cityIO. Interestingly, these are the easiest indicators to define. In fact, you can turn any species into a cityio_agent by defining their parent class.
-
You need to is_visible two things:
-
-
Set is_heatmap to true.
-
Define a reflex that updates the agent's location.
-
-
species people parent: cityio_agent skills:[moving]{ bool is_visible<-true; reflex move{ do wander; } }
-
Additionally, you can define the integers profile and mode that will control the way they are displayed in the front end. You can also define reflexes that update these two properties. For example, you can differentiate between drivers and walkers, or between day workers and night workers, etc.
model citIOGAMA // Import GAMABrix (this needs to be in the same directory as your model) import "GAMABrix.gaml" global { // Define the table you'll be working with string city_io_table<-"dungeonmaster"; geometry shape <- envelope(setup_cityio_world()); // Set post to true so that GAMABrix can post to cityIO bool post_on<-true; init { // Create people based on species defined below create people number:10; // Create 100 points of a heatmap indicator (species defined below) create thermometer number:100; // Use cityio_numeric_indicator to define a mean block height numeric indicator create cityio_numeric_indicator with: (viz_type:"bar",indicator_name: "Mean Height", indicator_value: "mean(brix collect each.height)"); // Create a numeric indicator based on the species defined below create my_numeric_indicator with: (viz_type:"bar",indicator_name: "Number of blocks"); } } // Define a custom numeric indicator species my_numeric_indicator parent: cityio_agent { // Set the indicator as numeric bool is_numeric<-true; // Visualize it as a bar chart string viz_type <- "bar"; // Define reflex that updates numeric_values reflex update_numeric { numeric_values<-[]; numeric_values<+indicator_name::length(brix); } } // Define custom heatmap indicator species thermometer parent: cityio_agent { // Set the indicator as heatmap bool is_heatmap<-true; // Define reflex that updates heatmap_values reflex update_heatmap { heatmap_values<-[]; heatmap_values<+ "heat"::rnd(10); heatmap_values<+ "map"::rnd(10); } } // Define people, to be used as agent indicators species people parent: cityio_agent skills:[moving]{ // Set agents as visible in cityIO bool is_visible<-true; // Update the agents location at every step reflex move{ do wander; } // Set base aspect to visualize in GAMA GUI aspect base{ draw circle(10) color:#blue; } } // Define a experiment to visualize in GUI experiment CityScope type: gui autorun:false{ output { display map_mode type:opengl background:#black{ species brix aspect:base; species people aspect:base position:{0,0,0.1}; } } }
Brix also has the capability of automatically updating GEOGRIDDATA. For simple one-time updates, follow the documentation of brix.Handler.update_geogrid_data(). To use this feeature, you first need to define a function that takes a brix.GEOGRIDDATA as an input. When used with brix.Handler.update_geogrid_data(), this function can take any number of keyword arguments. The following example raises the height of all cells by 3 units:
-
def add_height(geogrid_data, levels=1): for cell in geogrid_data: cell['height'] += levels return geogrid_data H = Handler('dungeonmaster', quietly=False) H.update_geogrid_data(add_height,levels=3)
-
Brix also supports GEOGRIDDATA updates everytime there is a registered user interaction in the front end. To add a function to the update schedule, use brix.Handler.add_geogrid_data_update_function(). This has the limitation that your update funcion cannot take in any arguments other. If this limitation proves too restrictive, please submit an issue and we’ll consider pushing an update.
-
The following example updates the whole grid to Light Industrial use everytime there’s a user interaction:
-
def update_g(geogrid_data): for cell in geogrid_data: cell['name'] = 'Light Industrial' return geogrid_data H = Handler(table_name,quietly=False) H.add_geogrid_data_update_function(update_g) H.listen()
-
The updates triggered by brix.Handler.listen() follow the following order:
-
-
-
get GEOGRIDDATA
-
-
-
run all GEOGRIDDATA updates using the result of 1 as input
-
-
-
get the new GEOGRIDDATA
-
-
-
update all indicators using the GEOGRIDDATA object resulting from 3
Brix provides a class for creating spatial grids for CityScope projects: brix.Grid_maker a subclass of brix.Handler.
-
For most use cases, you will create your table using the web-app editor found here. For more complex projects, you might need to create your own table from an existing dataset. For example, you might want to select the grid area using a polygon defined in a shapefile. The tools we highlight here can be use for this purpose.
-
The first step is to instantiate the class by defining the location of your table and its name. The lat,lon provided to the brix.Grid_maker constructor correspond to the top left corner of the grid (North-West).
-
from brix import Grid_maker table_name = 'dungeonmaster' lat,lon = 42.361875, -71.105713 G = Grid_maker(table_name, lat, lon)
-
If the table already exists, you can either use brix.Handler.delete_table() to delete it or wait to be prompted if you want to rewrite it. You can check if the table exists by using brix.Handler.is_table(). Please note that since brix.Grid_maker is a subclass of brix.Handler, most functions available for a brix.Handler object are also available for a brix.Grid_maker object. The table constructor also allows you to specify the cell_size, the nrows and ncols, as well as other parameters.
-
Once the grid maker object has been instatiated, we set the grid by running brix.Grid_maker.set_grid_geojson():
-
G.set_grid_geojson()
-
This will create the geojson that will be posted to CityIO to create the table. You can check the object by using brix.Grid_maker.get_grid_geojson().
-
The next step is to define the cell types that the user will be able to choose frorm. Defining the necessary types and the properties of each type is a very complex process that involves data collection and analysis as well as community engagement and simulation that is beyond the scope of this tutorial. The default table created with the Grid constructor only contains a simple type called Default. To see this, you can use brix.Grid_maker.grid_types(). If you wish to change this, you can use brix.Grid_maker.edit_types(). This function will either take a json-like object (dict of dicts) with the name of the type as the key, or a list of names of types that will be automatically completed with default values. Once the types have been defined, they can be expressed in the following way, adding as many properties as needed by your table:
The bare minimum properties that need to be defined are color, height, and interactive. If not provided, brix will assign them automatically.
-
The following line of code replaces the Default type by there other cell types callsed Type 1, Type 2, and Type 3, letting brix assign the color to each of them.
-
G.edit_types(['Type 1','Type 2','Type 3'])
-
For most applications, you will want to turn off some of the cells and make them non-interactive. Usually, this will involve a shapefile or a geojson that contains the polygon that defines the interactive part of the table. If you have a Shapely polygon stored in poly you can set the non-interactive cells by using brix.Grid_maker.set_noninteractive():
-
G.set_noninteractive(poly)
-
The final step is to commit the grid to CityIO. Use brix.Grid_maker.commit_grid():
-
G.commit_grid()
-
Putting it all together:
-
from brix import Grid_maker table_name = 'dungeonmaster' lat,lon = 42.361875, -71.105713 G = Grid_maker(table_name, lat, lon) G.set_grid_geojson() G.edit_types(['Type 1','Type 2','Type 3']) G.set_noninteractive(poly) G.commit_grid()
-
Alternatively, you can use poly as an argument to brix.grid_from_poly(). This function will calculate the location and the cell size based on the given polygon, and set the non-interactive parts. The following block of code achieves the same as the block above:
-
from brix import Grid_maker, grid_from_poly table_name = 'dungeonmaster' G = grid_from_poly(table_name, poly) G.edit_types(['Type 1','Type 2','Type 3']) G.commit_grid()
To automatically test your module, this library provides the brix.User class that simulates the behavior of a user interacting with your grid. This user runs in its own new thread to free up your main thread so that you can keep wokring on your indicator.
-
The following example consists of a brix.Handler that contains a diversity brix.Indicator that reponds to the updates of the brix.User:
-
from brix import Handler from brix.examples import Diversity from brix.test_tools import User table_name = 'dungeonmaster' U = User(table_name) H = Handler(table_name,quietly=False) div = Diversity() H.add_indicator(div) U.start_user() H.listen()
What is this library for? If you have never heard of a CityScope before, you might want to stop reading and learn about them here. CityScope is an awesome way to interact, explore, and co-create urban interventions in a way that can be accessed by multiple people with different background. If you know what they are, please keep reading.
-
What is a CityScope table? a ‘table’ is our way of describing a CityScope project. Why table then? Since historically, most CityScope instances were composed of a mesh between a physical table-top 3D model of a city, augmented with projections, software, and other interface hardware. So a table => project.
-
What is an indicator? An indicator is the result of running a module for CityScope. Indicators work by listening for updated from the CityScope table they are linked to, calculating some values by using a model, some function of the data, or a simulation, and then post the result of the calculations to CityIO to be displayed in the table.
-
What are the types of indicators you can build? Indicators can be anything that could be displayed on a CityScope table, including the supporting screens associated to it. For the purpose of this library, we distinguish three types of indicator: numeric, heatmap, simulation.
-
-
-
Numeric: Numeric indicators are just a number or set of numbers. They are usually displayed in a chart (bar chart, radar chart, etc) next to the table. The most common numeric indicator are the numbers that go in the radar plot, which display information about density, diversity, and proximity.
-
-
-
Heatmap: These indicators are geodata. They are made up of geometries (points, lines, or polygons) and properties associated to them. These indicators are displayed as layers directly on the CityScope table.
-
-
-
Simulation: These type of indicators are also displayed on the table but they are the result of an agent based simulation and are therefore displayed as a dynamic layer. They change over time like a short movie. These are not yet supported by this library.
This will build the container image to the latest version. git pull to
-update the code.
-
Running
-
The cityio container assumes that a redis instance is running in
-127.0.0.1:6379 (the default), this can be a docker container itself,
-if redis is running inside a different address or/and port, you can
-change the what is written in the DockerFile.
-
ENV REDIS_ADDR=127.0.0.1 ENV REDIS_PORT=6379
-
With that, the container can run by the following command.
-
docker run -p 8080:8080 --net=host cityio
-
the --net=host option is for the container to access the host side
-localhosts' ports, to have the container access redis.
-
This will output the logs in that session, where we usually run cityio
-in a tmux session for realtime observation. The -d option can be added
-to run in deamon mode.
-
-
\ No newline at end of file
diff --git a/build/archive/cityio/Internal_Note/index.html b/build/archive/cityio/Internal_Note/index.html
deleted file mode 100644
index 00eac13d..00000000
--- a/build/archive/cityio/Internal_Note/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-Internal_Note | Here We Build CityScope
-
-
-
-
-
cityio is using tmux's shared session for all the server admins to observe, stop, and restart the cityio instance.
-The location of this session file is /tmp/Shared, so to attach the tmux session:
-
tmux attach -S /tmp/Shared
-
To run the process, it should follow instructions written in the doc's Build.md.
-
-
\ No newline at end of file
diff --git a/build/archive/cityio/index.html b/build/archive/cityio/index.html
deleted file mode 100644
index 4c6e3519..00000000
--- a/build/archive/cityio/index.html
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
-[Archive] CityIO | Here We Build CityScope
-
-
-
-
-
text will be converted to json internally, will throw an error if it's not
-valid json. Server welcomes any valid json, but only things inside objects and grid objects
-will be used for comparison to detect uniqueness.
-
-
\ No newline at end of file
diff --git a/build/assets/.DS_Store b/build/assets/.DS_Store
deleted file mode 100644
index 3b3bf31d..00000000
Binary files a/build/assets/.DS_Store and /dev/null differ
diff --git a/build/assets/css/styles.a961cfe0.css b/build/assets/css/styles.a961cfe0.css
deleted file mode 100644
index 95b9033c..00000000
--- a/build/assets/css/styles.a961cfe0.css
+++ /dev/null
@@ -1 +0,0 @@
-.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--docusaurus-announcement-bar-height:auto;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}*{box-sizing:border-box}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.list_eTzJ article:last-child,.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_Gvgb,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_BuS1>:last-child,.cardContainer_fWXF :last-child,.collapsibleContent_i85q p:last-child,.details_lb9f>summary>p:last-child,.footer__items{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter);content:""}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:-webkit-sticky;position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;position:fixed;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;left:0;top:0;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_YfHR,.sidebarLogo_isFc,.themedComponent_mlkZ,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.lastUpdated_JAkA{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tocCollapsibleContent_vkbj a{display:block}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:-webkit-sticky;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark] .themedComponent--dark_xIcU,[data-theme=light] .themedComponent--light_NVdE,html:not([data-theme]) .themedComponent--light_NVdE{display:initial}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.iconExternalLink_nPIU{margin-left:.3rem}.dropdownNavbarItemMobile_S0Fm{cursor:pointer}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}@supports selector(:has(*)){.navbarSearchContainer_Bca1:not(:has(>*)){display:none}}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.errorBoundaryFallback_VBag{color:red;padding:.55rem}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.docMainContainer_TBSr,.docRoot_UBD9{display:flex;width:100%}.docsWrapper_hBAB{display:flex;flex:1 0 auto}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.cardContainer_fWXF{--ifm-link-color:var(--ifm-color-emphasis-800);--ifm-link-hover-color:var(--ifm-color-emphasis-700);--ifm-link-hover-decoration:none;border:1px solid var(--ifm-color-emphasis-200);box-shadow:0 1.5px 3px 0 #00000026;transition:all var(--ifm-transition-fast) ease;transition-property:border,box-shadow}.cardContainer_fWXF:hover{border-color:var(--ifm-color-primary);box-shadow:0 3px 6px 0 #0003}.cardTitle_rnsV{font-size:1.2rem}.cardDescription_PWke{font-size:.8rem}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:-webkit-sticky;position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.img_ev3q{height:auto}.admonition_xJq3{margin-bottom:1em}.admonitionHeading_Gvgb{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family)}.admonitionHeading_Gvgb:not(:last-child){margin-bottom:.3rem}.admonitionHeading_Gvgb code{text-transform:none}.admonitionIcon_Rf37{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_Rf37 svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.title_kItE{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-leading)*1.25)}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_TmdG{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.lastUpdated_JAkA{text-align:right}.tocMobile_ITEo{display:none}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:-webkit-sticky;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_i1dp,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_TmdG:focus,.expandButton_TmdG:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.navbarSearchContainer_Bca1{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_TmdG{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_i1dp{transform:rotate(180deg)}.docSidebarContainer_YfHR{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_DPk8{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_aRkj{height:100%;max-height:100vh;position:-webkit-sticky;position:sticky;top:0}.docMainContainer_TBSr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_lQrH{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_JWYK{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.docItemCol_VOVn,.generatedIndexPage_vN6x{max-width:75%!important}.list_eTzJ article:nth-last-child(-n+2){margin-bottom:0!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.docItemContainer_F8PC{padding:0 .3rem}.navbarSearchContainer_Bca1{position:absolute;right:var(--ifm-navbar-padding-horizontal)}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}}
\ No newline at end of file
diff --git a/build/assets/images/BOXEL_Scheme-d1cbf30ad7555493c80cc4206fb80c30.jpg b/build/assets/images/BOXEL_Scheme-d1cbf30ad7555493c80cc4206fb80c30.jpg
deleted file mode 100644
index 22e1d062..00000000
Binary files a/build/assets/images/BOXEL_Scheme-d1cbf30ad7555493c80cc4206fb80c30.jpg and /dev/null differ
diff --git a/build/assets/images/CityScopeJS-5c67b64921cab086329c46dfafa1715a.jpg b/build/assets/images/CityScopeJS-5c67b64921cab086329c46dfafa1715a.jpg
deleted file mode 100644
index f8e7a9cc..00000000
Binary files a/build/assets/images/CityScopeJS-5c67b64921cab086329c46dfafa1715a.jpg and /dev/null differ
diff --git a/build/assets/images/Github_CS_Organization_diagram-70db1a5f41cb44cdb42ecd86aba9d951.png b/build/assets/images/Github_CS_Organization_diagram-70db1a5f41cb44cdb42ecd86aba9d951.png
deleted file mode 100644
index 5222f49b..00000000
Binary files a/build/assets/images/Github_CS_Organization_diagram-70db1a5f41cb44cdb42ecd86aba9d951.png and /dev/null differ
diff --git a/build/assets/images/KarthikPatanjali-a839ba259d45fce91794e3a03c96804a.png b/build/assets/images/KarthikPatanjali-a839ba259d45fce91794e3a03c96804a.png
deleted file mode 100644
index 69e3f1c8..00000000
Binary files a/build/assets/images/KarthikPatanjali-a839ba259d45fce91794e3a03c96804a.png and /dev/null differ
diff --git a/build/assets/images/Type_House-98f14c2db41d983f2ef3fc933e5f6736.jpg b/build/assets/images/Type_House-98f14c2db41d983f2ef3fc933e5f6736.jpg
deleted file mode 100644
index 4cb62ab6..00000000
Binary files a/build/assets/images/Type_House-98f14c2db41d983f2ef3fc933e5f6736.jpg and /dev/null differ
diff --git a/build/assets/images/Type_Office-f695054fae45ec69f5d8b0ee3cfd46bb.jpg b/build/assets/images/Type_Office-f695054fae45ec69f5d8b0ee3cfd46bb.jpg
deleted file mode 100644
index 9750667b..00000000
Binary files a/build/assets/images/Type_Office-f695054fae45ec69f5d8b0ee3cfd46bb.jpg and /dev/null differ
diff --git a/build/assets/images/Type_Park-6de8b19ee6f1af59f0163282543d1669.jpg b/build/assets/images/Type_Park-6de8b19ee6f1af59f0163282543d1669.jpg
deleted file mode 100644
index da255b50..00000000
Binary files a/build/assets/images/Type_Park-6de8b19ee6f1af59f0163282543d1669.jpg and /dev/null differ
diff --git a/build/assets/images/Type_scheme-9fbe5b8f7e202e63d3f19aa4d5d5db10.jpg b/build/assets/images/Type_scheme-9fbe5b8f7e202e63d3f19aa4d5d5db10.jpg
deleted file mode 100644
index 22295e95..00000000
Binary files a/build/assets/images/Type_scheme-9fbe5b8f7e202e63d3f19aa4d5d5db10.jpg and /dev/null differ
diff --git a/build/assets/images/Types_examples-7e0f322f70968ac0ded9951db648ec30.jpg b/build/assets/images/Types_examples-7e0f322f70968ac0ded9951db648ec30.jpg
deleted file mode 100644
index 2b98ca4b..00000000
Binary files a/build/assets/images/Types_examples-7e0f322f70968ac0ded9951db648ec30.jpg and /dev/null differ
diff --git a/build/assets/images/arch-903c36303104dbdba881ec156abf41ea.png b/build/assets/images/arch-903c36303104dbdba881ec156abf41ea.png
deleted file mode 100644
index f0410e87..00000000
Binary files a/build/assets/images/arch-903c36303104dbdba881ec156abf41ea.png and /dev/null differ
diff --git a/build/assets/images/arielnoymanHCU-e60d82029bb9330a8bc08aaa4022b732.png b/build/assets/images/arielnoymanHCU-e60d82029bb9330a8bc08aaa4022b732.png
deleted file mode 100644
index 5e3bc9eb..00000000
Binary files a/build/assets/images/arielnoymanHCU-e60d82029bb9330a8bc08aaa4022b732.png and /dev/null differ
diff --git a/build/assets/images/brix-f6b88d38a0a50447532241c5e2b0bf6a.png b/build/assets/images/brix-f6b88d38a0a50447532241c5e2b0bf6a.png
deleted file mode 100644
index 1cca8992..00000000
Binary files a/build/assets/images/brix-f6b88d38a0a50447532241c5e2b0bf6a.png and /dev/null differ
diff --git a/build/assets/images/calc-4ff39b399a470946dcfa21d9885a2358.png b/build/assets/images/calc-4ff39b399a470946dcfa21d9885a2358.png
deleted file mode 100644
index 3d453191..00000000
Binary files a/build/assets/images/calc-4ff39b399a470946dcfa21d9885a2358.png and /dev/null differ
diff --git a/build/assets/images/cs_an-98816fb9a24173dcb29a59aa1ef5bdf3.jpg b/build/assets/images/cs_an-98816fb9a24173dcb29a59aa1ef5bdf3.jpg
deleted file mode 100644
index 97c251f9..00000000
Binary files a/build/assets/images/cs_an-98816fb9a24173dcb29a59aa1ef5bdf3.jpg and /dev/null differ
diff --git a/build/assets/images/deckgl-module-c3c9253421e0d70d9904c067e5711d7e.png b/build/assets/images/deckgl-module-c3c9253421e0d70d9904c067e5711d7e.png
deleted file mode 100644
index b4aa0899..00000000
Binary files a/build/assets/images/deckgl-module-c3c9253421e0d70d9904c067e5711d7e.png and /dev/null differ
diff --git a/build/assets/images/gridupdate-7da3e36522c4abd0df95834bf37cd0c4.png b/build/assets/images/gridupdate-7da3e36522c4abd0df95834bf37cd0c4.png
deleted file mode 100644
index b3376158..00000000
Binary files a/build/assets/images/gridupdate-7da3e36522c4abd0df95834bf37cd0c4.png and /dev/null differ
diff --git a/build/assets/images/initialcon-42240e1d4ec5ae66a2c9f36bbdff6cad.png b/build/assets/images/initialcon-42240e1d4ec5ae66a2c9f36bbdff6cad.png
deleted file mode 100644
index bea3b290..00000000
Binary files a/build/assets/images/initialcon-42240e1d4ec5ae66a2c9f36bbdff6cad.png and /dev/null differ
diff --git a/build/assets/images/initialcon-8ac3fd67ed5d459087e25d5bbd02b892.png b/build/assets/images/initialcon-8ac3fd67ed5d459087e25d5bbd02b892.png
deleted file mode 100644
index babf5513..00000000
Binary files a/build/assets/images/initialcon-8ac3fd67ed5d459087e25d5bbd02b892.png and /dev/null differ
diff --git a/build/assets/images/initialcon-d743feddd6a95b8c507e9d8d8800626d.png b/build/assets/images/initialcon-d743feddd6a95b8c507e9d8d8800626d.png
deleted file mode 100644
index 6bc5349e..00000000
Binary files a/build/assets/images/initialcon-d743feddd6a95b8c507e9d8d8800626d.png and /dev/null differ
diff --git a/build/assets/images/modulerequest-05516d0c491246f1d2e4ee17a9c22087.png b/build/assets/images/modulerequest-05516d0c491246f1d2e4ee17a9c22087.png
deleted file mode 100644
index 2f5e04d4..00000000
Binary files a/build/assets/images/modulerequest-05516d0c491246f1d2e4ee17a9c22087.png and /dev/null differ
diff --git a/build/assets/images/opening-project-a1235d80f08185e6294ea8bf78916462.png b/build/assets/images/opening-project-a1235d80f08185e6294ea8bf78916462.png
deleted file mode 100644
index 7a03fa1a..00000000
Binary files a/build/assets/images/opening-project-a1235d80f08185e6294ea8bf78916462.png and /dev/null differ
diff --git a/build/assets/images/project-view-dbe152589b18a5c4493e6b2c2f68f830.png b/build/assets/images/project-view-dbe152589b18a5c4493e6b2c2f68f830.png
deleted file mode 100644
index 7bc3a6bc..00000000
Binary files a/build/assets/images/project-view-dbe152589b18a5c4493e6b2c2f68f830.png and /dev/null differ
diff --git a/build/assets/images/scenariodeleterestore-5cb660ce6527e0d88ddd78bd78f68370.png b/build/assets/images/scenariodeleterestore-5cb660ce6527e0d88ddd78bd78f68370.png
deleted file mode 100644
index 84ebf5a2..00000000
Binary files a/build/assets/images/scenariodeleterestore-5cb660ce6527e0d88ddd78bd78f68370.png and /dev/null differ
diff --git a/build/assets/images/scenariosave-204bd25d5d39f9fb2602fb973d1370b3.png b/build/assets/images/scenariosave-204bd25d5d39f9fb2602fb973d1370b3.png
deleted file mode 100644
index 30cf5c51..00000000
Binary files a/build/assets/images/scenariosave-204bd25d5d39f9fb2602fb973d1370b3.png and /dev/null differ
diff --git a/build/assets/images/subremovalrequest-fc67d08ec2f9ff21a4a7f7ead1fd9245.png b/build/assets/images/subremovalrequest-fc67d08ec2f9ff21a4a7f7ead1fd9245.png
deleted file mode 100644
index 63f8de44..00000000
Binary files a/build/assets/images/subremovalrequest-fc67d08ec2f9ff21a4a7f7ead1fd9245.png and /dev/null differ
diff --git a/build/assets/images/subrequest-92c3c8a1abe3c94ee34328d8849c4751.png b/build/assets/images/subrequest-92c3c8a1abe3c94ee34328d8849c4751.png
deleted file mode 100644
index 427e0faf..00000000
Binary files a/build/assets/images/subrequest-92c3c8a1abe3c94ee34328d8849c4751.png and /dev/null differ
diff --git a/build/assets/images/web_ui-a8964ffa79f4bdd8f5c47db299d8e802.jpg b/build/assets/images/web_ui-a8964ffa79f4bdd8f5c47db299d8e802.jpg
deleted file mode 100644
index 93e078f6..00000000
Binary files a/build/assets/images/web_ui-a8964ffa79f4bdd8f5c47db299d8e802.jpg and /dev/null differ
diff --git a/build/assets/js/02b7a71d.f6b1c77c.js b/build/assets/js/02b7a71d.f6b1c77c.js
deleted file mode 100644
index b73e2498..00000000
--- a/build/assets/js/02b7a71d.f6b1c77c.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[123],{3386:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>d});var s=i(4848),n=i(8453);const a={sidebar_position:3},o=void 0,r={id:"cityio/CityIO - UI",title:"CityIO - UI",description:"The objective of this interface is to enable user interfaces to access information about the grids created in CityIO, as well as the Key Performance Indicators (KPIs) computed by the modules. Additionally, this interface will permit users to make changes to the grids.",source:"@site/docs/cityio/CityIO - UI.md",sourceDirName:"cityio",slug:"/cityio/CityIO - UI",permalink:"/cityio/CityIO - UI",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityio/CityIO - UI.md",tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/cityio/Architecture"},next:{title:"CityIO - Module",permalink:"/cityio/CityIO - Module"}},c={},d=[{value:"Message Flow",id:"message-flow",level:2},{value:"Initial connection",id:"initial-connection",level:2},{value:"Grid Update",id:"grid-update",level:2},{value:"Module Request",id:"module-request",level:2},{value:"Save Scenario",id:"save-scenario",level:2},{value:"Delete and Restore Scenario",id:"delete-and-restore-scenario",level:2}];function l(e){const t={code:"code",h2:"h2",img:"img",p:"p",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"The objective of this interface is to enable user interfaces to access information about the grids created in CityIO, as well as the Key Performance Indicators (KPIs) computed by the modules. Additionally, this interface will permit users to make changes to the grids."}),"\n",(0,s.jsx)(t.p,{children:"This WebSocket interface is independent of the User Interface's implementation, making it possible to utilize this WebSocket channel in CityScopeJS, Tangible User Interfaces (TUIs), and any forthcoming UI proposals."}),"\n",(0,s.jsx)(t.h2,{id:"message-flow",children:"Message Flow"}),"\n",(0,s.jsx)(t.p,{children:"The subsequent subsections detail the various data exchanges that can take place between CityIO and the User Interfaces."}),"\n",(0,s.jsx)(t.h2,{id:"initial-connection",children:"Initial connection"}),"\n",(0,s.jsxs)(t.p,{children:["When a user interface seeks to establish a connection with CityIO to send and receive information from a project, it initiates a request to ",(0,s.jsx)(t.code,{children:"/interface"}),", which will be upgraded to a WebSocket. Following this, the UI can designate the specific grid (project) it wishes to connect to, and as a result, the UI will receive the grid's data. Subsequently, the User Interface can request the list of scenarios associated with that project, as well as the list of available core modules."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Initial Connection",src:i(3714).A+"",width:"645",height:"570"})}),"\n",(0,s.jsx)(t.h2,{id:"grid-update",children:"Grid Update"}),"\n",(0,s.jsx)(t.p,{children:"When the user interface needs to update the grid at the user's request, it can transmit the updated GEOGRIDDATA to CityIO via the WebSocket."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Grid Update",src:i(6061).A+"",width:"696",height:"292"})}),"\n",(0,s.jsx)(t.h2,{id:"module-request",children:"Module Request"}),"\n",(0,s.jsx)(t.p,{children:"When the user interface intends to request the connection of a module based on a user's demand, it can send a MODULE_REQUEST message to CityIO."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Module Request",src:i(223).A+"",width:"646",height:"403"})}),"\n",(0,s.jsx)(t.h2,{id:"save-scenario",children:"Save Scenario"}),"\n",(0,s.jsx)(t.p,{children:"When the user interface aims to save the current state of the project as a scenario at a user's request, it can send a SEND_SCENARIO message to CityIO, including the name of the scenario and its description."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Module Request",src:i(2203).A+"",width:"970",height:"292"})}),"\n",(0,s.jsx)(t.h2,{id:"delete-and-restore-scenario",children:"Delete and Restore Scenario"}),"\n",(0,s.jsxs)(t.p,{children:["When the user interface seeks to delete or restore a scenario based on a user's request, it can send a MODIFY_SCENARIO message, with the property ",(0,s.jsx)(t.code,{children:"isInBin"})," set to true or false, depending on whether the scenario should be placed in the bin or restored."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Module Request",src:i(7707).A+"",width:"970",height:"607"})})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},6061:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/gridupdate-7da3e36522c4abd0df95834bf37cd0c4.png"},3714:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/initialcon-8ac3fd67ed5d459087e25d5bbd02b892.png"},223:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/modulerequest-05516d0c491246f1d2e4ee17a9c22087.png"},7707:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/scenariodeleterestore-5cb660ce6527e0d88ddd78bd78f68370.png"},2203:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/scenariosave-204bd25d5d39f9fb2602fb973d1370b3.png"},8453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>r});var s=i(6540);const n={},a=s.createContext(n);function o(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/0952c0dc.0a3edaab.js b/build/assets/js/0952c0dc.0a3edaab.js
deleted file mode 100644
index 7250ed3a..00000000
--- a/build/assets/js/0952c0dc.0a3edaab.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[157],{1966:s=>{s.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/0a23f7ce.71fabafa.js b/build/assets/js/0a23f7ce.71fabafa.js
deleted file mode 100644
index 1740e330..00000000
--- a/build/assets/js/0a23f7ce.71fabafa.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[394],{4455:t=>{t.exports=JSON.parse('{"title":"CityIO","slug":"/category/cityio","permalink":"/category/cityio","navigation":{"previous":{"title":"Types System","permalink":"/modules/Types System"},"next":{"title":"Introduction","permalink":"/cityio/Introduction"}}}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/1438b9ab.7f17a523.js b/build/assets/js/1438b9ab.7f17a523.js
deleted file mode 100644
index 7676b456..00000000
--- a/build/assets/js/1438b9ab.7f17a523.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[735],{6292:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>d});var n=i(4848),r=i(8453);const o={id:"Tutorial"},a="Tutorials",s={id:"archive/brix/Tutorial/Tutorial",title:"Tutorials",description:"This module also contains a set of other useful functions that integrate with brix.Handler and brix.Indicator.",source:"@site/docs/archive/brix/Tutorial/Tutorial.md",sourceDirName:"archive/brix/Tutorial",slug:"/archive/brix/Tutorial/",permalink:"/archive/brix/Tutorial/",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/brix/Tutorial/Tutorial.md",tags:[],version:"current",frontMatter:{id:"Tutorial"},sidebar:"sidebar",previous:{title:"GAMA",permalink:"/archive/brix/GAMA"},next:{title:"[Archive] CityIO",permalink:"/archive/cityio/"}},l={},d=[{value:"Auto-updates of GEOGRIDDATA",id:"auto-updates-of-geogriddata",level:2},{value:"Creating a table from python",id:"creating-a-table-from-python",level:2},{value:"Testing your module",id:"testing-your-module",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"tutorials",children:"Tutorials"}),"\n",(0,n.jsxs)(t.p,{children:["This module also contains a set of other useful functions that integrate with ",(0,n.jsx)(t.code,{children:"brix.Handler"})," and ",(0,n.jsx)(t.code,{children:"brix.Indicator"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["The functions ",(0,n.jsx)(t.code,{children:"brix.get_OSM_geometries()"})," and ",(0,n.jsx)(t.code,{children:"brix.get_OSM_nodes()"})," help you get data from Open Street Maps for your table."]}),"\n",(0,n.jsx)(t.h2,{id:"auto-updates-of-geogriddata",children:"Auto-updates of GEOGRIDDATA"}),"\n",(0,n.jsxs)(t.p,{children:["Brix also has the capability of automatically updating GEOGRIDDATA. For simple one-time updates, follow the documentation of ",(0,n.jsx)(t.code,{children:"brix.Handler.update_geogrid_data()"}),". To use this feeature, you first need to define a function that takes a ",(0,n.jsx)(t.code,{children:"brix.GEOGRIDDATA"})," as an input. When used with ",(0,n.jsx)(t.code,{children:"brix.Handler.update_geogrid_data()"}),", this function can take any number of keyword arguments. The following example raises the height of all cells by 3 units:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"def add_height(geogrid_data, levels=1):\n for cell in geogrid_data:\n cell['height'] += levels\n return geogrid_data\n\nH = Handler('dungeonmaster', quietly=False)\nH.update_geogrid_data(add_height,levels=3)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Brix also supports GEOGRIDDATA updates everytime there is a registered user interaction in the front end. To add a function to the update schedule, use ",(0,n.jsx)(t.code,{children:"brix.Handler.add_geogrid_data_update_function()"}),". This has the limitation that your update funcion cannot take in any arguments other. If this limitation proves too restrictive, please submit an issue and we\u2019ll consider pushing an update."]}),"\n",(0,n.jsx)(t.p,{children:"The following example updates the whole grid to Light Industrial use everytime there\u2019s a user interaction:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"def update_g(geogrid_data):\n for cell in geogrid_data:\n cell['name'] = 'Light Industrial'\n return geogrid_data\n\nH = Handler(table_name,quietly=False)\nH.add_geogrid_data_update_function(update_g)\nH.listen()\n"})}),"\n",(0,n.jsxs)(t.p,{children:["The updates triggered by ",(0,n.jsx)(t.code,{children:"brix.Handler.listen()"})," follow the following order:"]}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"get GEOGRIDDATA"}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"run all GEOGRIDDATA updates using the result of 1 as input"}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"get the new GEOGRIDDATA"}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"update all indicators using the GEOGRIDDATA object resulting from 3"}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"creating-a-table-from-python",children:"Creating a table from python"}),"\n",(0,n.jsxs)(t.p,{children:["Brix provides a class for creating spatial grids for CityScope projects: ",(0,n.jsx)(t.code,{children:"brix.Grid_maker"})," a subclass of ",(0,n.jsx)(t.code,{children:"brix.Handler"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["For most use cases, you will create your table using the web-app editor found ",(0,n.jsx)(t.a,{href:"https://cityscope.media.mit.edu/CS_cityscopeJS/#/editor",children:"here"}),". For more complex projects, you might need to create your own table from an existing dataset. For example, you might want to select the grid area using a polygon defined in a shapefile. The tools we highlight here can be use for this purpose."]}),"\n",(0,n.jsxs)(t.p,{children:["The first step is to instantiate the class by defining the location of your table and its name. The lat,lon provided to the ",(0,n.jsx)(t.code,{children:"brix.Grid_maker"})," constructor correspond to the top left corner of the grid (North-West)."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"from brix import Grid_maker\ntable_name = 'dungeonmaster'\nlat,lon = 42.361875, -71.105713\nG = Grid_maker(table_name, lat, lon)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["If the table already exists, you can either use ",(0,n.jsx)(t.code,{children:"brix.Handler.delete_table()"})," to delete it or wait to be prompted if you want to rewrite it. You can check if the table exists by using ",(0,n.jsx)(t.code,{children:"brix.Handler.is_table()"}),". Please note that since ",(0,n.jsx)(t.code,{children:"brix.Grid_maker"})," is a subclass of ",(0,n.jsx)(t.code,{children:"brix.Handler"}),", most functions available for a ",(0,n.jsx)(t.code,{children:"brix.Handler"})," object are also available for a ",(0,n.jsx)(t.code,{children:"brix.Grid_maker"})," object. The table constructor also allows you to specify the cell_size, the nrows and ncols, as well as other parameters."]}),"\n",(0,n.jsxs)(t.p,{children:["Once the grid maker object has been instatiated, we set the grid by running ",(0,n.jsx)(t.code,{children:"brix.Grid_maker.set_grid_geojson()"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"G.set_grid_geojson()\n"})}),"\n",(0,n.jsxs)(t.p,{children:["This will create the geojson that will be posted to CityIO to create the table. You can check the object by using ",(0,n.jsx)(t.code,{children:"brix.Grid_maker.get_grid_geojson()"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["The next step is to define the cell types that the user will be able to choose frorm. Defining the necessary types and the properties of each type is a very complex process that involves data collection and analysis as well as community engagement and simulation that is beyond the scope of this tutorial. The default table created with the Grid constructor only contains a simple type called Default. To see this, you can use ",(0,n.jsx)(t.code,{children:"brix.Grid_maker.grid_types()"}),". If you wish to change this, you can use ",(0,n.jsx)(t.code,{children:"brix.Grid_maker.edit_types()"}),". This function will either take a json-like object (dict of dicts) with the name of the type as the key, or a list of names of types that will be automatically completed with default values. Once the types have been defined, they can be expressed in the following way, adding as many properties as needed by your table:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"{\n 'Default': {\n 'color': [0, 0, 0],\n 'height': 0,\n 'interactive': 'Web',\n ...\n },\n ...\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"The bare minimum properties that need to be defined are color, height, and interactive. If not provided, brix will assign them automatically."}),"\n",(0,n.jsx)(t.p,{children:"The following line of code replaces the Default type by there other cell types callsed Type 1, Type 2, and Type 3, letting brix assign the color to each of them."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"G.edit_types(['Type 1','Type 2','Type 3'])\n"})}),"\n",(0,n.jsxs)(t.p,{children:["For most applications, you will want to turn off some of the cells and make them non-interactive. Usually, this will involve a shapefile or a geojson that contains the polygon that defines the interactive part of the table. If you have a Shapely polygon stored in poly you can set the non-interactive cells by using ",(0,n.jsx)(t.code,{children:"brix.Grid_maker.set_noninteractive()"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"G.set_noninteractive(poly)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["The final step is to commit the grid to CityIO. Use ",(0,n.jsx)(t.code,{children:"brix.Grid_maker.commit_grid()"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"G.commit_grid()\n"})}),"\n",(0,n.jsx)(t.p,{children:"Putting it all together:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"from brix import Grid_maker\ntable_name = 'dungeonmaster'\nlat,lon = 42.361875, -71.105713\nG = Grid_maker(table_name, lat, lon)\nG.set_grid_geojson()\nG.edit_types(['Type 1','Type 2','Type 3'])\nG.set_noninteractive(poly)\nG.commit_grid()\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Alternatively, you can use poly as an argument to ",(0,n.jsx)(t.code,{children:"brix.grid_from_poly()"}),". This function will calculate the location and the cell size based on the given polygon, and set the non-interactive parts. The following block of code achieves the same as the block above:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"from brix import Grid_maker, grid_from_poly\ntable_name = 'dungeonmaster'\nG = grid_from_poly(table_name, poly)\nG.edit_types(['Type 1','Type 2','Type 3'])\nG.commit_grid()\n"})}),"\n",(0,n.jsx)(t.h2,{id:"testing-your-module",children:"Testing your module"}),"\n",(0,n.jsxs)(t.p,{children:["To automatically test your module, this library provides the ",(0,n.jsx)(t.code,{children:"brix.User"})," class that simulates the behavior of a user interacting with your grid. This user runs in its own new thread to free up your main thread so that you can keep wokring on your indicator."]}),"\n",(0,n.jsxs)(t.p,{children:["The following example consists of a ",(0,n.jsx)(t.code,{children:"brix.Handler"})," that contains a diversity ",(0,n.jsx)(t.code,{children:"brix.Indicator"})," that reponds to the updates of the ",(0,n.jsx)(t.code,{children:"brix.User"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"from brix import Handler\nfrom brix.examples import Diversity\nfrom brix.test_tools import User\ntable_name = 'dungeonmaster'\nU = User(table_name)\nH = Handler(table_name,quietly=False)\ndiv = Diversity()\nH.add_indicator(div)\nU.start_user()\nH.listen()\n"})})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>s});var n=i(6540);const r={},o=n.createContext(r);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/14eb3368.9c4f08f7.js b/build/assets/js/14eb3368.9c4f08f7.js
deleted file mode 100644
index 8fda48e5..00000000
--- a/build/assets/js/14eb3368.9c4f08f7.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[969],{1243:(e,t,n)=>{n.d(t,{A:()=>g});n(6540);var s=n(4164),r=n(7559),i=n(1754),a=n(9169),l=n(8774),o=n(1312),c=n(6025),d=n(4848);function u(e){return(0,d.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,d.jsx)("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"})})}const m={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function h(){const e=(0,c.A)("/");return(0,d.jsx)("li",{className:"breadcrumbs__item",children:(0,d.jsx)(l.A,{"aria-label":(0,o.T)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e,children:(0,d.jsx)(u,{className:m.breadcrumbHomeIcon})})})}const b={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function p(e){let{children:t,href:n,isLast:s}=e;const r="breadcrumbs__link";return s?(0,d.jsx)("span",{className:r,itemProp:"name",children:t}):n?(0,d.jsx)(l.A,{className:r,href:n,itemProp:"item",children:(0,d.jsx)("span",{itemProp:"name",children:t})}):(0,d.jsx)("span",{className:r,children:t})}function x(e){let{children:t,active:n,index:r,addMicrodata:i}=e;return(0,d.jsxs)("li",{...i&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},className:(0,s.A)("breadcrumbs__item",{"breadcrumbs__item--active":n}),children:[t,(0,d.jsx)("meta",{itemProp:"position",content:String(r+1)})]})}function g(){const e=(0,i.OF)(),t=(0,a.Dt)();return e?(0,d.jsx)("nav",{className:(0,s.A)(r.G.docs.docBreadcrumbs,b.breadcrumbsContainer),"aria-label":(0,o.T)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"}),children:(0,d.jsxs)("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList",children:[t&&(0,d.jsx)(h,{}),e.map(((t,n)=>{const s=n===e.length-1,r="category"===t.type&&t.linkUnlisted?void 0:t.href;return(0,d.jsx)(x,{active:s,index:n,addMicrodata:!!r,children:(0,d.jsx)(p,{href:r,isLast:s,children:t.label})},n)}))]})}):null}},7247:(e,t,n)=>{n.r(t),n.d(t,{default:()=>V});var s=n(6540),r=n(1003),i=n(1754),a=n(6025),l=n(4164),o=n(8774),c=n(4586);const d=["zero","one","two","few","many","other"];function u(e){return d.filter((t=>e.includes(t)))}const m={locale:"en",pluralForms:u(["one","other"]),select:e=>1===e?"one":"other"};function h(){const{i18n:{currentLocale:e}}=(0,c.A)();return(0,s.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:u(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error('Failed to use Intl.PluralRules for locale "'+e+'".\nDocusaurus will fallback to the default (English) implementation.\nError: '+t.message+"\n"),m}}),[e])}function b(){const e=h();return{selectMessage:(t,n)=>function(e,t,n){const s=e.split("|");if(1===s.length)return s[0];s.length>n.pluralForms.length&&console.error("For locale="+n.locale+", a maximum of "+n.pluralForms.length+" plural forms are expected ("+n.pluralForms.join(",")+"), but the message contains "+s.length+": "+e);const r=n.select(t),i=n.pluralForms.indexOf(r);return s[Math.min(i,s.length-1)]}(n,t,e)}}var p=n(6654),x=n(1312),g=n(1107);const v={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var f=n(4848);function j(e){let{href:t,children:n}=e;return(0,f.jsx)(o.A,{href:t,className:(0,l.A)("card padding--lg",v.cardContainer),children:n})}function A(e){let{href:t,icon:n,title:s,description:r}=e;return(0,f.jsxs)(j,{href:t,children:[(0,f.jsxs)(g.A,{as:"h2",className:(0,l.A)("text--truncate",v.cardTitle),title:s,children:[n," ",s]}),r&&(0,f.jsx)("p",{className:(0,l.A)("text--truncate",v.cardDescription),title:r,children:r})]})}function N(e){var t;let{item:n}=e;const s=(0,i.Nr)(n),r=function(){const{selectMessage:e}=b();return t=>e(t,(0,x.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return s?(0,f.jsx)(A,{href:s,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:null!=(t=n.description)?t:r(n.items.length)}):null}function T(e){var t,n;let{item:s}=e;const r=(0,p.A)(s.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",a=(0,i.cC)(null!=(t=s.docId)?t:void 0);return(0,f.jsx)(A,{href:s.href,icon:r,title:s.label,description:null!=(n=s.description)?n:null==a?void 0:a.description})}function _(e){let{item:t}=e;switch(t.type){case"link":return(0,f.jsx)(T,{item:t});case"category":return(0,f.jsx)(N,{item:t});default:throw new Error("unknown item type "+JSON.stringify(t))}}function L(e){let{className:t}=e;const n=(0,i.$S)();return(0,f.jsx)(k,{items:n.items,className:t})}function k(e){const{items:t,className:n}=e;if(!t)return(0,f.jsx)(L,{...e});const s=(0,i.d1)(t);return(0,f.jsx)("section",{className:(0,l.A)("row",n),children:s.map(((e,t)=>(0,f.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,f.jsx)(_,{item:e})},t)))})}var y=n(6929),w=n(1878),I=n(4267),C=n(1243);const F={generatedIndexPage:"generatedIndexPage_vN6x",list:"list_eTzJ",title:"title_kItE"};function M(e){let{categoryGeneratedIndex:t}=e;return(0,f.jsx)(r.be,{title:t.title,description:t.description,keywords:t.keywords,image:(0,a.A)(t.image)})}function P(e){let{categoryGeneratedIndex:t}=e;const n=(0,i.$S)();return(0,f.jsxs)("div",{className:F.generatedIndexPage,children:[(0,f.jsx)(w.A,{}),(0,f.jsx)(C.A,{}),(0,f.jsx)(I.A,{}),(0,f.jsxs)("header",{children:[(0,f.jsx)(g.A,{as:"h1",className:F.title,children:t.title}),t.description&&(0,f.jsx)("p",{children:t.description})]}),(0,f.jsx)("article",{className:"margin-top--lg",children:(0,f.jsx)(k,{items:n.items,className:F.list})}),(0,f.jsx)("footer",{className:"margin-top--lg",children:(0,f.jsx)(y.A,{previous:t.navigation.previous,next:t.navigation.next})})]})}function V(e){return(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(M,{...e}),(0,f.jsx)(P,{...e})]})}},6929:(e,t,n)=>{n.d(t,{A:()=>o});n(6540);var s=n(1312),r=n(4164),i=n(8774),a=n(4848);function l(e){const{permalink:t,title:n,subLabel:s,isNext:l}=e;return(0,a.jsxs)(i.A,{className:(0,r.A)("pagination-nav__link",l?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t,children:[s&&(0,a.jsx)("div",{className:"pagination-nav__sublabel",children:s}),(0,a.jsx)("div",{className:"pagination-nav__label",children:n})]})}function o(e){const{previous:t,next:n}=e;return(0,a.jsxs)("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,s.T)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"}),children:[t&&(0,a.jsx)(l,{...t,subLabel:(0,a.jsx)(s.A,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc",children:"Previous"})}),n&&(0,a.jsx)(l,{...n,subLabel:(0,a.jsx)(s.A,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc",children:"Next"}),isNext:!0})]})}},4267:(e,t,n)=>{n.d(t,{A:()=>o});n(6540);var s=n(4164),r=n(1312),i=n(7559),a=n(2252),l=n(4848);function o(e){let{className:t}=e;const n=(0,a.r)();return n.badge?(0,l.jsx)("span",{className:(0,s.A)(t,i.G.docs.docVersionBadge,"badge badge--secondary"),children:(0,l.jsx)(r.A,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label},children:"Version: {versionLabel}"})}):null}},1878:(e,t,n)=>{n.d(t,{A:()=>x});n(6540);var s=n(4164),r=n(4586),i=n(8774),a=n(1312),l=n(4070),o=n(7559),c=n(5597),d=n(2252),u=n(4848);const m={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(a.A,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:(0,u.jsx)("b",{children:n.label})},children:"This is unreleased documentation for {siteTitle} {versionLabel} version."})},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(a.A,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:(0,u.jsx)("b",{children:n.label})},children:"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained."})}};function h(e){const t=m[e.versionMetadata.banner];return(0,u.jsx)(t,{...e})}function b(e){let{versionLabel:t,to:n,onClick:s}=e;return(0,u.jsx)(a.A,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:(0,u.jsx)("b",{children:(0,u.jsx)(i.A,{to:n,onClick:s,children:(0,u.jsx)(a.A,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label",children:"latest version"})})})},children:"For up-to-date documentation, see the {latestVersionLink} ({versionLabel})."})}function p(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:i}}=(0,r.A)(),{pluginId:a}=(0,l.vT)({failfast:!0}),{savePreferredVersionName:d}=(0,c.g1)(a),{latestDocSuggestion:m,latestVersionSuggestion:p}=(0,l.HW)(a),x=null!=m?m:(g=p).docs.find((e=>e.id===g.mainDocId));var g;return(0,u.jsxs)("div",{className:(0,s.A)(t,o.G.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert",children:[(0,u.jsx)("div",{children:(0,u.jsx)(h,{siteTitle:i,versionMetadata:n})}),(0,u.jsx)("div",{className:"margin-top--md",children:(0,u.jsx)(b,{versionLabel:p.label,to:x.path,onClick:()=>d(p.name)})})]})}function x(e){let{className:t}=e;const n=(0,d.r)();return n.banner?(0,u.jsx)(p,{className:t,versionMetadata:n}):null}}}]);
\ No newline at end of file
diff --git a/build/assets/js/17896441.917f5f3f.js b/build/assets/js/17896441.917f5f3f.js
deleted file mode 100644
index ef781226..00000000
--- a/build/assets/js/17896441.917f5f3f.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[401],{1243:(e,t,n)=>{"use strict";n.d(t,{A:()=>b});n(6540);var s=n(4164),a=n(7559),o=n(1754),i=n(9169),l=n(8774),c=n(1312),r=n(6025),d=n(4848);function u(e){return(0,d.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,d.jsx)("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"})})}const m={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function h(){const e=(0,r.A)("/");return(0,d.jsx)("li",{className:"breadcrumbs__item",children:(0,d.jsx)(l.A,{"aria-label":(0,c.T)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e,children:(0,d.jsx)(u,{className:m.breadcrumbHomeIcon})})})}const p={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function f(e){let{children:t,href:n,isLast:s}=e;const a="breadcrumbs__link";return s?(0,d.jsx)("span",{className:a,itemProp:"name",children:t}):n?(0,d.jsx)(l.A,{className:a,href:n,itemProp:"item",children:(0,d.jsx)("span",{itemProp:"name",children:t})}):(0,d.jsx)("span",{className:a,children:t})}function x(e){let{children:t,active:n,index:a,addMicrodata:o}=e;return(0,d.jsxs)("li",{...o&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},className:(0,s.A)("breadcrumbs__item",{"breadcrumbs__item--active":n}),children:[t,(0,d.jsx)("meta",{itemProp:"position",content:String(a+1)})]})}function b(){const e=(0,o.OF)(),t=(0,i.Dt)();return e?(0,d.jsx)("nav",{className:(0,s.A)(a.G.docs.docBreadcrumbs,p.breadcrumbsContainer),"aria-label":(0,c.T)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"}),children:(0,d.jsxs)("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList",children:[t&&(0,d.jsx)(h,{}),e.map(((t,n)=>{const s=n===e.length-1,a="category"===t.type&&t.linkUnlisted?void 0:t.href;return(0,d.jsx)(x,{active:s,index:n,addMicrodata:!!a,children:(0,d.jsx)(f,{href:a,isLast:s,children:t.label})},n)}))]})}):null}},6041:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>Tt});var s=n(6540),a=n(1003),o=n(9532),i=n(4848);const l=s.createContext(null);function c(e){let{children:t,content:n}=e;const a=function(e){return(0,s.useMemo)((()=>({metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc})),[e])}(n);return(0,i.jsx)(l.Provider,{value:a,children:t})}function r(){const e=(0,s.useContext)(l);if(null===e)throw new o.dV("DocProvider");return e}function d(){var e;const{metadata:t,frontMatter:n,assets:s}=r();return(0,i.jsx)(a.be,{title:t.title,description:t.description,keywords:n.keywords,image:null!=(e=s.image)?e:n.image})}var u=n(4164),m=n(4581),h=n(6929);function p(){const{metadata:e}=r();return(0,i.jsx)(h.A,{previous:e.previous,next:e.next})}var f=n(1878),x=n(4267),b=n(7559),g=n(1312),v=n(8774);const j={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function N(e){let{permalink:t,label:n,count:s}=e;return(0,i.jsxs)(v.A,{href:t,className:(0,u.A)(j.tag,s?j.tagWithCount:j.tagRegular),children:[n,s&&(0,i.jsx)("span",{children:s})]})}const A={tags:"tags_jXut",tag:"tag_QGVx"};function C(e){let{tags:t}=e;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("b",{children:(0,i.jsx)(g.A,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list",children:"Tags:"})}),(0,i.jsx)("ul",{className:(0,u.A)(A.tags,"padding--none","margin-left--sm"),children:t.map((e=>{let{label:t,permalink:n}=e;return(0,i.jsx)("li",{className:A.tag,children:(0,i.jsx)(N,{label:t,permalink:n})},n)}))})]})}const k={iconEdit:"iconEdit_Z9Sw"};function y(e){let{className:t,...n}=e;return(0,i.jsx)("svg",{fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,u.A)(k.iconEdit,t),"aria-hidden":"true",...n,children:(0,i.jsx)("g",{children:(0,i.jsx)("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})})})}function L(e){let{editUrl:t}=e;return(0,i.jsxs)(v.A,{to:t,className:b.G.common.editThisPage,children:[(0,i.jsx)(y,{}),(0,i.jsx)(g.A,{id:"theme.common.editThisPage",description:"The link label to edit the current page",children:"Edit this page"})]})}var _=n(4586);function B(e){void 0===e&&(e={});const{i18n:{currentLocale:t}}=(0,_.A)(),n=function(){const{i18n:{currentLocale:e,localeConfigs:t}}=(0,_.A)();return t[e].calendar}();return new Intl.DateTimeFormat(t,{calendar:n,...e})}function w(e){let{lastUpdatedAt:t}=e;const n=new Date(t),s=B({day:"numeric",month:"short",year:"numeric",timeZone:"UTC"}).format(n);return(0,i.jsx)(g.A,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:(0,i.jsx)("b",{children:(0,i.jsx)("time",{dateTime:n.toISOString(),itemProp:"dateModified",children:s})})},children:" on {date}"})}function T(e){let{lastUpdatedBy:t}=e;return(0,i.jsx)(g.A,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:(0,i.jsx)("b",{children:t})},children:" by {user}"})}function E(e){let{lastUpdatedAt:t,lastUpdatedBy:n}=e;return(0,i.jsxs)("span",{className:b.G.common.lastUpdated,children:[(0,i.jsx)(g.A,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t?(0,i.jsx)(w,{lastUpdatedAt:t}):"",byUser:n?(0,i.jsx)(T,{lastUpdatedBy:n}):""},children:"Last updated{atDate}{byUser}"}),!1]})}const H={lastUpdated:"lastUpdated_JAkA"};function M(e){let{className:t,editUrl:n,lastUpdatedAt:s,lastUpdatedBy:a}=e;return(0,i.jsxs)("div",{className:(0,u.A)("row",t),children:[(0,i.jsx)("div",{className:"col",children:n&&(0,i.jsx)(L,{editUrl:n})}),(0,i.jsx)("div",{className:(0,u.A)("col",H.lastUpdated),children:(s||a)&&(0,i.jsx)(E,{lastUpdatedAt:s,lastUpdatedBy:a})})]})}function I(){const{metadata:e}=r(),{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:s,tags:a}=e,o=a.length>0,l=!!(t||n||s);return o||l?(0,i.jsxs)("footer",{className:(0,u.A)(b.G.docs.docFooter,"docusaurus-mt-lg"),children:[o&&(0,i.jsx)("div",{className:(0,u.A)("row margin-top--sm",b.G.docs.docFooterTagsRow),children:(0,i.jsx)("div",{className:"col",children:(0,i.jsx)(C,{tags:a})})}),l&&(0,i.jsx)(M,{className:(0,u.A)("margin-top--sm",b.G.docs.docFooterEditMetaRow),editUrl:t,lastUpdatedAt:n,lastUpdatedBy:s})]}):null}var S=n(1422),U=n(6342);function V(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const s=n.slice(2,e.level);e.parentIndex=Math.max(...s),n[e.level]=t}));const s=[];return t.forEach((e=>{const{parentIndex:n,...a}=e;n>=0?t[n].children.push(a):s.push(a)})),s}function R(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:s}=e;return t.flatMap((e=>{const t=R({toc:e.children,minHeadingLevel:n,maxHeadingLevel:s});return function(e){return e.level>=n&&e.level<=s}(e)?[{...e,children:t}]:t}))}function z(e){const t=e.getBoundingClientRect();return t.top===t.bottom?z(e.parentNode):t}function O(e,t){var n;let{anchorTopOffset:s}=t;const a=e.find((e=>z(e).top>=s));if(a){var o;return function(e){return e.top>0&&e.bottom{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function G(e){const t=(0,s.useRef)(void 0),n=P();(0,s.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:s,linkActiveClassName:a,minHeadingLevel:o,maxHeadingLevel:i}=e;function l(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(s),l=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const s=[];for(let a=t;a<=n;a+=1)s.push("h"+a+".anchor");return Array.from(document.querySelectorAll(s.join()))}({minHeadingLevel:o,maxHeadingLevel:i}),c=O(l,{anchorTopOffset:n.current}),r=e.find((e=>c&&c.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(a),e.classList.add(a),t.current=e):e.classList.remove(a)}(e,e===r)}))}return document.addEventListener("scroll",l),document.addEventListener("resize",l),l(),()=>{document.removeEventListener("scroll",l),document.removeEventListener("resize",l)}}),[e,n])}function D(e){let{toc:t,className:n,linkClassName:s,isChild:a}=e;return t.length?(0,i.jsx)("ul",{className:a?void 0:n,children:t.map((e=>(0,i.jsxs)("li",{children:[(0,i.jsx)(v.A,{to:"#"+e.id,className:null!=s?s:void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,i.jsx)(D,{isChild:!0,toc:e.children,className:n,linkClassName:s})]},e.id)))}):null}const W=s.memo(D);function F(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:a="table-of-contents__link",linkActiveClassName:o,minHeadingLevel:l,maxHeadingLevel:c,...r}=e;const d=(0,U.p)(),u=null!=l?l:d.tableOfContents.minHeadingLevel,m=null!=c?c:d.tableOfContents.maxHeadingLevel,h=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return(0,s.useMemo)((()=>R({toc:V(t),minHeadingLevel:n,maxHeadingLevel:a})),[t,n,a])}({toc:t,minHeadingLevel:u,maxHeadingLevel:m});return G((0,s.useMemo)((()=>{if(a&&o)return{linkClassName:a,linkActiveClassName:o,minHeadingLevel:u,maxHeadingLevel:m}}),[a,o,u,m])),(0,i.jsx)(W,{toc:h,className:n,linkClassName:a,...r})}const q={tocCollapsibleButton:"tocCollapsibleButton_TO0P",tocCollapsibleButtonExpanded:"tocCollapsibleButtonExpanded_MG3E"};function Z(e){let{collapsed:t,...n}=e;return(0,i.jsx)("button",{type:"button",...n,className:(0,u.A)("clean-btn",q.tocCollapsibleButton,!t&&q.tocCollapsibleButtonExpanded,n.className),children:(0,i.jsx)(g.A,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component",children:"On this page"})})}const $={tocCollapsible:"tocCollapsible_ETCw",tocCollapsibleContent:"tocCollapsibleContent_vkbj",tocCollapsibleExpanded:"tocCollapsibleExpanded_sAul"};function J(e){let{toc:t,className:n,minHeadingLevel:s,maxHeadingLevel:a}=e;const{collapsed:o,toggleCollapsed:l}=(0,S.u)({initialState:!0});return(0,i.jsxs)("div",{className:(0,u.A)($.tocCollapsible,!o&&$.tocCollapsibleExpanded,n),children:[(0,i.jsx)(Z,{collapsed:o,onClick:l}),(0,i.jsx)(S.N,{lazy:!0,className:$.tocCollapsibleContent,collapsed:o,children:(0,i.jsx)(F,{toc:t,minHeadingLevel:s,maxHeadingLevel:a})})]})}const Y={tocMobile:"tocMobile_ITEo"};function K(){const{toc:e,frontMatter:t}=r();return(0,i.jsx)(J,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:(0,u.A)(b.G.docs.docTocMobile,Y.tocMobile)})}const Q={tableOfContents:"tableOfContents_bqdL",docItemContainer:"docItemContainer_F8PC"},X="table-of-contents__link toc-highlight",ee="table-of-contents__link--active";function te(e){let{className:t,...n}=e;return(0,i.jsx)("div",{className:(0,u.A)(Q.tableOfContents,"thin-scrollbar",t),children:(0,i.jsx)(F,{...n,linkClassName:X,linkActiveClassName:ee})})}function ne(){const{toc:e,frontMatter:t}=r();return(0,i.jsx)(te,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:b.G.docs.docTocDesktop})}var se=n(1107),ae=n(8453),oe=n(5260),ie=n(2303),le=n(5293);function ce(){const{prism:e}=(0,U.p)(),{colorMode:t}=(0,le.G)(),n=e.theme,s=e.darkTheme||n;return"dark"===t?s:n}var re=n(8426),de=n.n(re);const ue=/title=(?["'])(?.*?)\1/,me=/\{(?[\d,-]+)\}/,he={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},pe={...he,lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""},vb:{start:"['\u2018\u2019]",end:""},vbnet:{start:"(?:_\\s*)?['\u2018\u2019]",end:""},rem:{start:"[Rr][Ee][Mm]\\b",end:""},f90:{start:"!",end:""},ml:{start:"\\(\\*",end:"\\*\\)"},cobol:{start:"\\*>",end:""}},fe=Object.keys(he);function xe(e,t){const n=e.map((e=>{const{start:n,end:s}=pe[e];return"(?:"+n+"\\s*("+t.flatMap((e=>{var t,n;return[e.line,null==(t=e.block)?void 0:t.start,null==(n=e.block)?void 0:n.end].filter(Boolean)})).join("|")+")\\s*"+s+")"})).join("|");return new RegExp("^\\s*(?:"+n+")\\s*$")}function be(e,t){let n=e.replace(/\n$/,"");const{language:s,magicComments:a,metastring:o}=t;if(o&&me.test(o)){const e=o.match(me).groups.range;if(0===a.length)throw new Error("A highlight range has been given in code block's metastring (``` "+o+"), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.");const t=a[0].className,s=de()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(s),code:n}}if(void 0===s)return{lineClassNames:{},code:n};const i=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return xe(["js","jsBlock"],t);case"jsx":case"tsx":return xe(["js","jsBlock","jsx"],t);case"html":return xe(["js","jsBlock","html"],t);case"python":case"py":case"bash":return xe(["bash"],t);case"markdown":case"md":return xe(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return xe(["tex"],t);case"lua":case"haskell":case"sql":return xe(["lua"],t);case"wasm":return xe(["wasm"],t);case"vb":case"vba":case"visual-basic":return xe(["vb","rem"],t);case"vbnet":return xe(["vbnet","rem"],t);case"batch":return xe(["rem"],t);case"basic":return xe(["rem","f90"],t);case"fsharp":return xe(["js","ml"],t);case"ocaml":case"sml":return xe(["ml"],t);case"fortran":return xe(["f90"],t);case"cobol":return xe(["cobol"],t);default:return xe(fe,t)}}(s,a),l=n.split("\n"),c=Object.fromEntries(a.map((e=>[e.className,{start:0,range:""}]))),r=Object.fromEntries(a.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),u=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let h=0;hvoid 0!==e));r[t]?c[r[t]].range+=h+",":d[t]?c[d[t]].start=h:u[t]&&(c[u[t]].range+=c[u[t]].start+"-"+(h-1)+","),l.splice(h,1)}n=l.join("\n");const m={};return Object.entries(c).forEach((e=>{let[t,{range:n}]=e;de()(n).forEach((e=>{null!=m[e]||(m[e]=[]),m[e].push(t)}))})),{lineClassNames:m,code:n}}const ge={codeBlockContainer:"codeBlockContainer_Ckt0"};function ve(e){let{as:t,...n}=e;const s=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[s,a]=e;const o=t[s];o&&"string"==typeof a&&(n[o]=a)})),n}(ce());return(0,i.jsx)(t,{...n,style:s,className:(0,u.A)(n.className,ge.codeBlockContainer,b.G.common.codeBlock)})}const je={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function Ne(e){let{children:t,className:n}=e;return(0,i.jsx)(ve,{as:"pre",tabIndex:0,className:(0,u.A)(je.codeBlockStandalone,"thin-scrollbar",n),children:(0,i.jsx)("code",{className:je.codeBlockLines,children:t})})}const Ae={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Ce(e,t){const[n,a]=(0,s.useState)(),i=(0,s.useCallback)((()=>{var t;a(null==(t=e.current)?void 0:t.closest("[role=tabpanel][hidden]"))}),[e,a]);(0,s.useEffect)((()=>{i()}),[i]),function(e,t,n){void 0===n&&(n=Ae);const a=(0,o._q)(t),i=(0,o.Be)(n);(0,s.useEffect)((()=>{const t=new MutationObserver(a);return e&&t.observe(e,i),()=>t.disconnect()}),[e,a,i])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),i())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}var ke=n(1765);const ye={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function Le(e){let{line:t,classNames:n,showLineNumbers:s,getLineProps:a,getTokenProps:o}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const l=a({line:t,className:(0,u.A)(n,s&&ye.codeLine)}),c=t.map(((e,t)=>(0,i.jsx)("span",{...o({token:e,key:t})},t)));return(0,i.jsxs)("span",{...l,children:[s?(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("span",{className:ye.codeLineNumber}),(0,i.jsx)("span",{className:ye.codeLineContent,children:c})]}):c,(0,i.jsx)("br",{})]})}function _e(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})})}function Be(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}const we={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function Te(e){let{code:t,className:n}=e;const[a,o]=(0,s.useState)(!1),l=(0,s.useRef)(void 0),c=(0,s.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError("Expected parameter `text` to be a `string`, got `"+typeof e+"`.");const s=document.createElement("textarea"),a=document.activeElement;s.value=e,s.setAttribute("readonly",""),s.style.contain="strict",s.style.position="absolute",s.style.left="-9999px",s.style.fontSize="12pt";const o=document.getSelection(),i=o.rangeCount>0&&o.getRangeAt(0);n.append(s),s.select(),s.selectionStart=0,s.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}s.remove(),i&&(o.removeAllRanges(),o.addRange(i)),a&&a.focus()}(t),o(!0),l.current=window.setTimeout((()=>{o(!1)}),1e3)}),[t]);return(0,s.useEffect)((()=>()=>window.clearTimeout(l.current)),[]),(0,i.jsx)("button",{type:"button","aria-label":a?(0,g.T)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,g.T)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,g.T)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,u.A)("clean-btn",n,we.copyButton,a&&we.copyButtonCopied),onClick:c,children:(0,i.jsxs)("span",{className:we.copyButtonIcons,"aria-hidden":"true",children:[(0,i.jsx)(_e,{className:we.copyButtonIcon}),(0,i.jsx)(Be,{className:we.copyButtonSuccessIcon})]})})}function Ee(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})})}const He={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function Me(e){let{className:t,onClick:n,isEnabled:s}=e;const a=(0,g.T)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,i.jsx)("button",{type:"button",onClick:n,className:(0,u.A)("clean-btn",t,s&&He.wordWrapButtonEnabled),"aria-label":a,title:a,children:(0,i.jsx)(Ee,{className:He.wordWrapButtonIcon,"aria-hidden":"true"})})}function Ie(e){var t;let{children:n,className:a="",metastring:o,title:l,showLineNumbers:c,language:r}=e;const{prism:{defaultLanguage:d,magicComments:m}}=(0,U.p)(),h=function(e){return null==e?void 0:e.toLowerCase()}(null!=(t=null!=r?r:function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return null==t?void 0:t.replace(/language-/,"")}(a))?t:d),p=ce(),f=function(){const[e,t]=(0,s.useState)(!1),[n,a]=(0,s.useState)(!1),o=(0,s.useRef)(null),i=(0,s.useCallback)((()=>{const n=o.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[o,e]),l=(0,s.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=o.current,n=e>t||o.current.querySelector("code").hasAttribute("style");a(n)}),[o]);return Ce(o,l),(0,s.useEffect)((()=>{l()}),[e,l]),(0,s.useEffect)((()=>(window.addEventListener("resize",l,{passive:!0}),()=>{window.removeEventListener("resize",l)})),[l]),{codeBlockRef:o,isEnabled:e,isCodeScrollable:n,toggle:i}}(),x=function(e){var t,n;return null!=(t=null==e||null==(n=e.match(ue))?void 0:n.groups.title)?t:""}(o)||l,{lineClassNames:b,code:g}=be(n,{metastring:o,language:h,magicComments:m}),v=null!=c?c:function(e){return Boolean(null==e?void 0:e.includes("showLineNumbers"))}(o);return(0,i.jsxs)(ve,{as:"div",className:(0,u.A)(a,h&&!a.includes("language-"+h)&&"language-"+h),children:[x&&(0,i.jsx)("div",{className:je.codeBlockTitle,children:x}),(0,i.jsxs)("div",{className:je.codeBlockContent,children:[(0,i.jsx)(ke.f4,{theme:p,code:g,language:null!=h?h:"text",children:e=>{let{className:t,style:n,tokens:s,getLineProps:a,getTokenProps:o}=e;return(0,i.jsx)("pre",{tabIndex:0,ref:f.codeBlockRef,className:(0,u.A)(t,je.codeBlock,"thin-scrollbar"),style:n,children:(0,i.jsx)("code",{className:(0,u.A)(je.codeBlockLines,v&&je.codeBlockLinesWithNumbering),children:s.map(((e,t)=>(0,i.jsx)(Le,{line:e,getLineProps:a,getTokenProps:o,classNames:b[t],showLineNumbers:v},t)))})})}}),(0,i.jsxs)("div",{className:je.buttonGroup,children:[(f.isEnabled||f.isCodeScrollable)&&(0,i.jsx)(Me,{className:je.codeButton,onClick:()=>f.toggle(),isEnabled:f.isEnabled}),(0,i.jsx)(Te,{className:je.codeButton,code:g})]})]})]})}function Se(e){let{children:t,...n}=e;const a=(0,ie.A)(),o=function(e){return s.Children.toArray(e).some((e=>(0,s.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),l="string"==typeof o?Ie:Ne;return(0,i.jsx)(l,{...n,children:o},String(a))}function Ue(e){return(0,i.jsx)("code",{...e})}var Ve=n(3427);const Re={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function ze(e){return!!e&&("SUMMARY"===e.tagName||ze(e.parentElement))}function Oe(e,t){return!!e&&(e===t||Oe(e.parentElement,t))}function Pe(e){let{summary:t,children:n,...a}=e;(0,Ve.A)().collectAnchor(a.id);const o=(0,ie.A)(),l=(0,s.useRef)(null),{collapsed:c,setCollapsed:r}=(0,S.u)({initialState:!a.open}),[d,m]=(0,s.useState)(a.open),h=s.isValidElement(t)?t:(0,i.jsx)("summary",{children:null!=t?t:"Details"});return(0,i.jsxs)("details",{...a,ref:l,open:d,"data-collapsed":c,className:(0,u.A)(Re.details,o&&Re.isBrowser,a.className),onMouseDown:e=>{ze(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;ze(t)&&Oe(t,l.current)&&(e.preventDefault(),c?(r(!1),m(!0)):r(!0))},children:[h,(0,i.jsx)(S.N,{lazy:!1,collapsed:c,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{r(e),m(!e)},children:(0,i.jsx)("div",{className:Re.collapsibleContent,children:n})})]})}const Ge={details:"details_b_Ee"},De="alert alert--info";function We(e){let{...t}=e;return(0,i.jsx)(Pe,{...t,className:(0,u.A)(De,Ge.details,t.className)})}function Fe(e){const t=s.Children.toArray(e.children),n=t.find((e=>s.isValidElement(e)&&"summary"===e.type)),a=(0,i.jsx)(i.Fragment,{children:t.filter((e=>e!==n))});return(0,i.jsx)(We,{...e,summary:n,children:a})}function qe(e){return(0,i.jsx)(se.A,{...e})}const Ze={containsTaskList:"containsTaskList_mC6p"};function $e(e){if(void 0!==e)return(0,u.A)(e,(null==e?void 0:e.includes("contains-task-list"))&&Ze.containsTaskList)}const Je={img:"img_ev3q"};function Ye(e){var t;const{mdxAdmonitionTitle:n,rest:a}=function(e){const t=s.Children.toArray(e),n=t.find((e=>s.isValidElement(e)&&"mdxAdmonitionTitle"===e.type)),a=t.filter((e=>e!==n));return{mdxAdmonitionTitle:null==n?void 0:n.props.children,rest:a.length>0?(0,i.jsx)(i.Fragment,{children:a}):null}}(e.children),o=null!=(t=e.title)?t:n;return{...e,...o&&{title:o},children:a}}const Ke={admonition:"admonition_xJq3",admonitionHeading:"admonitionHeading_Gvgb",admonitionIcon:"admonitionIcon_Rf37",admonitionContent:"admonitionContent_BuS1"};function Qe(e){let{type:t,className:n,children:s}=e;return(0,i.jsx)("div",{className:(0,u.A)(b.G.common.admonition,b.G.common.admonitionType(t),Ke.admonition,n),children:s})}function Xe(e){let{icon:t,title:n}=e;return(0,i.jsxs)("div",{className:Ke.admonitionHeading,children:[(0,i.jsx)("span",{className:Ke.admonitionIcon,children:t}),n]})}function et(e){let{children:t}=e;return t?(0,i.jsx)("div",{className:Ke.admonitionContent,children:t}):null}function tt(e){const{type:t,icon:n,title:s,children:a,className:o}=e;return(0,i.jsxs)(Qe,{type:t,className:o,children:[(0,i.jsx)(Xe,{title:s,icon:n}),(0,i.jsx)(et,{children:a})]})}function nt(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})})}const st={icon:(0,i.jsx)(nt,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)",children:"note"})};function at(e){return(0,i.jsx)(tt,{...st,...e,className:(0,u.A)("alert alert--secondary",e.className),children:e.children})}function ot(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"})})}const it={icon:(0,i.jsx)(ot,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)",children:"tip"})};function lt(e){return(0,i.jsx)(tt,{...it,...e,className:(0,u.A)("alert alert--success",e.className),children:e.children})}function ct(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"})})}const rt={icon:(0,i.jsx)(ct,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)",children:"info"})};function dt(e){return(0,i.jsx)(tt,{...rt,...e,className:(0,u.A)("alert alert--info",e.className),children:e.children})}function ut(e){return(0,i.jsx)("svg",{viewBox:"0 0 16 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"})})}const mt={icon:(0,i.jsx)(ut,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.warning",description:"The default label used for the Warning admonition (:::warning)",children:"warning"})};function ht(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"})})}const pt={icon:(0,i.jsx)(ht,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)",children:"danger"})};const ft={icon:(0,i.jsx)(ut,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)",children:"caution"})};const xt={...{note:at,tip:lt,info:dt,warning:function(e){return(0,i.jsx)(tt,{...mt,...e,className:(0,u.A)("alert alert--warning",e.className),children:e.children})},danger:function(e){return(0,i.jsx)(tt,{...pt,...e,className:(0,u.A)("alert alert--danger",e.className),children:e.children})}},...{secondary:e=>(0,i.jsx)(at,{title:"secondary",...e}),important:e=>(0,i.jsx)(dt,{title:"important",...e}),success:e=>(0,i.jsx)(lt,{title:"success",...e}),caution:function(e){return(0,i.jsx)(tt,{...ft,...e,className:(0,u.A)("alert alert--warning",e.className),children:e.children})}}};function bt(e){const t=Ye(e),n=(s=t.type,xt[s]||(console.warn('No admonition component found for admonition type "'+s+'". Using Info as fallback.'),xt.info));var s;return(0,i.jsx)(n,{...t})}var gt=n(418);const vt={Head:oe.A,details:Fe,Details:Fe,code:function(e){return function(e){return void 0!==e.children&&s.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")))}(e)?(0,i.jsx)(Ue,{...e}):(0,i.jsx)(Se,{...e})},a:function(e){return(0,i.jsx)(v.A,{...e})},pre:function(e){return(0,i.jsx)(i.Fragment,{children:e.children})},ul:function(e){return(0,i.jsx)("ul",{...e,className:$e(e.className)})},li:function(e){return(0,Ve.A)().collectAnchor(e.id),(0,i.jsx)("li",{...e})},img:function(e){return(0,i.jsx)("img",{decoding:"async",loading:"lazy",...e,className:(t=e.className,(0,u.A)(t,Je.img))});var t},h1:e=>(0,i.jsx)(qe,{as:"h1",...e}),h2:e=>(0,i.jsx)(qe,{as:"h2",...e}),h3:e=>(0,i.jsx)(qe,{as:"h3",...e}),h4:e=>(0,i.jsx)(qe,{as:"h4",...e}),h5:e=>(0,i.jsx)(qe,{as:"h5",...e}),h6:e=>(0,i.jsx)(qe,{as:"h6",...e}),admonition:bt,mermaid:gt.A};function jt(e){let{children:t}=e;return(0,i.jsx)(ae.x,{components:vt,children:t})}function Nt(e){let{children:t}=e;const n=function(){const{metadata:e,frontMatter:t,contentTitle:n}=r();return t.hide_title||void 0!==n?null:e.title}();return(0,i.jsxs)("div",{className:(0,u.A)(b.G.docs.docMarkdown,"markdown"),children:[n&&(0,i.jsx)("header",{children:(0,i.jsx)(se.A,{as:"h1",children:n})}),(0,i.jsx)(jt,{children:t})]})}var At=n(1243);function Ct(){return(0,i.jsx)(g.A,{id:"theme.unlistedContent.title",description:"The unlisted content banner title",children:"Unlisted page"})}function kt(){return(0,i.jsx)(g.A,{id:"theme.unlistedContent.message",description:"The unlisted content banner message",children:"This page is unlisted. Search engines will not index it, and only users having a direct link can access it."})}function yt(){return(0,i.jsx)(oe.A,{children:(0,i.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})}function Lt(e){let{className:t}=e;return(0,i.jsx)(bt,{type:"caution",title:(0,i.jsx)(Ct,{}),className:(0,u.A)(t,b.G.common.unlistedBanner),children:(0,i.jsx)(kt,{})})}function _t(e){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(yt,{}),(0,i.jsx)(Lt,{...e})]})}const Bt={docItemContainer:"docItemContainer_Djhp",docItemCol:"docItemCol_VOVn"};function wt(e){let{children:t}=e;const n=function(){const{frontMatter:e,toc:t}=r(),n=(0,m.l)(),s=e.hide_table_of_contents,a=!s&&t.length>0;return{hidden:s,mobile:a?(0,i.jsx)(K,{}):void 0,desktop:!a||"desktop"!==n&&"ssr"!==n?void 0:(0,i.jsx)(ne,{})}}(),{metadata:{unlisted:s}}=r();return(0,i.jsxs)("div",{className:"row",children:[(0,i.jsxs)("div",{className:(0,u.A)("col",!n.hidden&&Bt.docItemCol),children:[s&&(0,i.jsx)(_t,{}),(0,i.jsx)(f.A,{}),(0,i.jsxs)("div",{className:Bt.docItemContainer,children:[(0,i.jsxs)("article",{children:[(0,i.jsx)(At.A,{}),(0,i.jsx)(x.A,{}),n.mobile,(0,i.jsx)(Nt,{children:t}),(0,i.jsx)(I,{})]}),(0,i.jsx)(p,{})]})]}),n.desktop&&(0,i.jsx)("div",{className:"col col--3",children:n.desktop})]})}function Tt(e){const t="docs-doc-id-"+e.content.metadata.id,n=e.content;return(0,i.jsx)(c,{content:e.content,children:(0,i.jsxs)(a.e3,{className:t,children:[(0,i.jsx)(d,{}),(0,i.jsx)(wt,{children:(0,i.jsx)(n,{})})]})})}},6929:(e,t,n)=>{"use strict";n.d(t,{A:()=>c});n(6540);var s=n(1312),a=n(4164),o=n(8774),i=n(4848);function l(e){const{permalink:t,title:n,subLabel:s,isNext:l}=e;return(0,i.jsxs)(o.A,{className:(0,a.A)("pagination-nav__link",l?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t,children:[s&&(0,i.jsx)("div",{className:"pagination-nav__sublabel",children:s}),(0,i.jsx)("div",{className:"pagination-nav__label",children:n})]})}function c(e){const{previous:t,next:n}=e;return(0,i.jsxs)("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,s.T)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"}),children:[t&&(0,i.jsx)(l,{...t,subLabel:(0,i.jsx)(s.A,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc",children:"Previous"})}),n&&(0,i.jsx)(l,{...n,subLabel:(0,i.jsx)(s.A,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc",children:"Next"}),isNext:!0})]})}},4267:(e,t,n)=>{"use strict";n.d(t,{A:()=>c});n(6540);var s=n(4164),a=n(1312),o=n(7559),i=n(2252),l=n(4848);function c(e){let{className:t}=e;const n=(0,i.r)();return n.badge?(0,l.jsx)("span",{className:(0,s.A)(t,o.G.docs.docVersionBadge,"badge badge--secondary"),children:(0,l.jsx)(a.A,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label},children:"Version: {versionLabel}"})}):null}},1878:(e,t,n)=>{"use strict";n.d(t,{A:()=>x});n(6540);var s=n(4164),a=n(4586),o=n(8774),i=n(1312),l=n(4070),c=n(7559),r=n(5597),d=n(2252),u=n(4848);const m={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(i.A,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:(0,u.jsx)("b",{children:n.label})},children:"This is unreleased documentation for {siteTitle} {versionLabel} version."})},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(i.A,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:(0,u.jsx)("b",{children:n.label})},children:"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained."})}};function h(e){const t=m[e.versionMetadata.banner];return(0,u.jsx)(t,{...e})}function p(e){let{versionLabel:t,to:n,onClick:s}=e;return(0,u.jsx)(i.A,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:(0,u.jsx)("b",{children:(0,u.jsx)(o.A,{to:n,onClick:s,children:(0,u.jsx)(i.A,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label",children:"latest version"})})})},children:"For up-to-date documentation, see the {latestVersionLink} ({versionLabel})."})}function f(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:o}}=(0,a.A)(),{pluginId:i}=(0,l.vT)({failfast:!0}),{savePreferredVersionName:d}=(0,r.g1)(i),{latestDocSuggestion:m,latestVersionSuggestion:f}=(0,l.HW)(i),x=null!=m?m:(b=f).docs.find((e=>e.id===b.mainDocId));var b;return(0,u.jsxs)("div",{className:(0,s.A)(t,c.G.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert",children:[(0,u.jsx)("div",{children:(0,u.jsx)(h,{siteTitle:o,versionMetadata:n})}),(0,u.jsx)("div",{className:"margin-top--md",children:(0,u.jsx)(p,{versionLabel:f.label,to:x.path,onClick:()=>d(f.name)})})]})}function x(e){let{className:t}=e;const n=(0,d.r)();return n.banner?(0,u.jsx)(f,{className:t,versionMetadata:n}):null}},8426:(e,t)=>{function n(e){let t,n=[];for(let s of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(s))n.push(parseInt(s,10));else if(t=s.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,s,a,o]=t;if(s&&o){s=parseInt(s),o=parseInt(o);const e=s{"use strict";n.d(t,{R:()=>i,x:()=>l});var s=n(6540);const a={},o=s.createContext(a);function i(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/237.5283eccd.js b/build/assets/js/237.5283eccd.js
deleted file mode 100644
index b3796f5a..00000000
--- a/build/assets/js/237.5283eccd.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[237],{3363:(e,t,i)=>{i.d(t,{A:()=>a});i(6540);var n=i(4164),o=i(1312),s=i(1107),r=i(4848);function a(e){let{className:t}=e;return(0,r.jsx)("main",{className:(0,n.A)("container margin-vert--xl",t),children:(0,r.jsx)("div",{className:"row",children:(0,r.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,r.jsx)(s.A,{as:"h1",className:"hero__title",children:(0,r.jsx)(o.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,r.jsx)("p",{children:(0,r.jsx)(o.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,r.jsx)("p",{children:(0,r.jsx)(o.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}},2237:(e,t,i)=>{i.r(t),i.d(t,{default:()=>c});i(6540);var n=i(1312),o=i(1003),s=i(781),r=i(3363),a=i(4848);function c(){const e=(0,n.T)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(o.be,{title:e}),(0,a.jsx)(s.A,{children:(0,a.jsx)(r.A,{})})]})}}}]);
\ No newline at end of file
diff --git a/build/assets/js/2eb856f7.12910cf4.js b/build/assets/js/2eb856f7.12910cf4.js
deleted file mode 100644
index 70e5b43f..00000000
--- a/build/assets/js/2eb856f7.12910cf4.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[370],{4979:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var n=i(4848),o=i(8453);const s={sidebar_position:1},r=void 0,c={id:"cityscopejs/Introduction",title:"Introduction",description:"CityScope platform for the web",source:"@site/docs/cityscopejs/Introduction.md",sourceDirName:"cityscopejs",slug:"/cityscopejs/Introduction",permalink:"/cityscopejs/Introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityscopejs/Introduction.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"sidebar",previous:{title:"CityScopeJS",permalink:"/category/cityscopejs"},next:{title:"Opening a project",permalink:"/cityscopejs/Opening a project"}},a={},d=[{value:"CityScope platform for the web",id:"cityscope-platform-for-the-web",level:2},{value:"What is it for?",id:"what-is-it-for",level:2},{value:"CityScopeJS Web interface",id:"cityscopejs-web-interface",level:6},{value:"CityScopeJS TUI",id:"cityscopejs-tui",level:6},{value:"Quick Start",id:"quick-start",level:2},{value:"Development",id:"development",level:2},{value:"Hard-Reset cityIO GEOGRIDDATA field",id:"hard-reset-cityio-geogriddata-field",level:4},{value:"CityScopeJS schema",id:"cityscopejs-schema",level:2},{value:"Data Requirements",id:"data-requirements",level:2},{value:"geogrid:geojson",id:"geogridgeojson",level:3}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h6:"h6",hr:"hr",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"cityscope-platform-for-the-web",children:"CityScope platform for the web"}),"\n",(0,n.jsxs)(t.p,{children:["CityScopeJS is the unified front-end for the ",(0,n.jsx)(t.a,{href:"https://cityscope.media.mit.edu/",children:"MIT CityScope"})," project. CityScopeJS allows users to examine different urban-design alternatives and observe their impact through different KPIs and matrices. CityScopeJS brings together different urban analytics modules, such as traffic simulation, ABM, noise, storm-water, access."]}),"\n",(0,n.jsx)(t.h2,{id:"what-is-it-for",children:"What is it for?"}),"\n",(0,n.jsx)(t.p,{children:"CityScopeJS is an online tool with a web interface or tangible user interface (TUI). Using the tool, users can input land uses, buildings, open spaces or transport routes, categorize them and enrich their description with details on usability, density and other parameters. This input forms the basis for calculating the various modules and indicators."}),"\n",(0,n.jsx)(t.p,{children:"This tool also enables collaboration among people within the City Science Network. By using a single tool for defining projects and visualizations, individuals can easily exchange processes, best practices, and even modules."}),"\n",(0,n.jsx)(t.h6,{id:"cityscopejs-web-interface",children:"CityScopeJS Web interface"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"TUI",src:i(8523).A+"",width:"1000",height:"587"})}),"\n",(0,n.jsx)(t.h6,{id:"cityscopejs-tui",children:"CityScopeJS TUI"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"TUI",src:i(2764).A+"",width:"1000",height:"1000"})}),"\n",(0,n.jsx)(t.hr,{}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsxs)(t.strong,{children:["CityScopeJS exposes two main features: ",(0,n.jsx)(t.code,{children:"CityScopeJS Grid Editor"})," and ",(0,n.jsx)(t.code,{children:"CityScopeJS Palyground"})]})}),"\n",(0,n.jsx)(t.h1,{id:"csjs-playground",children:"CSjs Playground"}),"\n",(0,n.jsx)(t.p,{children:"CSjs Playground is where users interact with the design of urban areas. The tool is built to allow snappy, real-time intervention with various land-uses. The design is then evaluated using different urban analytics modules."}),"\n",(0,n.jsx)(t.h2,{id:"quick-start",children:"Quick Start"}),"\n",(0,n.jsxs)(t.p,{children:["To explore the app for a known CityScope project, add a CityScope project name to this page URL (for example, ",(0,n.jsx)(t.code,{children:"__URL__/?cityscope=corktown"})," will run ",(0,n.jsx)(t.a,{href:"https://cityscope.media.mit.edu/CS_cityscopeJS/?cityscope=corktown",children:"CityScopeJS Corktown"})," project). You can also explore a list of active CityScope projects ",(0,n.jsx)(t.a,{href:"https://cityio.media.mit.edu",children:"here"}),"."]}),"\n",(0,n.jsx)(t.p,{children:"When in the app, edit the grid using the editing tool, and explore the different analytics updating"}),"\n",(0,n.jsx)(t.h2,{id:"development",children:"Development"}),"\n",(0,n.jsx)(t.p,{children:"CityScopeJS is being constantly developed through its frontend, backend and modules. This repo is subject to breaking changes."}),"\n",(0,n.jsxs)(t.p,{children:["In the project directory, you can run: ",(0,n.jsx)(t.code,{children:"npm start"})," Runs the app in the development mode.",(0,n.jsx)("br",{})," Open ",(0,n.jsx)(t.a,{href:"http://localhost:3000",children:"http://localhost:3000"})," to view it in the browser."]}),"\n",(0,n.jsxs)(t.h4,{id:"hard-reset-cityio-geogriddata-field",children:["Hard-Reset cityIO ",(0,n.jsx)(t.code,{children:"GEOGRIDDATA"})," field"]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Note!"})," This feature involves permanent data loss. If your dev created odd data for the grid, you can quickly reset it via:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"`$ curl https://cityio.media.mit.edu/api/table/clear/__TABLE_NAME__/GEOGRIDDATA`\n"})}),"\n",(0,n.jsx)(t.hr,{}),"\n",(0,n.jsx)(t.h1,{id:"csjs-grid-editor",children:"CSjs Grid Editor"}),"\n",(0,n.jsx)(t.p,{children:"The CSjs Grid Editor is a helper tool to bootstrap new CityScope projects. It allow a quick creation of:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"a CityScope endpoint on CityIO"}),"\n",(0,n.jsx)(t.li,{children:"a geo-located, 3D, editable and contextual CityScope grid"}),"\n",(0,n.jsx)(t.li,{children:"a list of land-uses to be used during the project"}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"cityscopejs-schema",children:"CityScopeJS schema"}),"\n",(0,n.jsx)(t.p,{children:"This document illustrates the data format and standards for the deployment of a CityScopeJS instance. Being a WIP project, this is subject to change."}),"\n",(0,n.jsx)(t.h2,{id:"data-requirements",children:"Data Requirements"}),"\n",(0,n.jsx)(t.h3,{id:"geogridgeojson",children:(0,n.jsx)(t.code,{children:"geogrid:geojson"})}),"\n",(0,n.jsxs)(t.p,{children:["Minimal data for initiation is a valid GeoJson ",(0,n.jsx)(t.code,{children:"FeatureCollection"})," of at least one ",(0,n.jsx)(t.code,{children:"Polygon"})," feature.\nIdeally, this field should be read once on init, due to its size and static state. User should not iterate over it."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'{\n "type": "FeatureCollection",\n "properties": {\n "header": {},\n "interactive_mapping": {"1245":{"TUI":"1"},"1472":{"WEB":"1"}}\n },\n\n "features": [\n {\n "type": "Feature",\n "properties": {},\n "geometry": {\n "type": "Polygon",\n "coordinates": [\n [\n [\n __lat__,\n __long__\n ],\n ...\n ]\n ]\n }\n }...\n ]\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.strong,{children:"optional fields"})}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.code,{children:"interactive_mapping"}),": maps the grid cells that are interactable via the HCI/TUI CityScope interface or web/mobile UI. This allow mixing of different interactions without overwriting. Format"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'{\n\t"__feature_number__": {\n\t\t"TUI": "__TUI_CELL_NUMBER__"\n\t},\n\t"__feature_number__": {\n\t\t"WEB": "__WEB_INTERACTION_CELL_NUMBER__"\n\t}\n}\n'})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},2764:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/CityScopeJS-5c67b64921cab086329c46dfafa1715a.jpg"},8523:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/web_ui-a8964ffa79f4bdd8f5c47db299d8e802.jpg"},8453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>c});var n=i(6540);const o={},s=n.createContext(o);function r(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/3027556f.ffcbacaa.js b/build/assets/js/3027556f.ffcbacaa.js
deleted file mode 100644
index 0a2e36d8..00000000
--- a/build/assets/js/3027556f.ffcbacaa.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[793],{614:(t,e,i)=>{i.r(e),i.d(e,{assets:()=>a,contentTitle:()=>s,default:()=>h,frontMatter:()=>c,metadata:()=>r,toc:()=>u});var o=i(4848),n=i(8453);const c={sidebar_position:1},s=void 0,r={id:"cityio/Introduction",title:"Introduction",description:"The purpose of this section is to outline the architecture and interfaces of CityIOWS, an updated version of CityIO that utilizes WebSockets for communication with modules and user interfaces.",source:"@site/docs/cityio/Introduction.md",sourceDirName:"cityio",slug:"/cityio/Introduction",permalink:"/cityio/Introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityio/Introduction.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"sidebar",previous:{title:"CityIO",permalink:"/category/cityio"},next:{title:"Architecture",permalink:"/cityio/Architecture"}},a={},u=[];function d(t){const e={img:"img",p:"p",...(0,n.R)(),...t.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(e.p,{children:"The purpose of this section is to outline the architecture and interfaces of CityIOWS, an updated version of CityIO that utilizes WebSockets for communication with modules and user interfaces."}),"\n",(0,o.jsx)(e.p,{children:"The diagram below illustrates the various components that interact with CityIOWS, including modules, core modules, and user interfaces. Communication among these components is facilitated through CityIO, serving as a broker. A WebSocket channel is established for each connection."}),"\n",(0,o.jsx)(e.p,{children:(0,o.jsx)(e.img,{alt:"CityIO Websockets",src:i(1242).A+"",width:"960",height:"252"})})]})}function h(t={}){const{wrapper:e}={...(0,n.R)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(d,{...t})}):d(t)}},1242:(t,e,i)=>{i.d(e,{A:()=>o});const o=i.p+"assets/images/arch-903c36303104dbdba881ec156abf41ea.png"},8453:(t,e,i)=>{i.d(e,{R:()=>s,x:()=>r});var o=i(6540);const n={},c=o.createContext(n);function s(t){const e=o.useContext(c);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function r(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(n):t.components||n:s(t.components),o.createElement(c.Provider,{value:e},t.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/3c6077be.558d856d.js b/build/assets/js/3c6077be.558d856d.js
deleted file mode 100644
index b5aaa3cd..00000000
--- a/build/assets/js/3c6077be.558d856d.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[694],{8408:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>d});var o=t(4848),a=t(8453);const i={sidebar_position:3},r=void 0,s={id:"modules/brix/Module example",title:"Module example",description:"In this section, we present how to code an example DeckGL module on Brix WS that connects with a project in CityScopeJS and displays various visualizations.",source:"@site/docs/modules/brix/Module example.md",sourceDirName:"modules/brix",slug:"/modules/brix/Module example",permalink:"/modules/brix/Module example",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/modules/brix/Module example.md",tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"sidebar",previous:{title:"DeckGL Modules",permalink:"/modules/brix/DeckGL Modules"},next:{title:"Introduction",permalink:"/modules/Core Modules/Introduction"}},l={},d=[{value:"Basic structure of a module",id:"basic-structure-of-a-module",level:2},{value:"DeckGL Modules: adding layers",id:"deckgl-modules-adding-layers",level:2},{value:"Connecting with CityIO",id:"connecting-with-cityio",level:2},{value:"Visualizing the result in CityScopeJS",id:"visualizing-the-result-in-cityscopejs",level:2}];function c(e){const n={code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"In this section, we present how to code an example DeckGL module on Brix WS that connects with a project in CityScopeJS and displays various visualizations."}),"\n",(0,o.jsx)(n.p,{children:"Currently, Brix WS is not published as a Python library available through pip. Consequently, the first step would be to download the code from GitHub."}),"\n",(0,o.jsx)(n.h2,{id:"basic-structure-of-a-module",children:"Basic structure of a module"}),"\n",(0,o.jsx)(n.p,{children:"The basic structure of any module will be as follows:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-python",children:"\nfrom brix.classes import DeckGLIndicator\n\nimport random\nfrom numpy import mean\nclass ExampleModule(DeckGLIndicator):\n\n def setup(self):\n self.name = 'example'\n\n def load_module(self):\n pass\n\n def return_indicator(self, geogrid_data):\n # Module code\n"})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"setup"})," function will be used to define the values of some variables, such as the name of the module."]}),"\n",(0,o.jsxs)(n.p,{children:["Data loading actions should go in the ",(0,o.jsx)(n.code,{children:"load_module"})," function"]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"return_indicator"})," will be the main function of any module, in this one, you can read the data of the grid realted to the project, executed the necessary calculations to obtain the module output, and return it in a proper structure to be sent back to CityIO."]}),"\n",(0,o.jsx)(n.h2,{id:"deckgl-modules-adding-layers",children:"DeckGL Modules: adding layers"}),"\n",(0,o.jsx)(n.p,{children:"In order to generate a DeckGL module, we need to send back to CityIO all the layers that will compose the visualization in CityScopeJS. In this example, we use different types of layers to generate a random indicator: heatmaps, columns, arc, and geojson."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-python",children:' def return_indicator(self, geogrid_data):\n\n data = []\n\n #HEATMAP\n features = []\n for cell in geogrid_data:\n feature = {}\n lat,lon = zip(*cell[\'geometry\'][\'coordinates\'][0])\n lat,lon = mean(lat),mean(lon)\n feature[\'coordinates\'] = [lat,lon]\n feature[\'weight\'] = random.random()*10\n features.append(feature)\n \n data.append({"type":"heatmap","data":features,"properties":{}}) \n\n #ARC\n arc_data = [{\n \'inbound\': 72633,\n \'outbound\': 74735,\n \'from\': {\n \'name\': \'MIT Media Lab\',\n \'coordinates\': [-71.08727713271684, 42.36041314214483]\n },\n \'to\': {\n \'name\': \'MIT CSAIL\',\n \'coordinates\': [-71.09060913355545, 42.36168851347742]\n }\n }]\n data.append({"type":"arc","data":arc_data,"properties":{"width":1}}) \n\n #COLUMNS\n features_columns = []\n for cell in geogrid_data:\n feature = {}\n lat,lon = zip(*cell[\'geometry\'][\'coordinates\'][0])\n lat,lon = mean(lat),mean(lon)\n feature[\'centroid\'] = [lat,lon]\n feature[\'value\'] = random.random()*300\n features_columns.append(feature)\n \n data.append({"type":"column","data":features_columns,"properties":{}}) \n\n #GEOJSON\n geojson_data = {"type": "FeatureCollection","features": [{"type": "Feature","properties": {},"geometry": {"coordinates": [[[-71.09236362469034,42.35778603125499],[-71.08986747898945,42.3585765398804],[-71.0901949616614,42.35911429516614],[-71.09076987568574,42.358931458885564],[-71.09126473839052,42.35978648280218],[-71.09261105604213,42.35938317108344],[-71.09214530290863,42.3584421003398],[-71.09268382996976,42.35830766051154],[-71.09236362469034,42.35778603125499]]],"type": "Polygon"}}]}\n \n data.append({"type":"geojsonbase","data":geojson_data,"properties":{}}) \n\n\n return data\n'})}),"\n",(0,o.jsx)(n.p,{children:"The straightforward solution is, for each layer, calculate the necessary data, and then append the layer to the ouput array."}),"\n",(0,o.jsx)(n.p,{children:"It is important to note that this method could be follow with any set of the available layers."}),"\n",(0,o.jsx)(n.h2,{id:"connecting-with-cityio",children:"Connecting with CityIO"}),"\n",(0,o.jsx)(n.p,{children:"Connecting a module to a CityScope project will only require to create a Handler, indicating the name of the table that you want to connect to. Then, add the indicator (module) previously defined to the handler, and start it."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-python",children:"from brix.classes import Handler\n\nindicator = ExampleModule()\n\nH = Handler(quietly=False,\n table_name='walkability')\nH.add_indicators([\n indicator\n ])\nH.listen()\n"})}),"\n",(0,o.jsx)(n.h2,{id:"visualizing-the-result-in-cityscopejs",children:"Visualizing the result in CityScopeJS"}),"\n",(0,o.jsx)(n.p,{children:"When everything is done, and you run the code, this will send to CityScopeJS the result of the module."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Subscription Request",src:t(181).A+"",width:"3092",height:"1690"})})]})}function u(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},181:(e,n,t)=>{t.d(n,{A:()=>o});const o=t.p+"assets/images/deckgl-module-c3c9253421e0d70d9904c067e5711d7e.png"},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>s});var o=t(6540);const a={},i=o.createContext(a);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/40e175d5.0db75752.js b/build/assets/js/40e175d5.0db75752.js
deleted file mode 100644
index 15a20e56..00000000
--- a/build/assets/js/40e175d5.0db75752.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[132],{756:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>o,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var t=n(4848),s=n(8453);const r={id:"CityScope Table Design"},a=void 0,c={id:"tanglibe user interfaces/CityScope Table Design",title:"CityScope Table Design",description:"CityScope Hardware",source:"@site/docs/tanglibe user interfaces/specs.md",sourceDirName:"tanglibe user interfaces",slug:"/tanglibe user interfaces/CityScope Table Design",permalink:"/tanglibe user interfaces/CityScope Table Design",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/tanglibe user interfaces/specs.md",tags:[],version:"current",frontMatter:{id:"CityScope Table Design"},sidebar:"sidebar",previous:{title:"RoboScope",permalink:"/tanglibe user interfaces/RoboScope"},next:{title:"Archive",permalink:"/category/archive"}},o={},l=[{value:"CityScope Hardware",id:"cityscope-hardware",level:2},{value:"Hardware",id:"hardware",level:2},{value:"Software",id:"software",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(i.h2,{id:"cityscope-hardware",children:"CityScope Hardware"}),"\n",(0,t.jsx)(i.p,{children:"CityScope hardware setup for CS+HCU FindingPlaces project, 2016"}),"\n",(0,t.jsx)(i.p,{children:(0,t.jsx)(i.img,{alt:"Ariel Noyman HCU",src:n(5168).A+"",title:"HCU FindingPlaces",width:"2656",height:"1400"})}),"\n",(0,t.jsxs)(i.p,{children:["CityScope generic module [Design: ",(0,t.jsx)(i.a,{href:"http://www.karthikpatanjali.com/#/cityscope-table/",children:"Karthik Patanjali"}),", 2015]"]}),"\n",(0,t.jsx)(i.p,{children:(0,t.jsx)(i.img,{alt:"Karthik_Patanjali",src:n(4335).A+"",title:"Karthik_Patanjali",width:"1400",height:"1063"})}),"\n",(0,t.jsx)(i.h1,{id:"specs",children:"Specs"}),"\n",(0,t.jsx)(i.p,{children:"The system is still in rapid development, so\nthe specification is very flexible. At this point the main components of a cityscope table will be:"}),"\n",(0,t.jsx)(i.h2,{id:"hardware",children:"Hardware"}),"\n",(0,t.jsxs)(i.ol,{children:["\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsx)(i.p,{children:"PC (preferably windows, since some software is win only)"}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsx)(i.p,{children:(0,t.jsx)(i.a,{href:"https://github.com/CityScope/cityscope.github.io/tree/master/CS_Hardware",children:"Table"})}),"\n",(0,t.jsx)(i.p,{children:"Not every deployment uses this table configuration, often times its just a table with the most important transparent top and grid, this is often made from acrylic and laser cut."}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsx)(i.p,{children:"Legos"}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsx)(i.p,{children:"Projectors"}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsx)(i.p,{children:(0,t.jsx)(i.a,{href:"https://www.amazon.com/gp/product/B006JH8T3S/ref=s9_acsd_top_hd_bw_bisR_c_x_1_w?pf_rd_m=ATVPDKIKX0DER&pf_rd_s=merchandised-search-3&pf_rd_r=W90AXQB8TSWYBB1ZZXG5&pf_rd_t=101&pf_rd_p=0af85809-accb-5a70-bc4f-f9a8f374e48c&pf_rd_i=172511",children:"Webcam"})}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsx)(i.p,{children:"(Internet connection)"}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(i.h2,{id:"software",children:"Software"}),"\n",(0,t.jsx)(i.p,{children:"CityScope is composed of multiple software"}),"\n",(0,t.jsxs)(i.ol,{children:["\n",(0,t.jsx)(i.li,{children:"Scanner (gets input from camera converts it to information that can be parsed through various simulation)\ncurrently this functionality is provided using one of below:"}),"\n"]}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsx)(i.li,{children:"Rhinoceros 3D (win only)"}),"\n",(0,t.jsx)(i.li,{children:"Unity game engine"}),"\n",(0,t.jsx)(i.li,{children:"Browser, JavaScript"}),"\n"]}),"\n",(0,t.jsxs)(i.ol,{start:"2",children:["\n",(0,t.jsx)(i.li,{children:"Simulation / Visualization\nthis differs largely on what to simulate, or the research question on focus.\nIn fact, some CityScope table has multiple simulations and visualizations living together."}),"\n"]}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.a,{href:"http://gama-platform.org/",children:"Gama"})," for agent based simulation"]}),"\n",(0,t.jsxs)(i.li,{children:["General Simulation and visualization","\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsx)(i.li,{children:"Rhinoceros 3D / Grasshopper"}),"\n",(0,t.jsx)(i.li,{children:"Unity game engine"}),"\n"]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,t.jsx)(i,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},4335:(e,i,n)=>{n.d(i,{A:()=>t});const t=n.p+"assets/images/KarthikPatanjali-a839ba259d45fce91794e3a03c96804a.png"},5168:(e,i,n)=>{n.d(i,{A:()=>t});const t=n.p+"assets/images/arielnoymanHCU-e60d82029bb9330a8bc08aaa4022b732.png"},8453:(e,i,n)=>{n.d(i,{R:()=>a,x:()=>c});var t=n(6540);const s={},r=t.createContext(s);function a(e){const i=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),t.createElement(r.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/41d6af12.5dabed65.js b/build/assets/js/41d6af12.5dabed65.js
deleted file mode 100644
index 4ce1560d..00000000
--- a/build/assets/js/41d6af12.5dabed65.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[408],{3301:e=>{e.exports=JSON.parse('{"title":"Archive","slug":"/category/archive","permalink":"/category/archive","navigation":{"previous":{"title":"CityScope Table Design","permalink":"/tanglibe user interfaces/CityScope Table Design"},"next":{"title":"[Archive] H3 Grid","permalink":"/archive/h3/"}}}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/4206db4b.fa9e573e.js b/build/assets/js/4206db4b.fa9e573e.js
deleted file mode 100644
index 98c78e17..00000000
--- a/build/assets/js/4206db4b.fa9e573e.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[887],{2635:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>d,toc:()=>l});var i=t(4848),s=t(8453);const a={id:"API"},c="list tables",d={id:"archive/cityio/API",title:"API",description:"Here is a list of APIs exposed for cityio.",source:"@site/docs/archive/cityio/api.md",sourceDirName:"archive/cityio",slug:"/archive/cityio/API",permalink:"/archive/cityio/API",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/cityio/api.md",tags:[],version:"current",frontMatter:{id:"API"},sidebar:"sidebar",previous:{title:"[Archive] CityIO",permalink:"/archive/cityio/"},next:{title:"Build",permalink:"/archive/cityio/Build"}},r={},l=[];function o(e){const n={code:"code",h1:"h1",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Here is a list of APIs exposed for cityio."}),"\n",(0,i.jsx)(n.h1,{id:"list-tables",children:"list tables"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/tables/list/\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'["test"]\n'})}),"\n",(0,i.jsx)(n.h1,{id:"get-a-table",children:"get a table"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/table/test/ | jq .\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"| jq ."})," is just to pretty format the result."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "data": 42,\n "grid": [\n 0,\n 1,\n 0\n ],\n "meta": {\n "hash": "BGuzwcPaxADXvLkR2uciX1pkRumFGJV25UENUur4mUfa",\n "hashes": {\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE",\n "grid": "D9VCvyZn98K9BfSAX26Nm22DTsCfbULokywhdTFKs9Ca"\n },\n "id": "F4tCJsaHmvqu2VRGht4Z4GdMttEArHewfUKiFFVz1w78",\n "timestamp": "2021-03-27T15:41:45.457952355+00:00"\n }\n}\n'})}),"\n",(0,i.jsx)(n.h1,{id:"post-a-table",children:"post a table"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'curl -X POST -d \'{"grid":[0,1,1]}\' \\\n-H "Content-Type:application/json" \\\nhttps://cityio.media.mit.edu/api/table/test/ | jq .\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "id": "6xU8W2WTzwMpyX3vQyRxkbKFxVLfpeV6dERkK9ATukBT",\n "name": "test",\n "status": "ok"\n}\n'})}),"\n",(0,i.jsx)(n.h1,{id:"get-deeper-data",children:"get deeper data"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/table/test/grid | jq .\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"[\n 0,\n 1,\n 1\n]\n"})}),"\n",(0,i.jsx)(n.h1,{id:"post-deeper-data",children:"post deeper data"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'curl -X POST -d \'{"setting":{"cars":true}}\' \\\n-H "Content-Type:application/json" \\\nhttps://cityio.media.mit.edu/api/table/test/new_module | jq .\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "id": "9Dqq91fFjfL5sse9AKyXoUsYXF3Tg62ALpo6fC2B3epB",\n "status": "ok"\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"ver3 lets you send even deeper data, if it's the base data already\nexists"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'curl -X POST -d \'{"pev": true, "cars":false}\' \\\n-H "Content-Type:application/json" \\\nhttps://cityio.media.mit.edu/api/table/test/new_module/setting | jq .\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "commit": "BTLvsmmQbJc5JiMZEsrhzMFgBjRRxcH8irDKz99WbC3b",\n "status": "ok"\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"this case the commit changes"}),"\n",(0,i.jsx)(n.h1,{id:"delete-table",children:"delete table"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl -X DELETE https://cityio.media.mit.edu/api/table/test/\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"ok\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/tables/list/\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"[]\n"})}),"\n",(0,i.jsx)(n.h1,{id:"dump-data",children:"dump data"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/dump/ | jq .\n"})}),"\n",(0,i.jsx)(n.p,{children:"This gives a good overview of how cityio is internally saving data."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "blob": [\n {\n "setting": {\n "cars": true\n }\n },\n [\n 0,\n 1,\n 0\n ],\n 42,\n "hello",\n {\n "setting": {\n "cars": false,\n "pev": true\n }\n },\n [\n 0,\n 1,\n 1\n ]\n ],\n "commit": [\n {\n "parent": "oPuhrsgmJU3aUS5pc2StUrftqUwTDUX3tEweF4NE4fD",\n "timestamp": "2021-03-27T15:41:45.457952355+00:00",\n "tree_id": "BGuzwcPaxADXvLkR2uciX1pkRumFGJV25UENUur4mUfa"\n },\n {\n "parent": "F4tCJsaHmvqu2VRGht4Z4GdMttEArHewfUKiFFVz1w78",\n "timestamp": "2021-03-27T15:44:52.177075895+00:00",\n "tree_id": "TCMSkt5Sy4MBqb1p6ve6t85CzKyTcuGexgvsHpm26tL"\n },\n {\n "parent": "0",\n "timestamp": "2021-03-27T15:02:32.840592341+00:00",\n "tree_id": "55qnpsNMspv9kJJuvQKvoq51s8kRoTN3YX11mVirKnRn"\n },\n {\n "parent": "9Dqq91fFjfL5sse9AKyXoUsYXF3Tg62ALpo6fC2B3epB",\n "timestamp": "2021-03-27T15:50:19.380681197+00:00",\n "tree_id": "BKLV9yuZB4fQmdPfgBqf3dNAWendRvCnMbjM4JBGEYdo"\n },\n {\n "parent": "BTLvsmmQbJc5JiMZEsrhzMFgBjRRxcH8irDKz99WbC3b",\n "timestamp": "2021-03-27T17:04:55.305024404+00:00",\n "tree_id": "UeD3pVhfBUrnoUjRbVR4W9Sh35gw2zBnWZu86qYFyBg"\n },\n {\n "parent": "6xU8W2WTzwMpyX3vQyRxkbKFxVLfpeV6dERkK9ATukBT",\n "timestamp": "2021-03-27T15:48:17.106557974+00:00",\n "tree_id": "8tFUU1YRaENHRBdsWg5q8FFC7jgwZi2Uxi9HAApDsVo1"\n }\n ],\n "tag": [\n {\n "commit": "GmJxu8Lq4vT2xx2HaW9nrmTJdprdKkkrFYFkQ8Mq8UcC",\n "name": "test"\n }\n ],\n "tree": [\n {\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE",\n "grid": "J1XtoDM5DGKZt97qBy3krz3ihhdtD9mJaxNMf62BAJhU",\n "new_module": "2tBViau8ebNWqxbxvqu5pjwFeMk7KjHCVRG4A7e7gubY"\n },\n {\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE",\n "grid": "D9VCvyZn98K9BfSAX26Nm22DTsCfbULokywhdTFKs9Ca"\n },\n {\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE",\n "grid": "J1XtoDM5DGKZt97qBy3krz3ihhdtD9mJaxNMf62BAJhU"\n },\n {\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE",\n "grid": "J1XtoDM5DGKZt97qBy3krz3ihhdtD9mJaxNMf62BAJhU",\n "new_module": "76sjJZQF22BsNYdTP71xpFTHwquQqXzwbfVPiQe5dsYm"\n },\n {\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE"\n },\n {\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE",\n "grid": "J1XtoDM5DGKZt97qBy3krz3ihhdtD9mJaxNMf62BAJhU",\n "new_module": "B8UAsPeLZskSvLDiWffD1vruGewxMBhMNwQF7xipQpGP"\n }\n ]\n}\n'})}),"\n",(0,i.jsx)(n.h1,{id:"get-module-by-id",children:"get module by Id"}),"\n",(0,i.jsxs)(n.p,{children:["a ",(0,i.jsx)(n.code,{children:"module"})," is recorded as ",(0,i.jsx)(n.code,{children:"blob"}),". Files are recorded as ",(0,i.jsx)(n.code,{children:"blobs"})," in git."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/module/8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE/\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"42\n"})}),"\n",(0,i.jsx)(n.h1,{id:"get-hashes-by-id",children:"get hashes by Id"}),"\n",(0,i.jsxs)(n.p,{children:["the ",(0,i.jsx)(n.code,{children:"hashes"})," entry in the meta is recorded as a ",(0,i.jsx)(n.code,{children:"tree"}),". Directories are\nrecorded as ",(0,i.jsx)(n.code,{children:"trees"})," in git."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/hashes/BGuzwcPaxADXvLkR2uciX1pkRumFGJV25UENUur4mUfa/ | jq .\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "data": "8kzzuAWtRcnhd4SnD2zeEuieq5VtuA8nsNcBgzpRaLuE",\n "grid": "D9VCvyZn98K9BfSAX26Nm22DTsCfbULokywhdTFKs9Ca"\n}\n'})}),"\n",(0,i.jsx)(n.h1,{id:"get-a-commit-by-id-and-roll-back",children:"get a commit by Id (and roll back)"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/commit/GmJxu8Lq4vT2xx2HaW9nrmTJdprdKkkrFYFkQ8Mq8UcC/ | jq .\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "tree_id": "UeD3pVhfBUrnoUjRbVR4W9Sh35gw2zBnWZu86qYFyBg",\n "parent": "BTLvsmmQbJc5JiMZEsrhzMFgBjRRxcH8irDKz99WbC3b",\n "timestamp": "2021-03-27T17:04:55.305024404+00:00"\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["the ",(0,i.jsx)(n.code,{children:"parent"})," field of this points to other commits. You can roll back to\ndifferent states using this endpoint."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/commit/BTLvsmmQbJc5JiMZEsrhzMFgBjRRxcH8irDKz99WbC3b/ | jq .\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'{\n "tree_id": "BKLV9yuZB4fQmdPfgBqf3dNAWendRvCnMbjM4JBGEYdo",\n "parent": "9Dqq91fFjfL5sse9AKyXoUsYXF3Tg62ALpo6fC2B3epB",\n "timestamp": "2021-03-27T15:50:19.380681197+00:00"\n}\n'})}),"\n",(0,i.jsx)(n.h1,{id:"post-a-table-by-tagging-similar-to-branching",children:"Post a table by 'tagging', similar to branching"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl -X POST https://cityio.media.mit.edu/api/table/raw/new_table/BTLvsmmQbJc5JiMZEsrhzMFgBjRRxcH8irDKz99WbC3b/ | jq .\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"curl https://cityio.media.mit.edu/api/tables/list/\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'["new_table","test"]\n'})}),"\n",(0,i.jsx)(n.p,{children:"This can be seen as branching, or copying states. You can force merge if\nyou have a commit id to overwrite."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>d});var i=t(6540);const s={},a=i.createContext(s);function c(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/4a555622.9bde79b2.js b/build/assets/js/4a555622.9bde79b2.js
deleted file mode 100644
index 779462e5..00000000
--- a/build/assets/js/4a555622.9bde79b2.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[117],{3635:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var o=i(4848),n=i(8453);const s={sidebar_position:5},c=void 0,r={id:"cityio/CityIO - Core",title:"CityIO - Core",description:"The objective of this interface is to facilitate the integration of core modules into the CityScope network.",source:"@site/docs/cityio/CityIO - Core.md",sourceDirName:"cityio",slug:"/cityio/CityIO - Core",permalink:"/cityio/CityIO - Core",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityio/CityIO - Core.md",tags:[],version:"current",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"sidebar",previous:{title:"CityIO - Module",permalink:"/cityio/CityIO - Module"},next:{title:"API",permalink:"/cityio/API"}},a={},d=[{value:"Message Flow",id:"message-flow",level:2},{value:"Initial connection",id:"initial-connection",level:2},{value:"Subscription request",id:"subscription-request",level:2},{value:"Subscription removal request",id:"subscription-removal-request",level:2}];function l(e){const t={code:"code",h2:"h2",img:"img",p:"p",...(0,n.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"The objective of this interface is to facilitate the integration of core modules into the CityScope network."}),"\n",(0,o.jsx)(t.h2,{id:"message-flow",children:"Message Flow"}),"\n",(0,o.jsx)(t.p,{children:"The following subsections will detail the various data exchanges that can take place between CityIO and the Core Modules."}),"\n",(0,o.jsx)(t.h2,{id:"initial-connection",children:"Initial connection"}),"\n",(0,o.jsxs)(t.p,{children:["To integrate a core module into the CityScope network, the module can establish a connection via the ",(0,o.jsx)(t.code,{children:"/module/core"})," endpoint. Upon successful connection, the module should send a CORE_MODULE_REGISTRATION message containing information to identify the module."]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"Initial Connection",src:i(733).A+"",width:"1042",height:"338"})}),"\n",(0,o.jsx)(t.h2,{id:"subscription-request",children:"Subscription request"}),"\n",(0,o.jsx)(t.p,{children:"When a user, through a user interface, wishes to connect a module to a project, they send a request to CityIO. This request is then forwarded to the core module as a SUBSCRIPTION_REQUEST message. If the module is available, the core module should respond by sending a SUBSCRIBE message to CityIO, including the identifier of the grid that requires the module's services. Upon receiving the grid information, the core module should calculate the necessary indicator and transmit this data back to CityIO."}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"Subscription Request",src:i(4976).A+"",width:"788",height:"385"})}),"\n",(0,o.jsx)(t.h2,{id:"subscription-removal-request",children:"Subscription removal request"}),"\n",(0,o.jsx)(t.p,{children:"If a user wishes to disconnect a module from a project, they can send a module removal request to CityIO. This request will be forwarded to the Core Module as a SUBSCRIPTION_REMOVAL_REQUEST. Upon receiving this message, the Core Module should then UNSUBSCRIBE from the project."}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"Subscription Removal Request",src:i(7976).A+"",width:"709",height:"292"})})]})}function u(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},733:(e,t,i)=>{i.d(t,{A:()=>o});const o=i.p+"assets/images/initialcon-42240e1d4ec5ae66a2c9f36bbdff6cad.png"},7976:(e,t,i)=>{i.d(t,{A:()=>o});const o=i.p+"assets/images/subremovalrequest-fc67d08ec2f9ff21a4a7f7ead1fd9245.png"},4976:(e,t,i)=>{i.d(t,{A:()=>o});const o=i.p+"assets/images/subrequest-92c3c8a1abe3c94ee34328d8849c4751.png"},8453:(e,t,i)=>{i.d(t,{R:()=>c,x:()=>r});var o=i(6540);const n={},s=o.createContext(n);function c(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/4e15b2cd.dcb450e7.js b/build/assets/js/4e15b2cd.dcb450e7.js
deleted file mode 100644
index 353edddc..00000000
--- a/build/assets/js/4e15b2cd.dcb450e7.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[861],{5621:(e,l,n)=>{n.r(l),n.d(l,{assets:()=>o,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>d});var r=n(4848),a=n(8453);const i={sidebar_position:2},s=void 0,t={id:"modules/brix/DeckGL Modules",title:"DeckGL Modules",description:"The main difference in using Brix WS compared to the previous version of Brix is the method of sending data to CityScope for visualization. The previous version of Brix allowed for various pre-defined visualizations, such as numeric with bars or graphs, heatmaps, or ABM, among others. While this was useful, it didn't offer enough flexibility for module makers to create complex visualizations with a variety of different elements. They were always constrained to using the same method to display data.",source:"@site/docs/modules/brix/DeckGL Modules.md",sourceDirName:"modules/brix",slug:"/modules/brix/DeckGL Modules",permalink:"/modules/brix/DeckGL Modules",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/modules/brix/DeckGL Modules.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/modules/brix/Introduction"},next:{title:"Module example",permalink:"/modules/brix/Module example"}},o={},d=[{value:"Available DeckGL Layers",id:"available-deckgl-layers",level:2},{value:"Arc",id:"arc",level:3},{value:"Column",id:"column",level:3},{value:"Contour",id:"contour",level:3},{value:"GeoJson",id:"geojson",level:3},{value:"Grid",id:"grid",level:3},{value:"GridCell",id:"gridcell",level:3},{value:"Heatmap",id:"heatmap",level:3},{value:"Hexagon",id:"hexagon",level:3},{value:"Icon",id:"icon",level:3},{value:"Line",id:"line",level:3},{value:"Path",id:"path",level:3},{value:"ScatterPlot",id:"scatterplot",level:3},{value:"Scenegraph",id:"scenegraph",level:3},{value:"SimpleMesh",id:"simplemesh",level:3},{value:"TextLayer",id:"textlayer",level:3}];function c(e){const l={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(l.p,{children:"The main difference in using Brix WS compared to the previous version of Brix is the method of sending data to CityScope for visualization. The previous version of Brix allowed for various pre-defined visualizations, such as numeric with bars or graphs, heatmaps, or ABM, among others. While this was useful, it didn't offer enough flexibility for module makers to create complex visualizations with a variety of different elements. They were always constrained to using the same method to display data."}),"\n",(0,r.jsxs)(l.p,{children:["To address this issue, Brix WS introduces ",(0,r.jsx)(l.strong,{children:"DeckGL modules"}),", a new type of module that can harness the full power of DeckGL and create robust visualizations using multiple DeckGL layers."]}),"\n",(0,r.jsx)(l.p,{children:"The structure of the data that DeckGL modules should follow is an array of objects, where each object represents one layer of the visualization. Every layer always has the same three properties:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsxs)(l.li,{children:[(0,r.jsx)(l.code,{children:"type"}),": The type of the layer."]}),"\n",(0,r.jsxs)(l.li,{children:[(0,r.jsx)(l.code,{children:"data"}),": The data to be represented."]}),"\n",(0,r.jsxs)(l.li,{children:[(0,r.jsx)(l.code,{children:"properties"}),": Additional properties to configure the visualization of the layer."]}),"\n"]}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:'[\n{"type":"column","data":$data,"properties":{}},\n{"type":"arc","data":$data,"properties":{}},\n{"type":"column","data":$data,"properties":{}},\n...\n]\n'})}),"\n",(0,r.jsx)(l.h2,{id:"available-deckgl-layers",children:"Available DeckGL Layers"}),"\n",(0,r.jsx)(l.p,{children:"At the time being, the available DeckGL layers that can be use in the modules are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsxs)(l.li,{children:["arc: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/arc-layer",children:"https://deck.gl/docs/api-reference/layers/arc-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["column: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/column-layer",children:"https://deck.gl/docs/api-reference/layers/column-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["contours: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/aggregation-layers/contour-layer",children:"https://deck.gl/docs/api-reference/aggregation-layers/contour-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["geojsonbase: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/geojson-layer",children:"https://deck.gl/docs/api-reference/layers/geojson-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["gridlayer: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/aggregation-layers/grid-layer",children:"https://deck.gl/docs/api-reference/aggregation-layers/grid-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["gridcell: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/grid-cell-layer",children:"https://deck.gl/docs/api-reference/layers/grid-cell-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["heatmap: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/aggregation-layers/heatmap-layer",children:"https://deck.gl/docs/api-reference/aggregation-layers/heatmap-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["hexagon: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/aggregation-layers/hexagon-layer",children:"https://deck.gl/docs/api-reference/aggregation-layers/hexagon-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["icon: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/icon-layer",children:"https://deck.gl/docs/api-reference/layers/icon-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["lines: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/line-layer",children:"https://deck.gl/docs/api-reference/layers/line-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["path: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/path-layer",children:"https://deck.gl/docs/api-reference/layers/path-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["scatterplot: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/scatterplot-layer",children:"https://deck.gl/docs/api-reference/layers/scatterplot-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["scenegraph: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/mesh-layers/scenegraph-layer",children:"https://deck.gl/docs/api-reference/mesh-layers/scenegraph-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["simpleMesh: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/mesh-layers/simple-mesh-layer",children:"https://deck.gl/docs/api-reference/mesh-layers/simple-mesh-layer"})]}),"\n",(0,r.jsxs)(l.li,{children:["textLayer: ",(0,r.jsx)(l.a,{href:"https://deck.gl/docs/api-reference/layers/text-layer",children:"https://deck.gl/docs/api-reference/layers/text-layer"})]}),"\n"]}),"\n",(0,r.jsx)(l.p,{children:"This list will grow over time to include all the layers in DeckGL. In each of the links, you can view an example of the visualization that the layer creates."}),"\n",(0,r.jsx)(l.h3,{id:"arc",children:"Arc"}),"\n",(0,r.jsx)(l.p,{children:"The arc layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "arc",\n "data":[\n {\n "from": {\n "coordinates": [-122.269029, 37.80787]\n },\n "to": {\n "coordinates": [-122.271604, 37.803664]\n },\n "sourceColor": [255, 140, 0],\n "targetColor": [100, 140, 0]\n },\n ],\n "properties": {\n "width": 20\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"width: integer, default value 12."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"column",children:"Column"}),"\n",(0,r.jsx)(l.p,{children:"The column layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "column",\n "data":[\n {"centroid": [-122.4, 37.7], "value": 0.2},\n ],\n "properties": {\n "disResolution": 12,\n "radius": 25\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"disResolution: integer, default value 12."}),"\n",(0,r.jsx)(l.li,{children:"radius: integer, default value 30."}),"\n",(0,r.jsx)(l.li,{children:"extruded: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"elevationScale: integer, default value 1."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"contour",children:"Contour"}),"\n",(0,r.jsx)(l.p,{children:"The contour layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "contour",\n "data":[\n {"coordinates": [-122.42177834, 37.78346622]}\n ],\n "properties": {\n "cellSize": 100\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"cellSize: integer, default value 200."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"geojson",children:"GeoJson"}),"\n",(0,r.jsx)(l.p,{children:"The GeoJson layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "geojsonbase",\n "data": $validGeoJsonObject,\n "properties": {\n "filled": false\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"stroked: boolean, default value false."}),"\n",(0,r.jsx)(l.li,{children:"filled: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"extruded: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"pointType: string, default value 'circle'."}),"\n",(0,r.jsx)(l.li,{children:"lineWidthScale: integer, default value 20."}),"\n",(0,r.jsx)(l.li,{children:"lineWidthMinPixels: integer, default value 100."}),"\n",(0,r.jsx)(l.li,{children:"pointRadius: integer, default value 100."}),"\n",(0,r.jsx)(l.li,{children:"lineWidth: integer, default value 1."}),"\n",(0,r.jsx)(l.li,{children:"elevation: integer, default value 30."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"grid",children:"Grid"}),"\n",(0,r.jsx)(l.p,{children:"The Grid layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "gridlayer",\n "data": [{"coordinates": [-122.42177834, 37.78346622]}],\n "properties": {\n "cellSize": 100\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"extruded: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"cellSize: integer, default value 200."}),"\n",(0,r.jsx)(l.li,{children:"elevationScale: integer, default value 4."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"gridcell",children:"GridCell"}),"\n",(0,r.jsx)(l.p,{children:"The GridCell layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "gridcell",\n "data": [{"centroid": [-122.42177834, 37.78346622], "value": 100}],\n "properties": {\n "cellSize": 100\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"extruded: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"cellSize: integer, default value 200."}),"\n",(0,r.jsx)(l.li,{children:"elevationScale: integer, default value 5000."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"heatmap",children:"Heatmap"}),"\n",(0,r.jsx)(l.p,{children:"The heatmap layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "heatmap",\n "data": [{"coordinates": [-122.42177834, 37.78346622], "weight": 100}],\n "properties": {\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.h3,{id:"hexagon",children:"Hexagon"}),"\n",(0,r.jsx)(l.p,{children:"The Hexagon layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "hexagon",\n "data": [{"coordinates": [-122.42177834, 37.78346622]}],\n "properties": {\n "elevationScale": 3\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"extruded: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"radius: integer, default value 200."}),"\n",(0,r.jsx)(l.li,{children:"elevationScale: integer, default value 4."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"icon",children:"Icon"}),"\n",(0,r.jsx)(l.p,{children:"The Icon layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "icon",\n "data": [{"coordinates": [-122.42177834, 37.78346622], "icon": $url, "width": 128, "height": 128, "anchorY": 128, "elevation": 30}],\n "properties": {\n "sizeScale": 3\n }\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"sizeScale: integer, default value 10."}),"\n",(0,r.jsx)(l.li,{children:"sizeMaxPixels: integer, default value 10."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"line",children:"Line"}),"\n",(0,r.jsx)(l.p,{children:"The line layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "line",\n "data":[\n {\n "from": {\n "coordinates": [-122.269029, 37.80787]\n },\n "to": {\n "coordinates": [-122.271604, 37.803664]\n },\n "color": [255, 140, 0]\n },\n ],\n "properties": {\n "width": 20\n }\n\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"width: integer, default value 50."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"path",children:"Path"}),"\n",(0,r.jsx)(l.p,{children:"The Path layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "path",\n "data":[\n {\n "path": [[-122.269029, 37.80787],[-122.271604, 37.803664],[-122.271604, 38.803664]],\n "color": [255, 140, 0],\n "width": 5\n },\n ],\n "properties": {\n "widthScale": 30\n }\n\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"widthScale: integer, default value 20."}),"\n",(0,r.jsx)(l.li,{children:"widthMinPixels: integer, default value 2."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"scatterplot",children:"ScatterPlot"}),"\n",(0,r.jsx)(l.p,{children:"The ScatterPlot layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "scatterplot",\n "data":[\n {"name": "Colma (COLM)", "address\u201d: "365 D Street, Colma CA 94014", "exits\u201d: 4214, "coordinates": [-122.466233, 37.684638]},\n ],\n "properties": {\n "lineWidthMinPixels": 2\n }\n\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"stroked: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"filled: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"radiusScale: integer, default value 6."}),"\n",(0,r.jsx)(l.li,{children:"radiusMinPixels: integer, default value 1."}),"\n",(0,r.jsx)(l.li,{children:"radiusMaxPixels: integer, default value 100."}),"\n",(0,r.jsx)(l.li,{children:"lineWidthMinPixels: integer, default value 1."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"scenegraph",children:"Scenegraph"}),"\n",(0,r.jsx)(l.p,{children:"The Scenegraph layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "scenegraph",\n "data":[\n {"coordinates": [-122.466233, 37.684638]},\n ],\n "properties": {\n "scenegraph": "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoxAnimated/glTF-Binary/BoxAnimated.glb"\n }\n\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n",(0,r.jsx)(l.li,{children:"scenegraph: string, url of the glb object."}),"\n",(0,r.jsx)(l.li,{children:"sizeScale: integer, default value 500."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"simplemesh",children:"SimpleMesh"}),"\n",(0,r.jsx)(l.p,{children:"The SimpleMesh layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "simpleMesh",\n "data":[\n {\n "position": [-122.45, 37.7],\n "angle": 0,\n "color": [255, 0, 0]\n },\n {\n "position": [-122.46, 37.73],\n "angle": 90,\n "color": [0, 255, 0]\n },\n ],\n "properties": {\n "mesh": "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/humanoid_quad.obj"\n }\n\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"sizeScale: integer, default value 1."}),"\n",(0,r.jsx)(l.li,{children:"mesh: string, url of the obj object."}),"\n"]}),"\n",(0,r.jsx)(l.h3,{id:"textlayer",children:"TextLayer"}),"\n",(0,r.jsx)(l.p,{children:"The Text layer should follow the schema of the next example:"}),"\n",(0,r.jsx)(l.pre,{children:(0,r.jsx)(l.code,{className:"language-json",children:' {\n "type": "textLayer",\n "data":[\n {\n "coordinates": [-122.45, 37.7],\n "text": "example",\n },\n {\n "position": [-122.46, 37.73],\n "text": "example",\n },\n ],\n "properties": {\n }\n\n }\n \n'})}),"\n",(0,r.jsx)(l.p,{children:"The available properties for this layer are the following:"}),"\n",(0,r.jsxs)(l.ul,{children:["\n",(0,r.jsx)(l.li,{children:"pickable: boolean, default value true."}),"\n"]})]})}function h(e={}){const{wrapper:l}={...(0,a.R)(),...e.components};return l?(0,r.jsx)(l,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,l,n)=>{n.d(l,{R:()=>s,x:()=>t});var r=n(6540);const a={},i=r.createContext(a);function s(e){const l=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(l):{...l,...e}}),[l,e])}function t(e){let l;return l=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),r.createElement(i.Provider,{value:l},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/57aa5823.7f8b0c27.js b/build/assets/js/57aa5823.7f8b0c27.js
deleted file mode 100644
index 7fd71e60..00000000
--- a/build/assets/js/57aa5823.7f8b0c27.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[459],{2384:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>s,default:()=>u,frontMatter:()=>c,metadata:()=>a,toc:()=>d});var n=i(4848),o=i(8453);const c={sidebar_position:4},s=void 0,a={id:"cityio/CityIO - Module",title:"CityIO - Module",description:"The aim of this interface is to enable user modules to access information about the grids created in CityIO, calculate Key Performance Indicators (KPIs), and then transmit them to the user interfaces.",source:"@site/docs/cityio/CityIO - Module.md",sourceDirName:"cityio",slug:"/cityio/CityIO - Module",permalink:"/cityio/CityIO - Module",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityio/CityIO - Module.md",tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"sidebar",previous:{title:"CityIO - UI",permalink:"/cityio/CityIO - UI"},next:{title:"CityIO - Core",permalink:"/cityio/CityIO - Core"}},r={},d=[{value:"Message Flow",id:"message-flow",level:2},{value:"Initial connection",id:"initial-connection",level:2},{value:"Module recalculation",id:"module-recalculation",level:2}];function l(e){const t={code:"code",h2:"h2",img:"img",p:"p",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"The aim of this interface is to enable user modules to access information about the grids created in CityIO, calculate Key Performance Indicators (KPIs), and then transmit them to the user interfaces."}),"\n",(0,n.jsx)(t.p,{children:"Brix can be utilized as Middleware to facilitate interaction with this interface."}),"\n",(0,n.jsx)(t.h2,{id:"message-flow",children:"Message Flow"}),"\n",(0,n.jsx)(t.p,{children:"The subsequent subsections provide descriptions of the various data exchanges that can occur between CityIO and the User-Defined modules."}),"\n",(0,n.jsx)(t.h2,{id:"initial-connection",children:"Initial connection"}),"\n",(0,n.jsxs)(t.p,{children:["To add a user-defined module to a project, the interface ",(0,n.jsx)(t.code,{children:"/module"})," can initiate a WebSocket channel. Once the connection is established, the module can send a SUBSCRIBE request to CityIO to acquire grid information. After receiving the grid details, the module should calculate the indicator and then send the information back to CityIO."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"Initial Connection",src:i(2899).A+"",width:"760",height:"431"})}),"\n",(0,n.jsx)(t.h2,{id:"module-recalculation",children:"Module recalculation"}),"\n",(0,n.jsx)(t.p,{children:"Upon receiving a GEOGRIDATA_UPDATE message from CityIO, the module should recalculate the indicator and send the updated information back to CityIO."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"Grid Update",src:i(7068).A+"",width:"760",height:"292"})})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},7068:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/calc-4ff39b399a470946dcfa21d9885a2358.png"},2899:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/initialcon-d743feddd6a95b8c507e9d8d8800626d.png"},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>a});var n=i(6540);const o={},c=n.createContext(o);function s(e){const t=n.useContext(c);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),n.createElement(c.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/5a7a18e6.eac0270e.js b/build/assets/js/5a7a18e6.eac0270e.js
deleted file mode 100644
index 0fae4db0..00000000
--- a/build/assets/js/5a7a18e6.eac0270e.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[383],{7020:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>o,contentTitle:()=>d,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>c});var r=n(4848),l=n(8453);const i={sidebar_position:6},d=void 0,t={id:"cityio/API",title:"API",description:"The CityIO HTTP API enables users to access and update information regarding the projects (grids).",source:"@site/docs/cityio/API.md",sourceDirName:"cityio",slug:"/cityio/API",permalink:"/cityio/API",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityio/API.md",tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"sidebar",previous:{title:"CityIO - Core",permalink:"/cityio/CityIO - Core"},next:{title:"Tangible User Interfaces",permalink:"/category/tangible-user-interfaces"}},o={},c=[{value:"Endpoints",id:"endpoints",level:2},{value:"List Projects",id:"list-projects",level:3},{value:"Parameters",id:"parameters",level:4},{value:"Request Body",id:"request-body",level:4},{value:"Success Response",id:"success-response",level:4},{value:"Error Response",id:"error-response",level:4},{value:"Example request",id:"example-request",level:4},{value:"Get Headers",id:"get-headers",level:3},{value:"Parameters",id:"parameters-1",level:4},{value:"Request Body",id:"request-body-1",level:4},{value:"Success Response",id:"success-response-1",level:4},{value:"Error Response",id:"error-response-1",level:4},{value:"Example request",id:"example-request-1",level:4},{value:"Get Grid",id:"get-grid",level:3},{value:"Parameters",id:"parameters-2",level:4},{value:"Request Body",id:"request-body-2",level:4},{value:"Success Response",id:"success-response-2",level:4},{value:"Error Response",id:"error-response-2",level:4},{value:"Example request",id:"example-request-2",level:4},{value:"Create or Update table",id:"create-or-update-table",level:3},{value:"Parameters",id:"parameters-3",level:4},{value:"Request Body",id:"request-body-3",level:4},{value:"Success Response",id:"success-response-3",level:4},{value:"Error Response",id:"error-response-3",level:4}];function a(e){const s={code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.p,{children:"The CityIO HTTP API enables users to access and update information regarding the projects (grids)."}),"\n",(0,r.jsx)(s.h2,{id:"endpoints",children:"Endpoints"}),"\n",(0,r.jsx)(s.h3,{id:"list-projects",children:"List Projects"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"URL"}),": ",(0,r.jsx)(s.code,{children:"/api/table/list"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Method"}),": ",(0,r.jsx)(s.code,{children:"GET"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Auth Required"}),": No"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Permissions Required"}),": None"]}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"parameters",children:"Parameters"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No parameters allowed."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"request-body",children:"Request Body"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No request body allowed."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"success-response",children:"Success Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Code"}),": ",(0,r.jsx)(s.code,{children:"200"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Content"}),": ",(0,r.jsx)(s.code,{children:"JSON"})]}),"\n"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'[\n "test_podzem",\n "nl_haarlem_pbl_bea",\n "ex6_sgp_full_new_landuse_noquay_nostation",\n "test",\n "ex2_sgp_full_new_landuse_quay_bot",\n "group51",\n "test_brix",\n ...\n]\n'})}),"\n",(0,r.jsx)(s.h4,{id:"error-response",children:"Error Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Error response not expected."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"example-request",children:"Example request"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.code,{children:"curl --location 'https://cityio-beta.media.mit.edu/cityio/api/table/list'"})}),"\n",(0,r.jsx)(s.h3,{id:"get-headers",children:"Get Headers"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"URL"}),": ",(0,r.jsx)(s.code,{children:"/api/table/list"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Method"}),": ",(0,r.jsx)(s.code,{children:"GET"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Auth Required"}),": No"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Permissions Required"}),": None"]}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"parameters-1",children:"Parameters"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No parameters allowed."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"request-body-1",children:"Request Body"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No request body allowed."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"success-response-1",children:"Success Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Code"}),": ",(0,r.jsx)(s.code,{children:"200"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Content"}),":"]}),"\n"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'[ {\n "tableHeader": {\n "cellSize": 15,\n "latitude": 42.3664655,\n "longitude": -71.0854323,\n "ncols": 20,\n "nrows": 20,\n "projection": "+proj=lcc +lat_1=42.68333333333333 +lat_2=41.71666666666667 +lat_0=41 +lon_0=-71.5 +x_0=200000 +y_0=750000 +ellps=GRS80 +datum=NAD83 +units=m +no_def",\n "rotation": 0,\n "tableName": "test",\n "tz": -5\n },\n "tableName": "test"\n },\n...\n]\n'})}),"\n",(0,r.jsx)(s.h4,{id:"error-response-1",children:"Error Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Error response not expected."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"example-request-1",children:"Example request"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.code,{children:"curl --location 'https://cityio-beta.media.mit.edu/cityio/api/table/headers'"})}),"\n",(0,r.jsx)(s.h3,{id:"get-grid",children:"Get Grid"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"URL"}),": ",(0,r.jsx)(s.code,{children:"/api/table/{tableName}/{dataPath}"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Method"}),": ",(0,r.jsx)(s.code,{children:"GET"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Auth Required"}),": No"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Permissions Required"}),": None"]}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"parameters-2",children:"Parameters"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.code,{children:"tableName"})," (String) - Name of the table"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.code,{children:"param2"})," (String, optional) - Data path to obtain (optional)"]}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"request-body-2",children:"Request Body"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No request body allowed."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"success-response-2",children:"Success Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Code"}),": ",(0,r.jsx)(s.code,{children:"200"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Content"}),":"]}),"\n"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'{\n "GEOGRID": {\n "features": [\n {\n "type": "Feature",\n "geometry": {\n "type": "Polygon",\n "coordinates": [\n [\n [\n -71.0854323,\n 42.36646549999987\n ],\n...\n}\n'})}),"\n",(0,r.jsx)(s.h4,{id:"error-response-2",children:"Error Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Code"}),": ",(0,r.jsx)(s.code,{children:"204"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Description"}),": Empty body if the table name or the path cannot be found."]}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"example-request-2",children:"Example request"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.code,{children:"curl --location 'https://cityio-beta.media.mit.edu/cityio/api/table/test'"})}),"\n",(0,r.jsx)(s.h3,{id:"create-or-update-table",children:"Create or Update table"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"URL"}),": ",(0,r.jsx)(s.code,{children:"/api/table/{tableName}"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Method"}),": ",(0,r.jsx)(s.code,{children:"POST"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Auth Required"}),": No"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Permissions Required"}),": None"]}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"parameters-3",children:"Parameters"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No request body expected."}),"\n"]}),"\n",(0,r.jsx)(s.h4,{id:"request-body-3",children:"Request Body"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:"{\n$TABLE_BODY\n}\n"})}),"\n",(0,r.jsx)(s.h4,{id:"success-response-3",children:"Success Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Code"}),": ",(0,r.jsx)(s.code,{children:"200"})]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Content"}),":"]}),"\n"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:"{\n$TABLE_BODY\n}\n"})}),"\n",(0,r.jsx)(s.h4,{id:"error-response-3",children:"Error Response"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"WIP"}),"\n"]})]})}function h(e={}){const{wrapper:s}={...(0,l.R)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>d,x:()=>t});var r=n(6540);const l={},i=r.createContext(l);function d(e){const s=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function t(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:d(e.components),r.createElement(i.Provider,{value:s},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/5e95c892.74e26148.js b/build/assets/js/5e95c892.74e26148.js
deleted file mode 100644
index c0356558..00000000
--- a/build/assets/js/5e95c892.74e26148.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[647],{7121:(e,s,c)=>{c.r(s),c.d(s,{default:()=>n});c(6540);var r=c(4164),t=c(1003),u=c(7559),a=c(2831),o=c(781),d=c(4848);function n(e){return(0,d.jsx)(t.e3,{className:(0,r.A)(u.G.wrapper.docsPages),children:(0,d.jsx)(o.A,{children:(0,a.v)(e.route.routes)})})}}}]);
\ No newline at end of file
diff --git a/build/assets/js/62455296.8f177904.js b/build/assets/js/62455296.8f177904.js
deleted file mode 100644
index 9d2b3af5..00000000
--- a/build/assets/js/62455296.8f177904.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[710],{8686:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var i=n(4848),o=n(8453);const s={id:"Internal_Note"},r=void 0,c={id:"archive/cityio/Internal_Note",title:"Internal_Note",description:"this section is for internal maintenance only.",source:"@site/docs/archive/cityio/notes.md",sourceDirName:"archive/cityio",slug:"/archive/cityio/Internal_Note",permalink:"/archive/cityio/Internal_Note",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/cityio/notes.md",tags:[],version:"current",frontMatter:{id:"Internal_Note"},sidebar:"sidebar",previous:{title:"Build",permalink:"/archive/cityio/Build"}},a={},d=[];function l(e){const t={code:"code",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"this section is for internal maintenance only."}),"\n",(0,i.jsxs)(t.p,{children:["cityio is using tmux's shared session for all the server admins to observe, stop, and restart the cityio instance.\nThe location of this session file is ",(0,i.jsx)(t.code,{children:"/tmp/Shared"}),", so to attach the tmux session:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"tmux attach -S /tmp/Shared\n"})}),"\n",(0,i.jsx)(t.p,{children:"To run the process, it should follow instructions written in the doc's Build.md."})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>c});var i=n(6540);const o={},s=i.createContext(o);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/6dfefd1c.26fa8450.js b/build/assets/js/6dfefd1c.26fa8450.js
deleted file mode 100644
index ac5d3b5c..00000000
--- a/build/assets/js/6dfefd1c.26fa8450.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[440],{8400:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>p,frontMatter:()=>s,metadata:()=>c,toc:()=>l});var o=i(4848),n=i(8453);const s={sidebar_position:3},r="Development on GitHub",c={id:"intro/github",title:"Development on GitHub",description:"CityScope is open-source software and is primarily hosted on GitHub. The organization structure is designed to facilitate the development and deployment of CityScope projects. The organization consists of two types of repositories: tools and cities.",source:"@site/docs/intro/github.md",sourceDirName:"intro",slug:"/intro/github",permalink:"/intro/github",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/intro/github.md",tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"sidebar",previous:{title:"System Architecture",permalink:"/intro/system"},next:{title:"CityScopeJS",permalink:"/category/cityscopejs"}},a={},l=[{value:"General development guidelines",id:"general-development-guidelines",level:2},{value:"Repos Structure",id:"repos-structure",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",ul:"ul",...(0,n.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"development-on-github",children:"Development on GitHub"}),"\n",(0,o.jsx)(t.p,{children:"CityScope is open-source software and is primarily hosted on GitHub. The organization structure is designed to facilitate the development and deployment of CityScope projects. The organization consists of two types of repositories: tools and cities."}),"\n",(0,o.jsx)(t.p,{children:"The image below illustrates the components currently available in the CityScope Beta Software architecture. Additional components can be incorporated as required in the future."}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"CityIO Websockets",src:i(7422).A+"",width:"4001",height:"1771"})}),"\n",(0,o.jsx)(t.h2,{id:"general-development-guidelines",children:"General development guidelines"}),"\n",(0,o.jsx)(t.p,{children:"There are many different repositories in the CityScope organization, and each one may have its own development guidelines, license, and contributing guidelines. However, there are some general guidelines that apply to all repositories:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"contact the maintainers of the repository to make sure your contribution is in line with the project's goals"}),"\n",(0,o.jsx)(t.li,{children:"Fork the repository and make your changes in your fork"}),"\n",(0,o.jsx)(t.li,{children:"Create a pull request to the original repository"}),"\n",(0,o.jsx)(t.li,{children:"Make sure your code is well-documented and tested"}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"repos-structure",children:"Repos Structure"}),"\n",(0,o.jsx)(t.p,{children:"This organization consists two types of repositories."}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"Tools"}),"\n",(0,o.jsxs)(t.p,{children:["Repositories having the prefix of ",(0,o.jsx)(t.code,{children:"CS_"})," are the bare tools that commonly used across city projects."]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"Cities"}),"\n",(0,o.jsxs)(t.p,{children:["Cities have their own repositories that includes links (more exactly submodules) of the above tools and other things. These repos start with ",(0,o.jsx)(t.code,{children:"CSL_"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"CityScope in Andorra. Photo: Ariel Noyman",src:i(1834).A+"",width:"2378",height:"2464"})})]})}function p(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},1834:(e,t,i)=>{i.d(t,{A:()=>o});const o=i.p+"assets/images/Github_CS_Organization_diagram-70db1a5f41cb44cdb42ecd86aba9d951.png"},7422:(e,t,i)=>{i.d(t,{A:()=>o});const o=i.p+"assets/images/current_dev-15561505387e0c93b9d3312aa723a9d8.jpg"},8453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>c});var o=i(6540);const n={},s=o.createContext(n);function r(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/6f967107.8110414f.js b/build/assets/js/6f967107.8110414f.js
deleted file mode 100644
index e48466c1..00000000
--- a/build/assets/js/6f967107.8110414f.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[261],{8268:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>h});var n=i(4848),r=i(8453);const o={sidebar_position:1},c="[Archive] H3 Grid",s={id:"archive/h3/h3",title:"[Archive] H3 Grid",description:"This documentation is under construction.",source:"@site/docs/archive/h3/h3.md",sourceDirName:"archive/h3",slug:"/archive/h3/",permalink:"/archive/h3/",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/h3/h3.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"sidebar",previous:{title:"Archive",permalink:"/category/archive"},next:{title:"[Archive] The brix library",permalink:"/archive/brix/"}},a={},h=[];function d(e){const t={admonition:"admonition",h1:"h1",p:"p",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"archive-h3-grid",children:"[Archive] H3 Grid"}),"\n",(0,n.jsx)(t.admonition,{title:"Warning",type:"warning",children:(0,n.jsx)(t.p,{children:"This documentation is under construction."})})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>c,x:()=>s});var n=i(6540);const r={},o=n.createContext(r);function c(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:c(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/70b71d1a.25491f3b.js b/build/assets/js/70b71d1a.25491f3b.js
deleted file mode 100644
index 8233f4a7..00000000
--- a/build/assets/js/70b71d1a.25491f3b.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[730],{977:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>d});var s=n(4848),i=n(8453);const o={sidebar_position:2},r=void 0,c={id:"cityio/Architecture",title:"Architecture",description:"WebSockets: definition and use",source:"@site/docs/cityio/Architecture.md",sourceDirName:"cityio",slug:"/cityio/Architecture",permalink:"/cityio/Architecture",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityio/Architecture.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/cityio/Introduction"},next:{title:"CityIO - UI",permalink:"/cityio/CityIO - UI"}},a={},d=[{value:"WebSockets: definition and use",id:"websockets-definition-and-use",level:2},{value:"WebSockets Messages",id:"websockets-messages",level:2},{value:"HTTP API",id:"http-api",level:2},{value:"Interfaces",id:"interfaces",level:2}];function l(e){const t={code:"code",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"websockets-definition-and-use",children:"WebSockets: definition and use"}),"\n",(0,s.jsx)(t.p,{children:"WebSockets provide a way for two-way communication between a client and a server over a single, long-lived connection. This is different from the traditional HTTP request-response model, where each request opens a new connection (or reuses an existing connection in a limited way), and the server cannot send messages to the client unless explicitly requested. WebSockets allow the server to send messages to the client at any time, facilitating real-time data transfer and interactive applications."}),"\n",(0,s.jsx)(t.p,{children:"In our scenario, CityIO is a message broker that collects, processes, and distributes urban data, and CityScopeJS is a web-based user interface that visualizes this data for analysis and decision-making."}),"\n",(0,s.jsx)(t.p,{children:"Using WebSockets CityScopeJS establishes a WebSocket connection to CityIO when a user opens a project. This single connection stays open for the duration of the user's session. Whenever CityIO has new data or updates, it can immediately push this data to CityScopeJS over the WebSocket connection. CityScopeJS receives the data in real-time and updates the visualizations accordingly. This setup minimizes network overhead, reduces server load, and provides a seamless, real-time user experience."}),"\n",(0,s.jsx)(t.h2,{id:"websockets-messages",children:"WebSockets Messages"}),"\n",(0,s.jsx)(t.p,{children:"The WebSocket messages exchanged between CityIO, the user interfaces (UIs), and the modules will adhere to the following structure, which is represented as a JSON schema:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-json",children:'{\n "title": "websocket-message",\n "description": "Structure of the websocket messages",\n "type": "object",\n "properties": {\n "type":{\n "type": "string"\n },\n "content":{\n "type": "object"\n }\n }\n}\n'})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["The property ",(0,s.jsx)(t.strong,{children:"type"})," will indicate what type of message is sending the entity."]}),"\n",(0,s.jsxs)(t.li,{children:["the property ",(0,s.jsx)(t.strong,{children:"content"})," will differ depending on the type of the message; should contain the information needed for the destination entity to process the message."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"Upon reception of a message, the CityScope entity (CityIO, User Interfaces, or Modules) will follow the next steps:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Parses the message as a JSON, using the previous schema."}),"\n",(0,s.jsxs)(t.li,{children:["Reads the type property:","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"If the type is recognized, reads the content property and executes the proper action."}),"\n",(0,s.jsx)(t.li,{children:"Otherwise, the message is discarted."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"http-api",children:"HTTP API"}),"\n",(0,s.jsx)(t.p,{children:"CityIO features an HTTP API that enables users to access a wide range of information about various projects. The REST API is designed to maintain compatibility with the previous version of CityIO, ensuring that older modules can seamlessly communicate with this new component."}),"\n",(0,s.jsx)(t.h2,{id:"interfaces",children:"Interfaces"}),"\n",(0,s.jsx)(t.p,{children:"The available interfaces, as previously mentioned, include the following:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Websocket channel ",(0,s.jsx)(t.strong,{children:"/interface"}),": interface to exchange messages with interfaces."]}),"\n",(0,s.jsxs)(t.li,{children:["Websocket channel ",(0,s.jsx)(t.strong,{children:"/module"}),": interface to exchange messages with modules."]}),"\n",(0,s.jsxs)(t.li,{children:["Websocket channel ",(0,s.jsx)(t.strong,{children:"/module/core"}),": interface to exchange messages with core modules."]}),"\n",(0,s.jsxs)(t.li,{children:["API REST ",(0,s.jsx)(t.strong,{children:"/api"}),": HTTP interface to obtain information from CityIO."]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>c});var s=n(6540);const i={},o=s.createContext(i);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/7332f3ba.891d7f4f.js b/build/assets/js/7332f3ba.891d7f4f.js
deleted file mode 100644
index 4beed84b..00000000
--- a/build/assets/js/7332f3ba.891d7f4f.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[860],{6842:(t,e,i)=>{i.r(e),i.d(e,{assets:()=>a,contentTitle:()=>r,default:()=>m,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var n=i(4848),o=i(8453);const s={sidebar_position:1},r=void 0,c={id:"modules/brix/Introduction",title:"Introduction",description:"This documentation is under construction. The content of the documentation may change without prior notice.",source:"@site/docs/modules/brix/Introduction.md",sourceDirName:"modules/brix",slug:"/modules/brix/Introduction",permalink:"/modules/brix/Introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/modules/brix/Introduction.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"sidebar",previous:{title:"Brix",permalink:"/category/brix"},next:{title:"DeckGL Modules",permalink:"/modules/brix/DeckGL Modules"}},a={},d=[];function u(t){const e={a:"a",admonition:"admonition",img:"img",p:"p",...(0,o.R)(),...t.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.admonition,{title:"Warning",type:"warning",children:(0,n.jsx)(e.p,{children:"This documentation is under construction. The content of the documentation may change without prior notice."})}),"\n",(0,n.jsx)(e.p,{children:"Brix is a Python library that manages communication with CityIO and CityScopeJS. This enables module makers to focus on their projects without the necessity of directly interacting with CityIO or the UI."}),"\n",(0,n.jsx)(e.p,{children:"As depicted in the following image, module makers only need to concern themselves with the code in their modules, the utilization of Brix, and the results obtained in CityScopeJS. All internal communication mechanisms and updates are managed by the CityScope platform."}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"Subscription Request",src:i(9083).A+"",width:"1330",height:"126"})}),"\n",(0,n.jsxs)(e.p,{children:["You can find more information about Brix on the following website: ",(0,n.jsx)(e.a,{href:"https://cityscope.media.mit.edu/CS_Brix/getting_started.html",children:"https://cityscope.media.mit.edu/CS_Brix/getting_started.html"})]})]})}function m(t={}){const{wrapper:e}={...(0,o.R)(),...t.components};return e?(0,n.jsx)(e,{...t,children:(0,n.jsx)(u,{...t})}):u(t)}},9083:(t,e,i)=>{i.d(e,{A:()=>n});const n=i.p+"assets/images/brix-f6b88d38a0a50447532241c5e2b0bf6a.png"},8453:(t,e,i)=>{i.d(e,{R:()=>r,x:()=>c});var n=i(6540);const o={},s=n.createContext(o);function r(t){const e=n.useContext(s);return n.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function c(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(o):t.components||o:r(t.components),n.createElement(s.Provider,{value:e},t.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/7365a548.c5a91fd5.js b/build/assets/js/7365a548.c5a91fd5.js
deleted file mode 100644
index 193fb5fb..00000000
--- a/build/assets/js/7365a548.c5a91fd5.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[376],{484:e=>{e.exports=JSON.parse('{"title":"Brix","description":"All you need to know about Brix Websockets.","slug":"/category/brix","permalink":"/category/brix","navigation":{"previous":{"title":"Modules","permalink":"/category/modules"},"next":{"title":"Introduction","permalink":"/modules/brix/Introduction"}}}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/78363d9c.638cfac1.js b/build/assets/js/78363d9c.638cfac1.js
deleted file mode 100644
index e8506ed5..00000000
--- a/build/assets/js/78363d9c.638cfac1.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[760],{1468:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>p});var n=o(4848),i=o(8453);const s={id:"RoboScope"},c=void 0,r={id:"tanglibe user interfaces/RoboScope",title:"RoboScope",description:"Work in progress!",source:"@site/docs/tanglibe user interfaces/RoboScope.md",sourceDirName:"tanglibe user interfaces",slug:"/tanglibe user interfaces/RoboScope",permalink:"/tanglibe user interfaces/RoboScope",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/tanglibe user interfaces/RoboScope.md",tags:[],version:"current",frontMatter:{id:"RoboScope"},sidebar:"sidebar",previous:{title:"CityScoPy",permalink:"/tanglibe user interfaces/CityScoPy"},next:{title:"CityScope Table Design",permalink:"/tanglibe user interfaces/CityScope Table Design"}},a={},p=[];function u(e){const t={admonition:"admonition",p:"p",...(0,i.R)(),...e.components};return(0,n.jsx)(t.admonition,{type:"caution",children:(0,n.jsx)(t.p,{children:"Work in progress!"})})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>c,x:()=>r});var n=o(6540);const i={},s=n.createContext(i);function c(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/7980bb0e.37c57d2a.js b/build/assets/js/7980bb0e.37c57d2a.js
deleted file mode 100644
index 94209ca3..00000000
--- a/build/assets/js/7980bb0e.37c57d2a.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[418],{3139:e=>{e.exports=JSON.parse('{"title":"Tangible User Interfaces","description":"Tangible User Interfaces for the CityScope platform","slug":"/category/tangible-user-interfaces","permalink":"/category/tangible-user-interfaces","navigation":{"previous":{"title":"API","permalink":"/cityio/API"},"next":{"title":"CityScoPy","permalink":"/tanglibe user interfaces/CityScoPy"}}}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/7d744e69.77fc8da4.js b/build/assets/js/7d744e69.77fc8da4.js
deleted file mode 100644
index 23f43c80..00000000
--- a/build/assets/js/7d744e69.77fc8da4.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[741],{9433:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var n=o(4848),i=o(8453);const r={slug:"/",sidebar_position:1,title:"Introduction"},a="CityScope",s={id:"intro/intro",title:"Introduction",description:"CityScope is a project conducted at the MIT Media Lab City Science group. It includes a slew of tangible and digital platforms dedicated to solving spatial design and urban planning challenges. The tools range from simulations that quantify the impact of disruptive interventions in cities to community engagement systems. We develop and deploy these tools around the world and maintain free and open-source community for the majority of our work.",source:"@site/docs/intro/intro.md",sourceDirName:"intro",slug:"/",permalink:"/",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/intro/intro.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{slug:"/",sidebar_position:1,title:"Introduction"},sidebar:"sidebar",next:{title:"System Architecture",permalink:"/intro/system"}},c={},d=[{value:"Figure: CityScope in Andorra La-Vella (Photo: Ariel Noyman)",id:"figure-cityscope-in-andorra-la-vella-photo-ariel-noyman",level:6}];function l(e){const t={admonition:"admonition",h1:"h1",h6:"h6",img:"img",p:"p",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"cityscope",children:"CityScope"}),"\n",(0,n.jsx)(t.p,{children:"CityScope is a project conducted at the MIT Media Lab City Science group. It includes a slew of tangible and digital platforms dedicated to solving spatial design and urban planning challenges. The tools range from simulations that quantify the impact of disruptive interventions in cities to community engagement systems. We develop and deploy these tools around the world and maintain free and open-source community for the majority of our work."}),"\n",(0,n.jsx)(t.admonition,{title:"Note",type:"warning",children:(0,n.jsx)(t.p,{children:"CityScope documentation and the software it describes are works in progress. The content of the documentation or the software may change without prior notice."})}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"CityScope in Andorra. Photo: Ariel Noyman",src:o(8750).A+"",width:"2253",height:"1502"})}),"\n",(0,n.jsx)(t.h6,{id:"figure-cityscope-in-andorra-la-vella-photo-ariel-noyman",children:"Figure: CityScope in Andorra La-Vella (Photo: Ariel Noyman)"}),"\n",(0,n.jsx)("iframe",{width:"100%",height:"600",src:"https://www.youtube.com/embed/o71Ab4cJ1uA",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8750:(e,t,o)=>{o.d(t,{A:()=>n});const n=o.p+"assets/images/cs_an-98816fb9a24173dcb29a59aa1ef5bdf3.jpg"},8453:(e,t,o)=>{o.d(t,{R:()=>a,x:()=>s});var n=o(6540);const i={},r=n.createContext(i);function a(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/8529a1a6.ddadba1f.js b/build/assets/js/8529a1a6.ddadba1f.js
deleted file mode 100644
index 4681d326..00000000
--- a/build/assets/js/8529a1a6.ddadba1f.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[374],{784:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>l,toc:()=>o});var s=i(4848),r=i(8453);const t={id:"Brix"},a="[Archive] The brix library",l={id:"archive/brix/Brix",title:"[Archive] The brix library",description:"Brix is a python library for CityScope modules which handles communication with City I/O.",source:"@site/docs/archive/brix/Brix.md",sourceDirName:"archive/brix",slug:"/archive/brix/",permalink:"/archive/brix/",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/brix/Brix.md",tags:[],version:"current",frontMatter:{id:"Brix"},sidebar:"sidebar",previous:{title:"[Archive] H3 Grid",permalink:"/archive/h3/"},next:{title:"Examples",permalink:"/archive/brix/Examples/"}},c={},o=[{value:"Introduction",id:"introduction",level:2},{value:"Installation",id:"installation",level:2},{value:"Indices and tables",id:"indices-and-tables",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.h1,{id:"archive-the-brix-library",children:["[Archive] The ",(0,s.jsx)(n.code,{children:"brix"})," library"]}),"\n",(0,s.jsxs)(n.p,{children:["Brix is a python library for CityScope modules which handles communication with ",(0,s.jsx)(n.a,{href:"http://cityio.media.mit.edu/",children:"City I/O"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsxs)(n.p,{children:["What is this library for? If you have never heard of a CityScope before, you might want to stop reading and learn about them ",(0,s.jsx)(n.a,{href:"https://cityscope.media.mit.edu/",children:"here"}),". CityScope is an awesome way to interact, explore, and co-create urban interventions in a way that can be accessed by multiple people with different background. If you know what they are, please keep reading."]}),"\n",(0,s.jsx)(n.p,{children:"What is a CityScope table? a \u2018table\u2019 is our way of describing a CityScope project. Why table then? Since historically, most CityScope instances were composed of a mesh between a physical table-top 3D model of a city, augmented with projections, software, and other interface hardware. So a table => project."}),"\n",(0,s.jsx)(n.p,{children:"What is an indicator? An indicator is the result of running a module for CityScope. Indicators work by listening for updated from the CityScope table they are linked to, calculating some values by using a model, some function of the data, or a simulation, and then post the result of the calculations to CityIO to be displayed in the table."}),"\n",(0,s.jsx)(n.p,{children:"What are the types of indicators you can build? Indicators can be anything that could be displayed on a CityScope table, including the supporting screens associated to it. For the purpose of this library, we distinguish three types of indicator: numeric, heatmap, simulation."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Numeric: Numeric indicators are just a number or set of numbers. They are usually displayed in a chart (bar chart, radar chart, etc) next to the table. The most common numeric indicator are the numbers that go in the radar plot, which display information about density, diversity, and proximity."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Heatmap: These indicators are geodata. They are made up of geometries (points, lines, or polygons) and properties associated to them. These indicators are displayed as layers directly on the CityScope table."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Simulation: These type of indicators are also displayed on the table but they are the result of an agent based simulation and are therefore displayed as a dynamic layer. They change over time like a short movie. These are not yet supported by this library."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,s.jsx)(n.p,{children:"Brix can be installed from pip. Just do:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"pip install cs-brix\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Getting started"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Basics of building a CityScope indicator"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Let\u2019s talk data (input)"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Build and test your indicator (output)"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Deploy your indicator"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Tutorials"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Auto-updates of GEOGRIDDATA"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Creating a table from python"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Testing your module"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Classes"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Handler class"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Indicator class"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"GEOGRIDDATA class"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Indicator sub-classes"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"User class"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Grid maker class"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Functions"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Helper functions"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Wrapper functions"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"OSM functions"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Examples"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Short examples"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Step by step examples"}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"indices-and-tables",children:"Indices and tables"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Index"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Search Page"}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>l});var s=i(6540);const r={},t=s.createContext(r);function a(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/89ac796e.d6940004.js b/build/assets/js/89ac796e.d6940004.js
deleted file mode 100644
index 71bbab5b..00000000
--- a/build/assets/js/89ac796e.d6940004.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[949],{8649:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>a});var s=i(4848),t=i(8453);const o={id:"CityScoPy"},r=void 0,c={id:"tanglibe user interfaces/CityScoPy",title:"CityScoPy",description:"Download latest release",source:"@site/docs/tanglibe user interfaces/CityScoPy.md",sourceDirName:"tanglibe user interfaces",slug:"/tanglibe user interfaces/CityScoPy",permalink:"/tanglibe user interfaces/CityScoPy",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/tanglibe user interfaces/CityScoPy.md",tags:[],version:"current",frontMatter:{id:"CityScoPy"},sidebar:"sidebar",previous:{title:"Tangible User Interfaces",permalink:"/category/tangible-user-interfaces"},next:{title:"RoboScope",permalink:"/tanglibe user interfaces/RoboScope"}},l={},a=[{value:"A tool for scanning interactions with a tangible LEGO grid and networking MIT CityScope Projects in Python",id:"a-tool-for-scanning-interactions-with-a-tangible-lego-grid-and-networking-mit-cityscope-projects-in-python",level:4},{value:"Usage",id:"usage",level:2},{value:"Class methods",id:"class-methods",level:2},{value:"Cityscopy.keystone()",id:"cityscopykeystone",level:3},{value:"Initial keystone and save to file",id:"initial-keystone-and-save-to-file",level:5},{value:"Cityscopy.scan()",id:"cityscopyscan",level:3},{value:"main scanning and sending method",id:"main-scanning-and-sending-method",level:5},{value:"options in __settings__.json",id:"options-in-__settings__json",level:5},{value:"output",id:"output",level:4},{value:"Cityscopy.udp_listener()",id:"cityscopyudp_listener",level:3},{value:"emulates local UDP server listener",id:"emulates-local-udp-server-listener",level:5},{value:"Errors",id:"errors",level:2},{value:"License",id:"license",level:2},{value:"Contribution",id:"contribution",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",h5:"h5",hr:"hr",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["*** ",(0,s.jsx)(n.a,{href:"https://github.com/CityScope/CS_Scanner_Python/releases/",children:"Download latest release "})," ***"]}),"\n",(0,s.jsx)(n.h4,{id:"a-tool-for-scanning-interactions-with-a-tangible-lego-grid-and-networking-mit-cityscope-projects-in-python",children:"A tool for scanning interactions with a tangible LEGO grid and networking MIT CityScope Projects in Python"}),"\n",(0,s.jsx)(n.p,{children:"CityScoPy is the main component of an interactive MIT CityScope table.\nIt is used for initiating and later run a interactive CityScope instance in any arbitrary geolocated area in the world. CityScoPy can capture, key-stone, scan and send uniquely tagged arrays of 2-dimension physical bricks."}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsx)(n.h2,{id:"usage",children:"Usage"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"install python 3.4 or higher"}),"\n",(0,s.jsx)(n.li,{children:"clone this repo"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ git clone https://github.com/CityScope/CS_CityScoPy.git\n$ cd CS_CityScoPy\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["install packages. To produce a list of needed packages, use ",(0,s.jsx)(n.code,{children:"pipreqs"}),", follow instructions ",(0,s.jsx)(n.a,{href:"https://github.com/bndr/pipreqs",children:"https://github.com/bndr/pipreqs"}),". Or, simply run the app and install packages as they appear as missing."]}),"\n",(0,s.jsxs)(n.li,{children:["tweak ",(0,s.jsx)(n.code,{children:"__settings__.json"})," to fit your cityIO table setup. Read ",(0,s.jsx)(n.a,{href:"https://github.com/cityscope/cs_cityio_backend/wiki",children:"cityIO documentation"})," for proper data structure"]}),"\n",(0,s.jsxs)(n.li,{children:["in ",(0,s.jsx)(n.code,{children:"run.py"})," setup a path to your settings file"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'CITYSCOPY_SETTINGS_PATH = "__path__/__settings__.json"\n'})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["initiate the ",(0,s.jsx)(n.code,{children:"Cityscopy"})," class (see ",(0,s.jsx)(n.code,{children:"run.py"})," example)"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"cityscopy = Cityscopy(CITYSCOPY_SETTINGS_PATH)\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"use one or more of the main methods. 'Blocking' means the method will run forever (while true loop). Advanced users can parallel blocking methods using multithreading."}),"\n"]}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Method"}),(0,s.jsx)(n.th,{children:"Usage"}),(0,s.jsx)(n.th,{children:"Blocking?"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"cityscopy.keystone()"})}),(0,s.jsx)(n.td,{children:"initial keystone and save to file"}),(0,s.jsx)(n.td,{children:"x"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"cityscopy.scan()"})}),(0,s.jsx)(n.td,{children:"main scanning and sending method"}),(0,s.jsx)(n.td,{children:"x"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"cityscopy.udp_listener()"})}),(0,s.jsx)(n.td,{children:"emulate local UDP server listener"}),(0,s.jsx)(n.td,{children:"x"})]})]})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["in terminal run the tool using ",(0,s.jsx)(n.code,{children:"$ run.py"})]}),"\n"]}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsx)(n.h2,{id:"class-methods",children:"Class methods"}),"\n",(0,s.jsx)(n.h3,{id:"cityscopykeystone",children:(0,s.jsx)(n.code,{children:"Cityscopy.keystone()"})}),"\n",(0,s.jsx)(n.h5,{id:"initial-keystone-and-save-to-file",children:"Initial keystone and save to file"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"the tool will start given a cam is connected and working"}),"\n",(0,s.jsxs)(n.li,{children:["Select 4 corners [up right, up left, bottom right, bottom left, at this order] of keystone region\nNote: no need to exactly select the corners, as these are only initial guides for ",(0,s.jsx)(n.code,{children:"scanner"})," method"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"keystone.txt"})," and close"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"cityscopyscan",children:(0,s.jsx)(n.code,{children:"Cityscopy.scan()"})}),"\n",(0,s.jsx)(n.h5,{id:"main-scanning-and-sending-method",children:"main scanning and sending method"}),"\n",(0,s.jsxs)(n.p,{children:["Scanner will detect colors in arrays of 2d-pixel arrays. Then, these color arrays will be compared to list of ",(0,s.jsx)(n.code,{children:"tags"})," attribute of a given ",(0,s.jsx)(n.code,{children:"__settings__.json"})," file. Then the tool will return a list of ",(0,s.jsx)(n.code,{children:"type"})," and ",(0,s.jsx)(n.code,{children:"rotation"})," for each of the scanned arrays. This list is then converted to cityIO acceptable JSON format and can be sent using POST request."]}),"\n",(0,s.jsxs)(n.h5,{id:"options-in-__settings__json",children:["options in ",(0,s.jsx)(n.code,{children:"__settings__.json"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n "cityscopy": {\n "cityscope_project_name": "cityscopy", // table name\n "type": ["0", "1", "2", ...], // types names\n "rotation": ["0", "1", "2", "3"], // default rotations (0, 90, 180, 270)\n "nrows": 10, // number of columns to scan\n "ncols": 10, // number of rows to scan\n "cell_gap": 10, // spacing between grid fields when using physical grid\n "camId": 0, // openCV will pick `camID` camera (usually 0)\n "interval": 250, // in ms, how many time should this send the packet\n "gui": true, // toggle GUI display\n "cityio": true, // toggle UDP or cityIO delivery\n "tags": [ // 16 digit strings of types being scanned [`1000000100000000`]\n "0000000000000000",\n "1111111111111111",\n "1111111100000000",\n ...\n ],\n "mirror_cam": false\n }\n}\n\n'})}),"\n",(0,s.jsxs)(n.p,{children:["Tool will start scanning using whatever keystone data was stored in ",(0,s.jsx)(n.code,{children:"keystone.txt"}),"\nmake corrections to the key stone using the sliders or keyboard using ",(0,s.jsx)(n.code,{children:"1,2,3,4"})," to select a corner and ",(0,s.jsx)(n.code,{children:"[w,a,s,d]"})," to move ",(0,s.jsx)(n.code,{children:"[up,left,down,right]"})," the selected corner. Press ",(0,s.jsx)(n.code,{children:"k"})," to save change to file and ",(0,s.jsx)(n.code,{children:"ctrl-c"})," twice [in the terminal window] to exit program"]}),"\n",(0,s.jsx)(n.h4,{id:"output",children:"output"}),"\n",(0,s.jsxs)(n.p,{children:["the app will attempt sending the resulted scan to cityIO server. If successful, the following JSON format data will appear on the cityIO endpoint defined in ",(0,s.jsx)(n.code,{children:"settings.json"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'\n{\n "grid": [\n [1, 0],\n [1, 0],\n [0, 0],\n [4, 0],\n [-1, -1],\n [-1, -1], // no type was found will return -1 as type and -1 as rotation\n ...\n ],\n\n ...\n other cityIO data\n ...\n}\n\n'})}),"\n",(0,s.jsx)(n.h3,{id:"cityscopyudp_listener",children:(0,s.jsx)(n.code,{children:"Cityscopy.udp_listener()"})}),"\n",(0,s.jsx)(n.h5,{id:"emulates-local-udp-server-listener",children:"emulates local UDP server listener"}),"\n",(0,s.jsxs)(n.p,{children:["simple helper method to emulate what a local UDP client might see if ",(0,s.jsx)(n.code,{children:"cityscopy"})," would send scan over localhost"]}),"\n",(0,s.jsx)(n.h2,{id:"errors",children:"Errors"}),"\n",(0,s.jsx)(n.p,{children:"OS, Python versions, openCV and peripheral devices such as webcams can sometimes cause issues. If you found and issue, please report it as a Github issue. Here're some encountered issues and their solutions:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Mac OSX High Sierra blocks multithreading"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["issue: ",(0,s.jsx)(n.code,{children:"objc[67570]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called."})]}),"\n",(0,s.jsxs)(n.li,{children:["solution: add to your ",(0,s.jsx)(n.code,{children:"$ .bash_profile"})," the line ",(0,s.jsx)(n.code,{children:"export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES"}),". See more here: ",(0,s.jsx)(n.a,{href:"https://stackoverflow.com/questions/50168647/multiprocessing-causes-python-to-crash-and-gives-an-error-may-have-been-in-progr",children:"https://stackoverflow.com/questions/50168647/multiprocessing-causes-python-to-crash-and-gives-an-error-may-have-been-in-progr"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Webcam crash on init, despite working on other apps"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["issue: camera is not configured in ",(0,s.jsx)(n.code,{children:"settings.json"})]}),"\n",(0,s.jsxs)(n.li,{children:["solution: make sure to test different ",(0,s.jsx)(n.code,{children:"camId"})," values. Your OS might put the camera after another device (2,3..)"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsx)(n.h2,{id:"license",children:"License"}),"\n",(0,s.jsxs)(n.p,{children:["Please see ",(0,s.jsx)(n.code,{children:"LICENSE"})," file for more details.This tool may require libraries which are subject to own licensing."]}),"\n",(0,s.jsx)(n.h2,{id:"contribution",children:"Contribution"}),"\n",(0,s.jsx)(n.p,{children:"Please use GitHub Issues and PR interface for contributions."}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsxs)(n.p,{children:["Maintained by ",(0,s.jsx)(n.a,{href:"http://arielnoyman.com",children:"Ariel Noyman"})]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.a,{href:"https://github.com/CityScope/CS_Scanner_Python/graphs/contributors",children:"Repo contributors"})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>c});var s=i(6540);const t={},o=s.createContext(t);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/8a98b319.b118f4c2.js b/build/assets/js/8a98b319.b118f4c2.js
deleted file mode 100644
index 2d2c7505..00000000
--- a/build/assets/js/8a98b319.b118f4c2.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[898],{7781:t=>{t.exports=JSON.parse('{"title":"CityScopeJS","slug":"/category/cityscopejs","permalink":"/category/cityscopejs","navigation":{"previous":{"title":"Development on GitHub","permalink":"/intro/github"},"next":{"title":"Introduction","permalink":"/cityscopejs/Introduction"}}}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/8fd40d43.b5ff2c54.js b/build/assets/js/8fd40d43.b5ff2c54.js
deleted file mode 100644
index 1a06dbf6..00000000
--- a/build/assets/js/8fd40d43.b5ff2c54.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[402],{4358:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>n,metadata:()=>c,toc:()=>l});var s=i(4848),o=i(8453);const n={sidebar_position:2},r="System Architecture",c={id:"intro/system",title:"System Architecture",description:"CityScope is composed of a series of tools loosely connected to each other. The tools are developed in different languages and frameworks, and they communicate through a central server, CityIO.",source:"@site/docs/intro/system.md",sourceDirName:"intro",slug:"/intro/system",permalink:"/intro/system",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/intro/system.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/"},next:{title:"Development on GitHub",permalink:"/intro/github"}},a={},l=[{value:"CityScopeJS",id:"cityscopejs",level:2},{value:"Figure: CityScopeJS Architecture (Photo: Ariel Noyman)",id:"figure-cityscopejs-architecture-photo-ariel-noyman",level:6},{value:"Modules",id:"modules",level:2},{value:"CityScope Server (cityIO)",id:"cityscope-server-cityio",level:2},{value:"Tangible User Interfaces",id:"tangible-user-interfaces",level:2}];function h(e){const t={a:"a",h1:"h1",h2:"h2",h6:"h6",img:"img",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"system-architecture",children:"System Architecture"}),"\n",(0,s.jsx)(t.p,{children:"CityScope is composed of a series of tools loosely connected to each other. The tools are developed in different languages and frameworks, and they communicate through a central server, CityIO."}),"\n",(0,s.jsx)(t.h2,{id:"cityscopejs",children:"CityScopeJS"}),"\n",(0,s.jsx)(t.p,{children:"CityScopeJS is a modular, open-ended architecture for MIT CityScope project."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"User interface to interact with the CityScope projects"}),"\n",(0,s.jsx)(t.li,{children:"Uses CityIO Websockets to communicate with the server"}),"\n",(0,s.jsx)(t.li,{children:"New user experience and design for the CityScope projects"}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"CityScopeJS Architecture",src:i(9473).A+"",width:"4001",height:"1771"})}),"\n",(0,s.jsx)(t.h6,{id:"figure-cityscopejs-architecture-photo-ariel-noyman",children:"Figure: CityScopeJS Architecture (Photo: Ariel Noyman)"}),"\n",(0,s.jsxs)(t.p,{children:["CityScopeJS includes several other modules for building, testing and deploying an end-to-end CityScope platform. Each module is developed as a standalone part of the system with minimal dependency on others. Data flow between modules is done using ",(0,s.jsx)(t.a,{href:"https://cityio.media.mit.edu",children:"cityIO"}),", which operates between the different modules."]}),"\n",(0,s.jsx)(t.h2,{id:"modules",children:"Modules"}),"\n",(0,s.jsx)(t.p,{children:"Different analysis modules calculate various indicators on urban performance, such as noise, mobility, energy and others. These analysis modules are developed by experts in each evaluation field."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Urban Indicators module: ",(0,s.jsx)(t.a,{href:"https://github.com/CityScope/CS_Urban_Indicators",children:"https://github.com/CityScope/CS_Urban_Indicators"})]}),"\n",(0,s.jsxs)(t.li,{children:["A service providing mobility simulation, Agent Based Simulation, and aggregated mobility prediction for CityScope projects ",(0,s.jsx)(t.a,{href:"https://github.com/CityScope/CS_Mobility_Service",children:"https://github.com/CityScope/CS_Mobility_Service"})]}),"\n",(0,s.jsxs)(t.li,{children:["Noise Modeling for Grasbrook, Hamburg: ",(0,s.jsx)(t.a,{href:"https://github.com/CityScope/CSL_Hamburg_Noise",children:"https://github.com/CityScope/CSL_Hamburg_Noise"})]}),"\n",(0,s.jsxs)(t.li,{children:["Agent Based Modeling ",(0,s.jsx)(t.a,{href:"https://github.com/CityScope/CS_Simulation_GAMA",children:"https://github.com/CityScope/CS_Simulation_GAMA"})]}),"\n",(0,s.jsxs)(t.li,{children:["Traffic Simulation module using DLR SUMO ",(0,s.jsx)(t.a,{href:"https://github.com/CityScope/CS_SUMOscope",children:"https://github.com/CityScope/CS_SUMOscope"})]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"cityscope-server-cityio",children:"CityScope Server (cityIO)"}),"\n",(0,s.jsx)(t.p,{children:"CityIO is a server program that saves tables to have different software (visualization, simulation) read/write information. It exposes an API to serve JSON files representing table info."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Enables the communication between the different components of the system."}),"\n",(0,s.jsx)(t.li,{children:"Saves the projects to access them seamlessly in all the components."}),"\n",(0,s.jsx)(t.li,{children:"Rebuilt to allow real-time communication, using WebSockets."}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["See ",(0,s.jsx)(t.a,{href:"https://github.com/CityScope/CS_CityIO",children:"https://github.com/CityScope/CS_CityIO"})]}),"\n",(0,s.jsx)(t.h2,{id:"tangible-user-interfaces",children:"Tangible User Interfaces"}),"\n",(0,s.jsx)(t.p,{children:"CityScope also includes tangible user interfaces (TUIs) that allow users to interact with the system in a physical way. These interfaces are developed using the CityScopeJS platform."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["CityScope Scanner: ",(0,s.jsx)(t.a,{href:"https://github.com/CityScope/CS_CityScoPy",children:"https://github.com/CityScope/CS_CityScoPy"})]}),"\n"]})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},9473:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/CityScopeJS_arch-ed1917ce223b84765036b435c6877aba.jpg"},8453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>c});var s=i(6540);const o={},n=s.createContext(o);function r(e){const t=s.useContext(n);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(n.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/935f2afb.6c0f0a46.js b/build/assets/js/935f2afb.6c0f0a46.js
deleted file mode 100644
index e3796633..00000000
--- a/build/assets/js/935f2afb.6c0f0a46.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[581],{5610:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"sidebar":[{"type":"category","label":"CityScope","items":[{"type":"category","label":"Introduction","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"System Architecture","href":"/intro/system","docId":"intro/system","unlisted":false},{"type":"link","label":"Development on GitHub","href":"/intro/github","docId":"intro/github","unlisted":false}],"href":"/"},{"type":"category","label":"CityScopeJS","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction","href":"/cityscopejs/Introduction","docId":"cityscopejs/Introduction","unlisted":false},{"type":"link","label":"Opening a project","href":"/cityscopejs/Opening a project","docId":"cityscopejs/Opening a project","unlisted":false},{"type":"link","label":"Project view","href":"/cityscopejs/Project view","docId":"cityscopejs/Project view","unlisted":false}],"href":"/category/cityscopejs"},{"type":"category","label":"Modules","collapsible":true,"collapsed":true,"items":[{"type":"category","label":"Brix","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction","href":"/modules/brix/Introduction","docId":"modules/brix/Introduction","unlisted":false},{"type":"link","label":"DeckGL Modules","href":"/modules/brix/DeckGL Modules","docId":"modules/brix/DeckGL Modules","unlisted":false},{"type":"link","label":"Module example","href":"/modules/brix/Module example","docId":"modules/brix/Module example","unlisted":false}],"href":"/category/brix"},{"type":"category","label":"Core Modules","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction","href":"/modules/Core Modules/Introduction","docId":"modules/Core Modules/Introduction","unlisted":false}]},{"type":"link","label":"Types System","href":"/modules/Types System","docId":"modules/Types System","unlisted":false}],"href":"/category/modules"},{"type":"category","label":"CityIO","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Introduction","href":"/cityio/Introduction","docId":"cityio/Introduction","unlisted":false},{"type":"link","label":"Architecture","href":"/cityio/Architecture","docId":"cityio/Architecture","unlisted":false},{"type":"link","label":"CityIO - UI","href":"/cityio/CityIO - UI","docId":"cityio/CityIO - UI","unlisted":false},{"type":"link","label":"CityIO - Module","href":"/cityio/CityIO - Module","docId":"cityio/CityIO - Module","unlisted":false},{"type":"link","label":"CityIO - Core","href":"/cityio/CityIO - Core","docId":"cityio/CityIO - Core","unlisted":false},{"type":"link","label":"API","href":"/cityio/API","docId":"cityio/API","unlisted":false}],"href":"/category/cityio"},{"type":"category","label":"Tangible User Interfaces","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"CityScoPy","href":"/tanglibe user interfaces/CityScoPy","docId":"tanglibe user interfaces/CityScoPy","unlisted":false},{"type":"link","label":"RoboScope","href":"/tanglibe user interfaces/RoboScope","docId":"tanglibe user interfaces/RoboScope","unlisted":false},{"type":"link","label":"CityScope Table Design","href":"/tanglibe user interfaces/CityScope Table Design","docId":"tanglibe user interfaces/CityScope Table Design","unlisted":false}],"href":"/category/tangible-user-interfaces"},{"type":"category","label":"Archive","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"[Archive] H3 Grid","href":"/archive/h3/","docId":"archive/h3/h3","unlisted":false},{"type":"category","label":"[Archive] The brix library","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Examples","href":"/archive/brix/Examples/","docId":"archive/brix/Examples/Examples","unlisted":false},{"type":"link","label":"GAMA","href":"/archive/brix/GAMA","docId":"archive/brix/GAMA","unlisted":false},{"type":"link","label":"Tutorials","href":"/archive/brix/Tutorial/","docId":"archive/brix/Tutorial/Tutorial","unlisted":false}],"href":"/archive/brix/"},{"type":"category","label":"[Archive] CityIO","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"API","href":"/archive/cityio/API","docId":"archive/cityio/API","unlisted":false},{"type":"link","label":"Build","href":"/archive/cityio/Build","docId":"archive/cityio/Build","unlisted":false},{"type":"link","label":"Internal_Note","href":"/archive/cityio/Internal_Note","docId":"archive/cityio/Internal_Note","unlisted":false}],"href":"/archive/cityio/"}],"href":"/category/archive"}],"collapsed":true,"collapsible":true}]},"docs":{"archive/brix/Brix":{"id":"archive/brix/Brix","title":"[Archive] The brix library","description":"Brix is a python library for CityScope modules which handles communication with City I/O.","sidebar":"sidebar"},"archive/brix/Examples/Examples":{"id":"archive/brix/Examples/Examples","title":"Examples","description":"Short examples","sidebar":"sidebar"},"archive/brix/GAMA":{"id":"archive/brix/GAMA","title":"GAMA","description":"Agent-Based Model developped in the CityScience group using Gama Platform and integrated in CityScope","sidebar":"sidebar"},"archive/brix/Tutorial/Tutorial":{"id":"archive/brix/Tutorial/Tutorial","title":"Tutorials","description":"This module also contains a set of other useful functions that integrate with brix.Handler and brix.Indicator.","sidebar":"sidebar"},"archive/cityio/API":{"id":"archive/cityio/API","title":"API","description":"Here is a list of APIs exposed for cityio.","sidebar":"sidebar"},"archive/cityio/Build":{"id":"archive/cityio/Build","title":"Build","description":"From version 3, the Dockerfile inside the repository can be used for","sidebar":"sidebar"},"archive/cityio/CityIO":{"id":"archive/cityio/CityIO","title":"[Archive] CityIO","description":"- data-hub (dump?) to have several clients work together","sidebar":"sidebar"},"archive/cityio/Internal_Note":{"id":"archive/cityio/Internal_Note","title":"Internal_Note","description":"this section is for internal maintenance only.","sidebar":"sidebar"},"archive/h3/h3":{"id":"archive/h3/h3","title":"[Archive] H3 Grid","description":"This documentation is under construction.","sidebar":"sidebar"},"cityio/API":{"id":"cityio/API","title":"API","description":"The CityIO HTTP API enables users to access and update information regarding the projects (grids).","sidebar":"sidebar"},"cityio/Architecture":{"id":"cityio/Architecture","title":"Architecture","description":"WebSockets: definition and use","sidebar":"sidebar"},"cityio/CityIO - Core":{"id":"cityio/CityIO - Core","title":"CityIO - Core","description":"The objective of this interface is to facilitate the integration of core modules into the CityScope network.","sidebar":"sidebar"},"cityio/CityIO - Module":{"id":"cityio/CityIO - Module","title":"CityIO - Module","description":"The aim of this interface is to enable user modules to access information about the grids created in CityIO, calculate Key Performance Indicators (KPIs), and then transmit them to the user interfaces.","sidebar":"sidebar"},"cityio/CityIO - UI":{"id":"cityio/CityIO - UI","title":"CityIO - UI","description":"The objective of this interface is to enable user interfaces to access information about the grids created in CityIO, as well as the Key Performance Indicators (KPIs) computed by the modules. Additionally, this interface will permit users to make changes to the grids.","sidebar":"sidebar"},"cityio/Introduction":{"id":"cityio/Introduction","title":"Introduction","description":"The purpose of this section is to outline the architecture and interfaces of CityIOWS, an updated version of CityIO that utilizes WebSockets for communication with modules and user interfaces.","sidebar":"sidebar"},"cityscopejs/Introduction":{"id":"cityscopejs/Introduction","title":"Introduction","description":"CityScope platform for the web","sidebar":"sidebar"},"cityscopejs/Opening a project":{"id":"cityscopejs/Opening a project","title":"Opening a project","description":"On the CityScopeJS landing page, there are two ways to access a project.","sidebar":"sidebar"},"cityscopejs/Project view":{"id":"cityscopejs/Project view","title":"Project view","description":"When you open a project, CityScopeJS will present you with the project view. This page aims to provide a workspace where you can manage your projects and visualize the outputs of modules. It consists of a navigation bar at the top of the screen, where you can click on different buttons to open several windows with various functionalities. The available options are:","sidebar":"sidebar"},"intro/github":{"id":"intro/github","title":"Development on GitHub","description":"CityScope is open-source software and is primarily hosted on GitHub. The organization structure is designed to facilitate the development and deployment of CityScope projects. The organization consists of two types of repositories: tools and cities.","sidebar":"sidebar"},"intro/intro":{"id":"intro/intro","title":"Introduction","description":"CityScope is a project conducted at the MIT Media Lab City Science group. It includes a slew of tangible and digital platforms dedicated to solving spatial design and urban planning challenges. The tools range from simulations that quantify the impact of disruptive interventions in cities to community engagement systems. We develop and deploy these tools around the world and maintain free and open-source community for the majority of our work.","sidebar":"sidebar"},"intro/system":{"id":"intro/system","title":"System Architecture","description":"CityScope is composed of a series of tools loosely connected to each other. The tools are developed in different languages and frameworks, and they communicate through a central server, CityIO.","sidebar":"sidebar"},"modules/brix/DeckGL Modules":{"id":"modules/brix/DeckGL Modules","title":"DeckGL Modules","description":"The main difference in using Brix WS compared to the previous version of Brix is the method of sending data to CityScope for visualization. The previous version of Brix allowed for various pre-defined visualizations, such as numeric with bars or graphs, heatmaps, or ABM, among others. While this was useful, it didn\'t offer enough flexibility for module makers to create complex visualizations with a variety of different elements. They were always constrained to using the same method to display data.","sidebar":"sidebar"},"modules/brix/Introduction":{"id":"modules/brix/Introduction","title":"Introduction","description":"This documentation is under construction. The content of the documentation may change without prior notice.","sidebar":"sidebar"},"modules/brix/Module example":{"id":"modules/brix/Module example","title":"Module example","description":"In this section, we present how to code an example DeckGL module on Brix WS that connects with a project in CityScopeJS and displays various visualizations.","sidebar":"sidebar"},"modules/Core Modules/Introduction":{"id":"modules/Core Modules/Introduction","title":"Introduction","description":"This documentation is under construction.","sidebar":"sidebar"},"modules/Types System":{"id":"modules/Types System","title":"Types System","description":"CityScope (CS) Types are the basic land-use units that can be combined and arranged to represent urban environments within the CityScope platform. CS Types are assigned to each cell within the grid that is overlaid over the urban area of enquiry. The grid provides unified segmentation, scale and a level of abstraction that can be easily manipulated by users. Each cell within the grid can either be fixed or dynamic, depending on project limits; fixed cells within a grid are not intended to be changeable by users; dynamic cells are intended for manipulation to interact with the CityScope platform. Interactions take place as users manipulate Types within the project area.","sidebar":"sidebar"},"tanglibe user interfaces/CityScope Table Design":{"id":"tanglibe user interfaces/CityScope Table Design","title":"CityScope Table Design","description":"CityScope Hardware","sidebar":"sidebar"},"tanglibe user interfaces/CityScoPy":{"id":"tanglibe user interfaces/CityScoPy","title":"CityScoPy","description":"Download latest release","sidebar":"sidebar"},"tanglibe user interfaces/RoboScope":{"id":"tanglibe user interfaces/RoboScope","title":"RoboScope","description":"Work in progress!","sidebar":"sidebar"}}}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/9576d6be.692a8dec.js b/build/assets/js/9576d6be.692a8dec.js
deleted file mode 100644
index 525dcfb4..00000000
--- a/build/assets/js/9576d6be.692a8dec.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[379],{1452:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>c});var n=t(4848),l=t(8453);const a={id:"CityIO"},s="[Archive] CityIO",r={id:"archive/cityio/CityIO",title:"[Archive] CityIO",description:"- data-hub (dump?) to have several clients work together",source:"@site/docs/archive/cityio/cityio.md",sourceDirName:"archive/cityio",slug:"/archive/cityio/",permalink:"/archive/cityio/",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/cityio/cityio.md",tags:[],version:"current",frontMatter:{id:"CityIO"},sidebar:"sidebar",previous:{title:"Tutorials",permalink:"/archive/brix/Tutorial/"},next:{title:"API",permalink:"/archive/cityio/API"}},d={},c=[{value:"welcome page with links to available tables",id:"welcome-page-with-links-to-available-tables",level:2},{value:"dev endpoints",id:"dev-endpoints",level:2},{value:"list available tables",id:"list-available-tables",level:2},{value:"get table data",id:"get-table-data",level:2},{value:"post table data",id:"post-table-data",level:2},{value:"delete table data",id:"delete-table-data",level:2},{value:"delete module data",id:"delete-module-data",level:2}];function o(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"archive-cityio",children:"[Archive] CityIO"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"data-hub (dump?) to have several clients work together"}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"(lower case)architecture to enforce collaboration within network"}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"server program"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"saves tables to have different software (visualization, simulation) read/write information"}),"\n",(0,n.jsx)(i.li,{children:"exposes a REST API (=url's) to serve json files, representiving table info"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(i.h1,{id:"resources",children:"Resources"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.a,{href:"https://github.com/mitmedialab/cityioserver/wiki/API",children:"API"})}),"\n",(0,n.jsx)(i.p,{children:"shows the endpoint URLs for clients to operate various request through HTTP. (ex. Getting a table data, Updating table data... etc.)"}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.a,{href:"https://github.com/mitmedialab/cityioserver/wiki/Client-Examples",children:"Client Examples"})}),"\n",(0,n.jsx)(i.p,{children:"shows hello world examples from each client in different frameworks (GAMA, Grasshopper, Unity ... etc)"}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(i.h2,{id:"welcome-page-with-links-to-available-tables",children:[(0,n.jsx)(i.a,{href:"https://cityio.media.mit.edu",children:"welcome page"})," with links to available tables"]}),"\n",(0,n.jsx)(i.h1,{id:"api",children:"API"}),"\n",(0,n.jsxs)(i.p,{children:["[baseurl] ",(0,n.jsx)(i.a,{href:"https://cityio.media.mit.edu",children:"https://cityio.media.mit.edu"})]}),"\n",(0,n.jsx)(i.h2,{id:"dev-endpoints",children:"dev endpoints"}),"\n",(0,n.jsx)(i.p,{children:"endpoints in development will have /dev before the api"}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.code,{children:"https://cityio.media.mit.edu/dev/api/table/:tableName"})}),"\n",(0,n.jsx)(i.h2,{id:"list-available-tables",children:"list available tables"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"[GET] https://cityio.media.mit.edu/api/tables/list\n"})}),"\n",(0,n.jsx)(i.h2,{id:"get-table-data",children:"get table data"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"[GET] https://cityio.media.mit.edu/api/table/:tableName\n"})}),"\n",(0,n.jsx)(i.p,{children:"params:"}),"\n",(0,n.jsx)(i.p,{children:"tableName : name of table"}),"\n",(0,n.jsx)(i.p,{children:"format: json/application"}),"\n",(0,n.jsxs)(i.p,{children:[(0,n.jsx)(i.a,{href:"https://cityio.media.mit.edu/table/:tableName",children:"https://cityio.media.mit.edu/table/:tableName"})," is ",(0,n.jsx)(i.strong,{children:"deprecated"})]}),"\n",(0,n.jsx)(i.h2,{id:"post-table-data",children:"post table data"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"[POST] https://cityio.media.mit.edu/api/table/update/:tableName\n"})}),"\n",(0,n.jsx)(i.p,{children:"params:"}),"\n",(0,n.jsx)(i.p,{children:"tableName: name of table"}),"\n",(0,n.jsx)(i.p,{children:"body"}),"\n",(0,n.jsxs)(i.p,{children:[(0,n.jsx)(i.code,{children:"text/plain"})," or ",(0,n.jsx)(i.code,{children:"json/application"})," format accepted."]}),"\n",(0,n.jsxs)(i.p,{children:["text will be converted to json internally, will throw an error if it's not\nvalid json. Server welcomes any valid json, but only things inside ",(0,n.jsx)(i.code,{children:"objects"})," and ",(0,n.jsx)(i.code,{children:"grid"})," objects\nwill be used for comparison to detect uniqueness."]}),"\n",(0,n.jsxs)(i.p,{children:[(0,n.jsx)(i.a,{href:"https://cityio.media.mit.edu/table/update/:tableName",children:"https://cityio.media.mit.edu/table/update/:tableName"})," is ",(0,n.jsx)(i.strong,{children:"deprecated"})]}),"\n",(0,n.jsx)(i.h2,{id:"delete-table-data",children:"delete table data"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"[GET] https://cityio.media.mit.edu/api/table/clear/:tablename\n"})}),"\n",(0,n.jsx)(i.p,{children:"params:"}),"\n",(0,n.jsx)(i.p,{children:"tableName: name of table"}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.strong,{children:"be careful! will delete all data from memory cache and DB"})}),"\n",(0,n.jsx)(i.h2,{id:"delete-module-data",children:"delete module data"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"[GET] https://cityio.media.mit.edu/api/table/clear/:tablename/:modulename\n"})}),"\n",(0,n.jsx)(i.p,{children:"params:"}),"\n",(0,n.jsx)(i.p,{children:"tablename: name of table\nmodulename: name of module"}),"\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.strong,{children:"be careful! will delete all data from memory cache and DB"})}),"\n",(0,n.jsx)(i.h1,{id:"how-to-run-it-locally",children:"How to run it Locally"}),"\n",(0,n.jsx)(i.p,{children:"The current version is developed using rust."}),"\n",(0,n.jsxs)(i.ol,{children:["\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["install ",(0,n.jsx)(i.a,{href:"https://www.rust-lang.org/tools/install",children:"rust"})]}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"clone this repository"}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["clone ",(0,n.jsx)(i.a,{href:"https://github.com/yasushisakai/sha256",children:"sha256 repo"})]}),"\n",(0,n.jsx)(i.p,{children:"this repo should live in the same directory as the main repo"}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"get db credentials from yasushi, save it in the root of this repo"}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:(0,n.jsx)(i.code,{children:"cargo run --bin server --release"})}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(i.p,{children:"this will compile the program and run it in port 8080"}),"\n",(0,n.jsx)(i.p,{children:"the server will now run locally"})]})}function h(e={}){const{wrapper:i}={...(0,l.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(o,{...e})}):o(e)}},8453:(e,i,t)=>{t.d(i,{R:()=>s,x:()=>r});var n=t(6540);const l={},a=n.createContext(l);function s(e){const i=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function r(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:s(e.components),n.createElement(a.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/969018c5.822bc7a6.js b/build/assets/js/969018c5.822bc7a6.js
deleted file mode 100644
index 8248a630..00000000
--- a/build/assets/js/969018c5.822bc7a6.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[890],{5622:e=>{e.exports=JSON.parse('{"title":"Modules","description":"CityScope Modules","slug":"/category/modules","permalink":"/category/modules","navigation":{"previous":{"title":"Project view","permalink":"/cityscopejs/Project view"},"next":{"title":"Brix","permalink":"/category/brix"}}}')}}]);
\ No newline at end of file
diff --git a/build/assets/js/a38df249.88412aeb.js b/build/assets/js/a38df249.88412aeb.js
deleted file mode 100644
index 29020306..00000000
--- a/build/assets/js/a38df249.88412aeb.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[946],{3833:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>a});var o=n(4848),c=n(8453);const s={sidebar_position:2},i=void 0,r={id:"cityscopejs/Opening a project",title:"Opening a project",description:"On the CityScopeJS landing page, there are two ways to access a project.",source:"@site/docs/cityscopejs/Opening a project.md",sourceDirName:"cityscopejs",slug:"/cityscopejs/Opening a project",permalink:"/cityscopejs/Opening a project",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityscopejs/Opening a project.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/cityscopejs/Introduction"},next:{title:"Project view",permalink:"/cityscopejs/Project view"}},p={},a=[];function d(e){const t={img:"img",li:"li",ol:"ol",p:"p",...(0,c.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"On the CityScopeJS landing page, there are two ways to access a project."}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Using the 'Search CityScope Project' text input, users can search for and access the desired project."}),"\n",(0,o.jsx)(t.li,{children:"Users can also access a project by utilizing the globe map and selecting a project by clicking on its corresponding icon."}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"CityScopeJS How to Open a Project",src:n(3865).A+"",width:"1162",height:"848"})})]})}function l(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},3865:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/opening-project-a1235d80f08185e6294ea8bf78916462.png"},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var o=n(6540);const c={},s=o.createContext(c);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:i(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/a7bd4aaa.feee8c2a.js b/build/assets/js/a7bd4aaa.feee8c2a.js
deleted file mode 100644
index 2c9c2332..00000000
--- a/build/assets/js/a7bd4aaa.feee8c2a.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[98],{4532:(n,e,s)=>{s.r(e),s.d(e,{default:()=>d});s(6540);var o=s(1003),r=s(2967),t=s(2252),c=s(2831),i=s(1463),u=s(4848);function a(n){const{version:e}=n;return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(i.A,{version:e.version,tag:(0,r.tU)(e.pluginId,e.version)}),(0,u.jsx)(o.be,{children:e.noIndex&&(0,u.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})]})}function l(n){const{version:e,route:s}=n;return(0,u.jsx)(o.e3,{className:e.className,children:(0,u.jsx)(t.n,{version:e,children:(0,c.v)(s.routes)})})}function d(n){return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(a,{...n}),(0,u.jsx)(l,{...n})]})}}}]);
\ No newline at end of file
diff --git a/build/assets/js/a94703ab.e215fd4d.js b/build/assets/js/a94703ab.e215fd4d.js
deleted file mode 100644
index 3c264dbc..00000000
--- a/build/assets/js/a94703ab.e215fd4d.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[48],{2559:(e,t,n)=>{n.r(t),n.d(t,{default:()=>be});var a=n(6540),o=n(4164),i=n(1003),s=n(7559),l=n(1754),r=n(6588),c=n(1312),d=n(3104),u=n(5062);const m={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};var b=n(4848);function h(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,o]=(0,a.useState)(!1),i=(0,a.useRef)(!1),{startScroll:s,cancelScroll:l}=(0,d.gk)();return(0,d.Mq)(((e,n)=>{let{scrollY:a}=e;const s=null==n?void 0:n.scrollY;s&&(i.current?i.current=!1:a>=s?(l(),o(!1)):a{e.location.hash&&(i.current=!0,o(!1))})),{shown:n,scrollToTop:()=>s(0)}}({threshold:300});return(0,b.jsx)("button",{"aria-label":(0,c.T)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,o.A)("clean-btn",s.G.common.backToTopButton,m.backToTopButton,e&&m.backToTopButtonShow),type:"button",onClick:t})}var p=n(3109),x=n(6347),j=n(4581),f=n(6342),v=n(3465);function _(e){return(0,b.jsx)("svg",{width:"20",height:"20","aria-hidden":"true",...e,children:(0,b.jsxs)("g",{fill:"#7a7a7a",children:[(0,b.jsx)("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),(0,b.jsx)("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})]})})}const A={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function g(e){let{onClick:t}=e;return(0,b.jsx)("button",{type:"button",title:(0,c.T)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,c.T)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,o.A)("button button--secondary button--outline",A.collapseSidebarButton),onClick:t,children:(0,b.jsx)(_,{className:A.collapseSidebarButtonIcon})})}var k=n(5041),C=n(9532);const S=Symbol("EmptyContext"),T=a.createContext(S);function N(e){let{children:t}=e;const[n,o]=(0,a.useState)(null),i=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:o})),[n]);return(0,b.jsx)(T.Provider,{value:i,children:t})}var I=n(1422),B=n(9169),y=n(8774),w=n(2303);function L(e){let{collapsed:t,categoryLabel:n,onClick:a}=e;return(0,b.jsx)("button",{"aria-label":t?(0,c.T)({id:"theme.DocSidebarItem.expandCategoryAriaLabel",message:"Expand sidebar category '{label}'",description:"The ARIA label to expand the sidebar category"},{label:n}):(0,c.T)({id:"theme.DocSidebarItem.collapseCategoryAriaLabel",message:"Collapse sidebar category '{label}'",description:"The ARIA label to collapse the sidebar category"},{label:n}),"aria-expanded":!t,type:"button",className:"clean-btn menu__caret",onClick:a})}function E(e){let{item:t,onItemClick:n,activePath:i,level:r,index:c,...d}=e;const{items:u,label:m,collapsible:h,className:p,href:x}=t,{docs:{sidebar:{autoCollapseCategories:j}}}=(0,f.p)(),v=function(e){const t=(0,w.A)();return(0,a.useMemo)((()=>e.href&&!e.linkUnlisted?e.href:!t&&e.collapsible?(0,l.Nr)(e):void 0),[e,t])}(t),_=(0,l.w8)(t,i),A=(0,B.ys)(x,i),{collapsed:g,setCollapsed:k}=(0,I.u)({initialState:()=>!!h&&(!_&&t.collapsed)}),{expandedItem:N,setExpandedItem:E}=function(){const e=(0,a.useContext)(T);if(e===S)throw new C.dV("DocSidebarItemsExpandedStateProvider");return e}(),M=function(e){void 0===e&&(e=!g),E(e?null:c),k(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:o}=e;const i=(0,C.ZC)(t);(0,a.useEffect)((()=>{t&&!i&&n&&o(!1)}),[t,i,n,o])}({isActive:_,collapsed:g,updateCollapsed:M}),(0,a.useEffect)((()=>{h&&null!=N&&N!==c&&j&&k(!0)}),[h,N,c,k,j]),(0,b.jsxs)("li",{className:(0,o.A)(s.G.docs.docSidebarItemCategory,s.G.docs.docSidebarItemCategoryLevel(r),"menu__list-item",{"menu__list-item--collapsed":g},p),children:[(0,b.jsxs)("div",{className:(0,o.A)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":A}),children:[(0,b.jsx)(y.A,{className:(0,o.A)("menu__link",{"menu__link--sublist":h,"menu__link--sublist-caret":!x&&h,"menu__link--active":_}),onClick:h?e=>{null==n||n(t),x?M(!1):(e.preventDefault(),M())}:()=>{null==n||n(t)},"aria-current":A?"page":void 0,role:h&&!x?"button":void 0,"aria-expanded":h&&!x?!g:void 0,href:h?null!=v?v:"#":v,...d,children:m}),x&&h&&(0,b.jsx)(L,{collapsed:g,categoryLabel:m,onClick:e=>{e.preventDefault(),M()}})]}),(0,b.jsx)(I.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:g,children:(0,b.jsx)(U,{items:u,tabIndex:g?-1:0,onItemClick:n,activePath:i,level:r+1})})]})}var M=n(6654),H=n(3186);const G={menuExternalLink:"menuExternalLink_NmtK"};function W(e){let{item:t,onItemClick:n,activePath:a,level:i,index:r,...c}=e;const{href:d,label:u,className:m,autoAddBaseUrl:h}=t,p=(0,l.w8)(t,a),x=(0,M.A)(d);return(0,b.jsx)("li",{className:(0,o.A)(s.G.docs.docSidebarItemLink,s.G.docs.docSidebarItemLinkLevel(i),"menu__list-item",m),children:(0,b.jsxs)(y.A,{className:(0,o.A)("menu__link",!x&&G.menuExternalLink,{"menu__link--active":p}),autoAddBaseUrl:h,"aria-current":p?"page":void 0,to:d,...x&&{onClick:n?()=>n(t):void 0},...c,children:[u,!x&&(0,b.jsx)(H.A,{})]})},u)}const P={menuHtmlItem:"menuHtmlItem_M9Kj"};function R(e){let{item:t,level:n,index:a}=e;const{value:i,defaultStyle:l,className:r}=t;return(0,b.jsx)("li",{className:(0,o.A)(s.G.docs.docSidebarItemLink,s.G.docs.docSidebarItemLinkLevel(n),l&&[P.menuHtmlItem,"menu__list-item"],r),dangerouslySetInnerHTML:{__html:i}},a)}function D(e){let{item:t,...n}=e;switch(t.type){case"category":return(0,b.jsx)(E,{item:t,...n});case"html":return(0,b.jsx)(R,{item:t,...n});default:return(0,b.jsx)(W,{item:t,...n})}}function F(e){let{items:t,...n}=e;const a=(0,l.Y)(t,n.activePath);return(0,b.jsx)(N,{children:a.map(((e,t)=>(0,b.jsx)(D,{item:e,index:t,...n},t)))})}const U=(0,a.memo)(F),V={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function Y(e){let{path:t,sidebar:n,className:i}=e;const l=function(){const{isActive:e}=(0,k.Mj)(),[t,n]=(0,a.useState)(e);return(0,d.Mq)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return(0,b.jsx)("nav",{"aria-label":(0,c.T)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,o.A)("menu thin-scrollbar",V.menu,l&&V.menuWithAnnouncementBar,i),children:(0,b.jsx)("ul",{className:(0,o.A)(s.G.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(U,{items:n,activePath:t,level:1})})})}const K="sidebar_njMd",z="sidebarWithHideableNavbar_wUlq",q="sidebarHidden_VK0M",O="sidebarLogo_isFc";function J(e){let{path:t,sidebar:n,onCollapse:a,isHidden:i}=e;const{navbar:{hideOnScroll:s},docs:{sidebar:{hideable:l}}}=(0,f.p)();return(0,b.jsxs)("div",{className:(0,o.A)(K,s&&z,i&&q),children:[s&&(0,b.jsx)(v.A,{tabIndex:-1,className:O}),(0,b.jsx)(Y,{path:t,sidebar:n}),l&&(0,b.jsx)(g,{onClick:a})]})}const Q=a.memo(J);var X=n(5600),Z=n(9876);const $=e=>{let{sidebar:t,path:n}=e;const a=(0,Z.M)();return(0,b.jsx)("ul",{className:(0,o.A)(s.G.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(U,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&a.toggle(),"link"===e.type&&a.toggle()},level:1})})};function ee(e){return(0,b.jsx)(X.GX,{component:$,props:e})}const te=a.memo(ee);function ne(e){const t=(0,j.l)(),n="desktop"===t||"ssr"===t,a="mobile"===t;return(0,b.jsxs)(b.Fragment,{children:[n&&(0,b.jsx)(Q,{...e}),a&&(0,b.jsx)(te,{...e})]})}const ae={expandButton:"expandButton_TmdG",expandButtonIcon:"expandButtonIcon_i1dp"};function oe(e){let{toggleSidebar:t}=e;return(0,b.jsx)("div",{className:ae.expandButton,title:(0,c.T)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,c.T)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t,children:(0,b.jsx)(_,{className:ae.expandButtonIcon})})}const ie={docSidebarContainer:"docSidebarContainer_YfHR",docSidebarContainerHidden:"docSidebarContainerHidden_DPk8",sidebarViewport:"sidebarViewport_aRkj"};function se(e){var t;let{children:n}=e;const o=(0,r.t)();return(0,b.jsx)(a.Fragment,{children:n},null!=(t=null==o?void 0:o.name)?t:"noSidebar")}function le(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:i}=e;const{pathname:l}=(0,x.zy)(),[r,c]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{r&&c(!1),!r&&(0,p.O)()&&c(!0),i((e=>!e))}),[i,r]);return(0,b.jsx)("aside",{className:(0,o.A)(s.G.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&c(!0)},children:(0,b.jsx)(se,{children:(0,b.jsxs)("div",{className:(0,o.A)(ie.sidebarViewport,r&&ie.sidebarViewportHidden),children:[(0,b.jsx)(ne,{sidebar:t,path:l,onCollapse:d,isHidden:r}),r&&(0,b.jsx)(oe,{toggleSidebar:d})]})})})}const re={docMainContainer:"docMainContainer_TBSr",docMainContainerEnhanced:"docMainContainerEnhanced_lQrH",docItemWrapperEnhanced:"docItemWrapperEnhanced_JWYK"};function ce(e){let{hiddenSidebarContainer:t,children:n}=e;const a=(0,r.t)();return(0,b.jsx)("main",{className:(0,o.A)(re.docMainContainer,(t||!a)&&re.docMainContainerEnhanced),children:(0,b.jsx)("div",{className:(0,o.A)("container padding-top--md padding-bottom--lg",re.docItemWrapper,t&&re.docItemWrapperEnhanced),children:n})})}const de={docRoot:"docRoot_UBD9",docsWrapper:"docsWrapper_hBAB"};function ue(e){let{children:t}=e;const n=(0,r.t)(),[o,i]=(0,a.useState)(!1);return(0,b.jsxs)("div",{className:de.docsWrapper,children:[(0,b.jsx)(h,{}),(0,b.jsxs)("div",{className:de.docRoot,children:[n&&(0,b.jsx)(le,{sidebar:n.items,hiddenSidebarContainer:o,setHiddenSidebarContainer:i}),(0,b.jsx)(ce,{hiddenSidebarContainer:o,children:t})]})]})}var me=n(3363);function be(e){const t=(0,l.B5)(e);if(!t)return(0,b.jsx)(me.A,{});const{docElement:n,sidebarName:a,sidebarItems:c}=t;return(0,b.jsx)(i.e3,{className:(0,o.A)(s.G.page.docsDocPage),children:(0,b.jsx)(r.V,{name:a,items:c,children:(0,b.jsx)(ue,{children:n})})})}},3363:(e,t,n)=>{n.d(t,{A:()=>l});n(6540);var a=n(4164),o=n(1312),i=n(1107),s=n(4848);function l(e){let{className:t}=e;return(0,s.jsx)("main",{className:(0,a.A)("container margin-vert--xl",t),children:(0,s.jsx)("div",{className:"row",children:(0,s.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,s.jsx)(i.A,{as:"h1",className:"hero__title",children:(0,s.jsx)(o.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}}}]);
\ No newline at end of file
diff --git a/build/assets/js/b632e823.64294f65.js b/build/assets/js/b632e823.64294f65.js
deleted file mode 100644
index b999fd94..00000000
--- a/build/assets/js/b632e823.64294f65.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[666],{9931:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>a,frontMatter:()=>s,metadata:()=>c,toc:()=>u});var n=o(4848),i=o(8453);const s={sidebar_position:1},r="Introduction",c={id:"modules/Core Modules/Introduction",title:"Introduction",description:"This documentation is under construction.",source:"@site/docs/modules/Core Modules/Introduction.md",sourceDirName:"modules/Core Modules",slug:"/modules/Core Modules/Introduction",permalink:"/modules/Core Modules/Introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/modules/Core Modules/Introduction.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"sidebar",previous:{title:"Module example",permalink:"/modules/brix/Module example"},next:{title:"Types System",permalink:"/modules/Types System"}},d={},u=[];function l(e){const t={admonition:"admonition",h1:"h1",p:"p",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(t.admonition,{title:"Warning",type:"warning",children:(0,n.jsx)(t.p,{children:"This documentation is under construction."})})]})}function a(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>r,x:()=>c});var n=o(6540);const i={},s=n.createContext(i);function r(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/b87b04f0.d73d630a.js b/build/assets/js/b87b04f0.d73d630a.js
deleted file mode 100644
index 0e87e502..00000000
--- a/build/assets/js/b87b04f0.d73d630a.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[852],{990:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>l});var t=i(4848),a=i(8453);const r={id:"Examples"},o="Examples",s={id:"archive/brix/Examples/Examples",title:"Examples",description:"Short examples",source:"@site/docs/archive/brix/Examples/Examples.md",sourceDirName:"archive/brix/Examples",slug:"/archive/brix/Examples/",permalink:"/archive/brix/Examples/",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/brix/Examples/Examples.md",tags:[],version:"current",frontMatter:{id:"Examples"},sidebar:"sidebar",previous:{title:"[Archive] The brix library",permalink:"/archive/brix/"},next:{title:"GAMA",permalink:"/archive/brix/GAMA"}},d={},l=[{value:"Short examples",id:"short-examples",level:2},{value:"Numeric indicator: diversity",id:"numeric-indicator-diversity",level:3},{value:"Composite indicator: average",id:"composite-indicator-average",level:3},{value:"Heatmap indicator",id:"heatmap-indicator",level:3},{value:"Textual indicator",id:"textual-indicator",level:3},{value:"Multiple tables simultaneously",id:"multiple-tables-simultaneously",level:3},{value:"Hybrid indicator",id:"hybrid-indicator",level:3},{value:"Step by step examples",id:"step-by-step-examples",level:2},{value:"Diversity of land-use indicator - step by step",id:"diversity-of-land-use-indicator---step-by-step",level:3},{value:"Composite indicator \u2013 step by step tutorial",id:"composite-indicator--step-by-step-tutorial",level:3},{value:"Heatmap indicator \u2013 step by step tutorial",id:"heatmap-indicator--step-by-step-tutorial",level:3},{value:"Static-Heatmap indicator",id:"static-heatmap-indicator",level:3}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"examples",children:"Examples"}),"\n",(0,t.jsx)(n.h2,{id:"short-examples",children:"Short examples"}),"\n",(0,t.jsx)(n.h3,{id:"numeric-indicator-diversity",children:"Numeric indicator: diversity"}),"\n",(0,t.jsxs)(n.p,{children:["Indicators are built as subclasses of the ",":class","\u201dbrix.Indicator class, with three functions that need to be defined: ",(0,t.jsx)(n.code,{children:"brix.Indicator.setup()"}),", ",(0,t.jsx)(n.code,{children:"brix.Indicator.load_module()"}),", and ",(0,t.jsx)(n.code,{children:"brix.Indicator.return_indicator()"}),". The function ",(0,t.jsx)(n.code,{children:"brix.Indicator.setup()"})," acts like an ",(0,t.jsx)(n.strong,{children:"init"}),". It can take any argument and runs when the object is instantiated. The function ",(0,t.jsx)(n.code,{children:"brix.Indicator.load_module()"})," is also run when the indicator in initialized, but it cannot take any arguments. Any inputs needed to run ",(0,t.jsx)(n.code,{children:"brix.Indicator.load_module()"})," should be passed to ",(0,t.jsx)(n.code,{children:"brix.Indicator.setup()"})," and defined as class attributes. The function ",(0,t.jsx)(n.code,{children:"brix.Indicator.return_indicator()"})," is the only required one and should take in a geogrid_data object (returned from ",(0,t.jsx)(n.code,{children:"brix.Handler.get_geogrid_data()"})," or from ",(0,t.jsx)(n.code,{children:"brix.Indicator.get_geogrid_data()"}),") and return the value of the indicator either as a number, a dictionary, or a list of dictionaries/numbers. Sometimes, the indicator requires geographic information from the table to calculate it. To get geographic information from the table, set the property ",(0,t.jsx)(n.code,{children:"brix.Indicator.requires_geometry"})," to True (see Noise heatmap as an example)."]}),"\n",(0,t.jsx)(n.p,{children:"The following example implements a diversity-of-land-use indicator"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Indicator\nfrom brix import Handler\nfrom numpy import log\nfrom collections import Counter\n\nclass Diversity(Indicator):\n def setup(self):\n self.name = 'Entropy'\n\n def load_module(self):\n pass\n\n def return_indicator(self, geogrid_data):\n uses = [cell['land_use'] for cell in geogrid_data]\n uses = [use for use in uses if use != 'None']\n frequencies = Counter(uses)\n total = sum(frequencies.values(), 0.0)\n entropy = 0\n for key in frequencies:\n p = frequencies[key]/total\n entropy += -p*log(p)\n return entropy\n\ndiv = Diversity()\nH = Handler('dungeonmaster', quietly=False)\nH.add_indicator(div)\nH.listen()\n"})}),"\n",(0,t.jsx)(n.h3,{id:"composite-indicator-average",children:"Composite indicator: average"}),"\n",(0,t.jsx)(n.p,{children:"In some settings, it might be useful to aggregate different indicators to get a average feel of what the neighborhood looks like. For this use case, brix provides a simplified CompositeIndicator class that only needs an aggregation function."}),"\n",(0,t.jsxs)(n.p,{children:["Let\u2019s create an indicator that averages Innovation Potential, Mobility Inmpact, and Economic Impact. We use the ",(0,t.jsx)(n.code,{children:"brix.CompositeIndicator"})," class for this. This class takes an aggregate function as input. This function should take the result of ",(0,t.jsx)(n.code,{children:"brix.Handler.get_indicator_values()"})," as input and returns a number. If you want to have more control over what the ",(0,t.jsx)(n.code,{children:"brix.CompositeIndicator"})," does you can always extend the class."]}),"\n",(0,t.jsx)(n.p,{children:"Here is the simplest example that averages the values of three indicators:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler, CompositeIndicator\nfrom brix.examples import RandomIndicator\n\ndef innovation_average(indicator_values):\n avg = (indicator_values['Innovation Potential']+indicator_values['Mobility Impact']+indicator_values['Economic Impact'])/3\n return avg\n\nH = Handler('dungeonmaster')\nR = RandomIndicator()\navg_I = CompositeIndicator(innovation_average,name='Composite')\nH.add_indicators([R,avg_I])\n"})}),"\n",(0,t.jsx)(n.p,{children:"In some cases, the aggregation function is too simple to write it again. In the example before, you can also pass it a pre-existing function, such as np.mean, making sure that you select the indicators that will be passed as input, by their name."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler, CompositeIndicator\nfrom brix.examples import RandomIndicator\nimport numpy as np\n\nH = Handler('dungeonmaster')\nR = RandomIndicator()\navg_I = CompositeIndicator(np.mean,selected_indicators=['Innovation Potential','Mobility Impact','Economic Impact'],name='Composite')\nH.add_indicators([R,avg_I])\n"})}),"\n",(0,t.jsx)(n.h3,{id:"heatmap-indicator",children:"Heatmap indicator"}),"\n",(0,t.jsxs)(n.p,{children:["The same class can be used to define a heatmap or accessiblity indicator, as opposed to a numeric indicator. First, set the class property ",(0,t.jsx)(n.code,{children:"brix.Indicator.indicator_type"})," equal to heatmap or to access. This will flag the indicator as a heatmap and will tell the Handler class what to do with it.\nSecond, make sure that the ",(0,t.jsx)(n.code,{children:"brix.Indicator.return_indicator()"})," function returns a list of features or a geojson.\nThe example below shows an indicator that returns noise for every point in the center of a grid cell. Because this indicator needs the coordinates of table to return the geojson, it sets the property ",(0,t.jsx)(n.code,{children:"brix.Indicator.requires_geometry"})," to True."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Indicator\nclass Noise(Indicator):\n '''\n Example of Noise heatmap indicator for points centered in each grid cell.\n\n Note that this class requires the geometry of the table as input, which is why it sets:\n requires_geometry = True\n in the setup.\n\n '''\n def setup(self):\n self.indicator_type = 'heatmap'\n self.requires_geometry = True\n\n def load_module(self):\n pass\n\n def return_indicator(self, geogrid_data):\n features = []\n for cell in geogrid_data:\n feature = {}\n lat,lon = zip(*cell['geometry']['coordinates'][0])\n lat,lon = mean(lat),mean(lon)\n feature['geometry'] = {'coordinates': [lat,lon],'type': 'Point'}\n feature['properties'] = {self.name:random()}\n features.append(feature)\n out = {'type':'FeatureCollection','features':features}\n return out\n"})}),"\n",(0,t.jsx)(n.h3,{id:"textual-indicator",children:"Textual indicator"}),"\n",(0,t.jsxs)(n.p,{children:["The example below annotates two randomly chosen cells with ",(0,t.jsx)(n.code,{children:"yes!"})," and ",(0,t.jsx)(n.code,{children:"no!"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Indicator\nimport random\nclass RandomFlag(Indicator):\n '''\n Example of textual indicator that annotates two random cells.\n '''\n def setup(self):\n self.indicator_type = 'textual'\n self.requires_geometry = True\n self.name = 'Yes/No'\n\n def return_indicator(self, geogrid_data):\n cells = random.sample(geogrid_data,2)\n out = [\n {'id':cells[0]['id'],'info':'yes!'},\n {'id':cells[1]['id'],'info':'no!'},\n ]\n return out\n"})}),"\n",(0,t.jsx)(n.h3,{id:"multiple-tables-simultaneously",children:"Multiple tables simultaneously"}),"\n",(0,t.jsxs)(n.p,{children:["The following examples instantiates three ",(0,t.jsx)(n.code,{children:"brix.Handler"})," objects for three different tables (dungeonA, dungeonB, and dungeonC) and adds a diversity of land use indicator to each. It then runs ",(0,t.jsx)(n.code,{children:"brix.Handler.listen()"})," for each table in its own separate thread."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler\nfrom brix.examples import Diversity, RandomIndicator\n\ntable_list = ['dungeona','dungeonb','dungeonc']\n\nhandler_list = []\nfor table_name in table_list:\n H = Handler(table_name)\n div = Diversity()\n rand = RandomIndicator()\n H.add_indicators([div,rand])\n handler_list.append(H)\n\nfor h in handler_list:\n h.listen()\n"})}),"\n",(0,t.jsx)(n.h3,{id:"hybrid-indicator",children:"Hybrid indicator"}),"\n",(0,t.jsx)(n.p,{children:"For more complex uses cases, where a module runs a big simulation and wants to show both a heatmap and a numeric indicator, you can use a hybrid indicator. To start, set:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"self.indicator_type = 'hybrid'\n"})}),"\n",(0,t.jsx)(n.p,{children:"If you set your indicator as hybrid you need to define a numeric and a heatmap part. The following example generates a heatmap with noise and the average noise as a numeric indicator."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Indicator\nfrom numpy import mean\nimport random\nclass HybridNoise(Indicator):\n def setup(self):\n self.indicator_type = 'hybrid'\n self.name = 'noise'\n self.requires_geometry = True\n self.mynoise = None\n\n def return_indicator_heatmap(self, geogrid_data):\n features = []\n for cell in geogrid_data:\n feature = {}\n lat,lon = zip(*cell['geometry']['coordinates'][0])\n lat,lon = mean(lat),mean(lon)\n feature['geometry'] = {'coordinates': [lat,lon],'type': 'Point'}\n feature['properties'] = {self.name:random.random()}\n features.append(feature)\n self.mynoise = features\n out = {'type':'FeatureCollection','features':features}\n return out\n\n def return_indicator_numeric(self, geogrid_data):\n mean_noise = mean([cell['properties'][self.name] for cell in self.mynoise])\n return mean_noise\n"})}),"\n",(0,t.jsx)(n.p,{children:"By default, brix will run the heatmap indicator first, followed by the numeric indicator. If you need more control over how these functions interact with each other, you can always re-define the return_indicator function. If you choose to do so, make sure that it returns a dictionary with two keys (\u2018heatmap\u2019 and \u2018numeric\u2019):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"{'heatmap': heatmap_values, 'numeric': numeric_values}\n"})}),"\n",(0,t.jsx)(n.p,{children:"In the previous example:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"def return_indicator(self, geogrid_data):\n out = {}\n out['heatmap'] = self.return_indicator_heatmap(geogrid_data)\n out['numeric'] = self.return_indicator_numeric(geogrid_data)\n return out\n"})}),"\n",(0,t.jsx)(n.h2,{id:"step-by-step-examples",children:"Step by step examples"}),"\n",(0,t.jsx)(n.h3,{id:"diversity-of-land-use-indicator---step-by-step",children:"Diversity of land-use indicator - step by step"}),"\n",(0,t.jsxs)(n.p,{children:["As an example, we\u2019ll build a diversity of land use indicator for the test table. The process is the same for any table, provided that it has a GEOGRID variable. Indicators are built as subclasses of the ",(0,t.jsx)(n.code,{children:"brix.Indicator"})," class, with three functions that need to be defined: ",(0,t.jsx)(n.code,{children:"brix.Indicator.setup()"}),", ",(0,t.jsx)(n.code,{children:"brix.Indicator.load_module()"}),", and ",(0,t.jsx)(n.code,{children:"brix.Indicator.return_indicator()"}),". The function ",(0,t.jsx)(n.code,{children:"brix.Indicator.setup()"})," acts like an ",(0,t.jsx)(n.strong,{children:"init"}),". It can take any argument and runs when the object is instantiated. The function ",(0,t.jsx)(n.code,{children:"brix.Indicator.load_module()"})," is also run when the indicator in initialized, but it cannot take any arguments. Any inputs needed to run ",(0,t.jsx)(n.code,{children:"brix.Indicator.load_module()"})," should be passed to ",(0,t.jsx)(n.code,{children:"brix.Indicator.setup()"})," and defined as class attributes. The function ",(0,t.jsx)(n.code,{children:"brix.Indicator.return_indicator()"})," is the only required one and should take in a geogrid_data object (returned from ",(0,t.jsx)(n.code,{children:"brix.Handler.get_geogrid_data()"})," or from ",(0,t.jsx)(n.code,{children:"brix.Indicator.get_geogrid_data()"}),") and return the value of the indicator either as a number, a dictionary, or a list of dictionaries/numbers."]}),"\n",(0,t.jsxs)(n.p,{children:["To start developing the diversity indicator, you can use the Handler class to get the ",(0,t.jsx)(n.code,{children:"geogrid_data"})," that is an input of the ",(0,t.jsx)(n.code,{children:"brix.Indicator.return_indicator()"})," function."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler\nH = Handler('dungeonmaster')\ngeogrid_data = H.geogrid_data()\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The returned ",(0,t.jsx)(n.code,{children:"geogrid_data"})," object depends on the table, but for dungeonmaster it looks like this:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"[\n {\n 'color': [0, 0, 0, 0],\n 'height': 0.1,\n 'id': 0,\n 'interactive': True,\n 'land_use': 'None',\n 'name': 'empty',\n 'tui_id': None\n },\n {\n 'color': [247, 94, 133, 180],\n 'height': [0, 80],\n 'id': 1,\n 'interactive': True,\n 'land_use': 'PD',\n 'name': 'Office Tower',\n 'old_color': [133, 94, 247, 180],\n 'old_height': [0, 10],\n 'tui_id': None\n },\n {\n 'color': [0, 0, 0, 0],\n 'height': 0.1,\n 'id': 2,\n 'interactive': True,\n 'land_use': 'None',\n 'name': 'empty',\n 'tui_id': None\n },\n ...\n]\n"})}),"\n",(0,t.jsxs)(n.p,{children:["We build the diversity indicator by delecting the ",(0,t.jsx)(n.code,{children:"land_use"})," variable in each cell and calculating the Shannon Entropy for this:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from numpy import log\nfrom collections import Counter\nuses = [cell['land_use'] for cell in geogrid_data]\nuses = [use for use in uses if use != 'None']\n\nfrequencies = Counter(uses)\n\ntotal = sum(frequencies.values(), 0.0)\nentropy = 0\nfor key in frequencies:\n p = frequencies[key]/total\n entropy += -p*log(p)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Now, we wrap this calculation in the ",(0,t.jsx)(n.code,{children:"brix.Indicator.return_indicator()"})," in a Diversity class that inherits the properties from the ",(0,t.jsx)(n.code,{children:"brix.Indicator"})," class:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Indicator\nfrom numpy import log\nfrom collections import Counter\n\nclass Diversity(Indicator):\n\n def setup(self):\n self.name = 'Entropy'\n\n def load_module(self):\n pass\n\n def return_indicator(self, geogrid_data):\n uses = [cell['land_use'] for cell in geogrid_data]\n uses = [use for use in uses if use != 'None']\n\n frequencies = Counter(uses)\n\n total = sum(frequencies.values(), 0.0)\n entropy = 0\n for key in frequencies:\n p = frequencies[key]/total\n entropy += -p*log(p)\n\n return entropy\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Because this indicator is very simple, it does not need any parameters or data to calculate the value, which is why the ",(0,t.jsx)(n.code,{children:"load_module"})," function is empty. The ",(0,t.jsx)(n.code,{children:"setup"})," function defines the properties of the module, which in this case is just the name."]}),"\n",(0,t.jsx)(n.p,{children:"Finally, we run the indicator by instantiating the new class and passing it to a Handler object:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler\n\ndiv = Diversity()\n\nH = Handler('dungeonmaster', quietly=False)\nH.add_indicator(div)\nH.listen()\n"})}),"\n",(0,t.jsx)(n.h3,{id:"composite-indicator--step-by-step-tutorial",children:"Composite indicator \u2013 step by step tutorial"}),"\n",(0,t.jsx)(n.p,{children:"Let\u2019s create an indicator that averages Innovation Potential, Mobility Inmpact, and Economic Impact.\nFirst, we load the RandomIndicator and pass it to a Handler."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler, CompositeIndicator\nfrom brix.examples import RandomIndicator\n\nH = Handler('dungeonmaster')\nR = RandomIndicator()\nH.add_indicator(R)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To develop the aggregate function, we use the ",(0,t.jsx)(n.code,{children:"brix.Handler.get_indicator_values"})," function from the handler class. We need to make sure our aggregate function works with that the Handler is returning:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"indicator_values = H.get_indicator_values()\n"})}),"\n",(0,t.jsxs)(n.p,{children:["In this case, the ",(0,t.jsx)(n.code,{children:"indicator_values"})," is a dictionary with the following elements:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"{\n 'Social Wellbeing': 0.9302328967423512,\n 'Environmental Impact': 0.8229183561962108,\n 'Mobility Impact': 0.3880460148817071,\n 'Economic Impact': 0.13782084927373295,\n 'Innovation Potential': 0.8913823890081203\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"We do not need to use all of the values returned by the Handler for our indicator."}),"\n",(0,t.jsxs)(n.p,{children:["Next, we write our simple average function that takes ",(0,t.jsx)(n.code,{children:"indicator_values"})," as input and returns a value, and pass it as an argument to the ",(0,t.jsx)(n.code,{children:"brix.CompositeIndicator"})," class constructor."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"def innovation_average(indicator_values):\n avg = (indicator_values['Innovation Potential']+indicator_values['Mobility Impact']+indicator_values['Economic Impact'])/3\n return avg\n\navg_I = CompositeIndicator(innovation_average,name='Composite')\n"})}),"\n",(0,t.jsx)(n.p,{children:"To make sure it is running, we can test it as usual:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"avg_I.return_indicator(indicator_values)\n"})}),"\n",(0,t.jsx)(n.p,{children:"We finally add it to the Handler:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"H.add_indicator(avg_I)\n"})}),"\n",(0,t.jsx)(n.h3,{id:"heatmap-indicator--step-by-step-tutorial",children:"Heatmap indicator \u2013 step by step tutorial"}),"\n",(0,t.jsx)(n.p,{children:"This section will show you step by step how to build a proximity to parks indicator."}),"\n",(0,t.jsxs)(n.p,{children:["Let\u2019s start by setting up a simple subclass of the Indicator class, give it a name, and set it as a ",(0,t.jsx)(n.code,{children:"heatmap"})," indicator:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Indicator\nclass ProximityIndicator(Indicator):\n def setup(self):\n self.name = 'Parks'\n self.indicator_type = 'heatmap'\n\n def return_indicator(self, geogrid_data):\n pass\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Next, we link it to the table. This step is only for building the indicator as we use a ",(0,t.jsx)(n.code,{children:"brix.Handler"})," object when deploying it."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"P = ProximityIndicator()\nP.link_table('dungeonmaster')\nP.get_geogrid_data()\n"})}),"\n",(0,t.jsxs)(n.p,{children:["When running ",(0,t.jsx)(n.code,{children:"brix.Indicator.get_geogrid_data()"})," we see that every cell has a ",(0,t.jsx)(n.code,{children:"name"})," property and some cells are classified as ",(0,t.jsx)(n.code,{children:"Park"}),". You\u2019ll also notice that by default, when building a ",(0,t.jsx)(n.code,{children:"heatmap"})," indicator, ",(0,t.jsx)(n.code,{children:"geogrid_data"})," returns the geometries. You can change this behavior by setting ",(0,t.jsx)(n.code,{children:"self.requires_geometry=False"})," in your ",(0,t.jsx)(n.code,{children:"setup"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Next, we define the ",(0,t.jsx)(n.code,{children:"return_indicator"})," function. For debugging and testing you can define this function as stand alone function before adding it as a method to the ProximityIndicator. Some useful functions for debugging are ",(0,t.jsx)(n.code,{children:"brix.Indicator.get_geogrid_data()"})," and ",(0,t.jsx)(n.code,{children:"brix.Indicator.get_table_properties()"})," that will list general properties of the linked table."]}),"\n",(0,t.jsx)(n.p,{children:"In this example, the proximity indicator is defined as one over the distance to the closest park. When the cell is a park, we define the proximity as 1/(half size of each cell) to avoid dividing by zero."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"import numpy as np\nfrom geopy.distance import distance as geodistance # Function for distance between coordinates\n\ndef return_indicator(self,geogrid_data):\n parks = [cell for cell in geogrid_data if cell['name']=='Park'] # Find all parks\n parks_locations = [np.mean(cell['geometry']['coordinates'][0],0) for cell in parks] # Filter out the center of all park locations (locations are lon,lat format)\n\n features = []\n for cell in geogrid_data: # Calculate a value for the indicator for each cell\n cell_coords = np.mean(cell['geometry']['coordinates'][0],0) # Calculate center of cell (locations are lon,lat format)\n if cell['name']=='Park': # If cell is park, set distance to zero\n park_distance = 25 # This is based on half the cell size (see P.get_table_properties())\n else:\n distances = [geodistance(cell_coords[::-1],park_loc[::-1]).m for park_loc in parks_locations] # Distance between cell and each park. Notice that we reverse the coordinates for geodistance.\n park_distance = min(distances) # get distance to closest park\n\n proximity = 1/park_distance\n scaled_proximity = (proximity-0.002)/(0.03-0.002) # this ensures the indicator is between zero and one\n\n # Generate feature with points (lon,lat format) and properties.\n feature = {}\n feature['geometry'] = {'coordinates': list(cell_coords),'type': 'Point'} # cell_coords should be a list\n feature['properties'] = {self.name: scaled_proximity} # Use the indicator name to tag the value\n\n features.append(feature) # add to features list for export\n\n out = {'type':'FeatureCollection','features':features}\n return out\n"})}),"\n",(0,t.jsxs)(n.p,{children:["You can test your function by running: ",(0,t.jsx)(n.code,{children:"return_indicator(P,geogrid_data)"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Finally, let\u2019s put it all together:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Indicator\nimport numpy as np\nfrom geopy.distance import distance as geodistance\n\nclass ProximityIndicator(Indicator):\n def setup(self):\n self.name = 'Parks'\n self.indicator_type = 'heatmap'\n\n def return_indicator(self,geogrid_data):\n parks = [cell for cell in geogrid_data if cell['name']=='Park']\n parks_locations = [np.mean(cell['geometry']['coordinates'][0],0) for cell in parks]\n\n features = []\n for cell in geogrid_data:\n cell_coords = list(np.mean(cell['geometry']['coordinates'][0],0) )\n if cell['name']=='Park':\n park_distance = 45\n else:\n distances = [geodistance(cell_coords[::-1],park_loc[::-1]).m for park_loc in parks_locations]\n park_distance = min(distances)\n\n proximity = 1/park_distance\n scaled_proximity = (proximity-0.002)/(0.03-0.002)\n\n feature = {}\n feature['geometry'] = {'coordinates': cell_coords,'type': 'Point'}\n feature['properties'] = {self.name: scaled_proximity}\n\n features.append(feature)\n\n out = {'type':'FeatureCollection','features':features}\n return out\n"})}),"\n",(0,t.jsx)(n.p,{children:"And to deploy it:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler\nH = Handler('dungeonmaster')\nP = ProximityIndicator()\nH.add_indicator(P)\nH.listen()\n"})}),"\n",(0,t.jsx)(n.h3,{id:"static-heatmap-indicator",children:"Static-Heatmap indicator"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"brix.Indicator"})," class provides a flexible way to define any type of indicator. In some cases, a simple approach is needed. Let\u2019s assume we want to build a simple heatmap indicator that just visualizes a given shapefile, and does not react to changes in geogriddata. We can use ",(0,t.jsx)(n.code,{children:"brix.StaticHeatmap"})," to build that."]}),"\n",(0,t.jsxs)(n.p,{children:["In this example, we will use the number of houses by block in Guadalajara, Mexico. You can download the shapefile from ",(0,t.jsx)(n.a,{href:"https://www.inegi.org.mx/contenidos/masiva/indicadores/inv/14_Manzanas_INV2016_shp.zip",children:"HERE"}),". We will not be using our trusted dungeonmaster table, as it does not overlap with the data. Instead we will use jalisco."]}),"\n",(0,t.jsxs)(n.p,{children:["The first step will be to \u201cgriddify\u201d our shapefile, meaning we will transform it from polygons to sampling points. Please note that you can use any sampling method for this, and that the sampling points do not need to match the grid. To make things easier, we have provided ",(0,t.jsx)(n.code,{children:"brix.griddify()"}),", which uses the centroids of the grid to sample the values of the heatmap."]}),"\n",(0,t.jsx)(n.p,{children:"We start by loading the shapefile and removing the missing values:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"import geopandas as gpd\nshapefile = gpd.read_file('/Users/username/Downloads/14_Manzanas_INV2016_shp/14_Manzanas_INV2016.shp')\nshapefile = shapefile[shapefile['VIVTOT']!='N.D.']\nshapefile['VIVTOT'] = shapefile['VIVTOT'].astype(float)\n"})}),"\n",(0,t.jsx)(n.p,{children:"Since the VIVTOT column that we are interested in visualizing has a skewed distribution, we will log-transform it."}),"\n",(0,t.jsx)(n.p,{children:"::"}),"\n",(0,t.jsx)(n.p,{children:"import numpy as np\nshapefile[\u2018log_VIVTOT\u2019] = np.log(shapefile[\u2018VIVTOT\u2019]+1)"}),"\n",(0,t.jsx)(n.p,{children:"Next, we load a table and use its grid to sample the heatmap."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler\nH = Handler('jalisco')\ngeogrid_data = H.get_geogrid_data()\n"})}),"\n",(0,t.jsx)(n.p,{children:"The next step is to use the grid to sample the values of the heatmap. We will use the log_VIVTOT column, and save the resulting heatmap to a file so we can load it later. We will also remove the missing values."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import griddify\nheatmap = griddify(geogrid_data,shapefile,columns=['log_VIVTOT'])\nheatmap = heatmap[~heatmap['log_VIVTOT'].isna()]\nheatmap.to_file('/Users/username/Downloads/14_Manzanas_INV2016_shp/HEATMAP.shp')\n"})}),"\n",(0,t.jsxs)(n.p,{children:["This shapefile is a table of points and their properties. To build your indicator you can either load the file and pass it to the :class",":brix",".StaticHeatmap` constructor, or have the constructor load it for you."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import StaticHeatmap\nN = StaticHeatmap('/Users/username/Downloads/14_Manzanas_INV2016_shp/HEATMAP.shp',columns=['log_VIVTOT'])\n"})}),"\n",(0,t.jsx)(n.p,{children:"Finally, we add it to a Handler class and check the update package:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"H = Handler('jalisco')\nH.add_indicator(N)\nH.update_package()\n"})}),"\n",(0,t.jsx)(n.p,{children:"To sum up, to preprocess the data:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"import geopandas as gpd\nimport numpy as np\nfrom brix import Handler\nfrom brix import griddify\n\nshapefile = gpd.read_file('/Users/username/Downloads/14_Manzanas_INV2016_shp/14_Manzanas_INV2016.shp')\nshapefile = shapefile[shapefile['VIVTOT']!='N.D.']\nshapefile['VIVTOT'] = shapefile['VIVTOT'].astype(float)\nshapefile['log_VIVTOT'] = np.log(shapefile['VIVTOT']+1)\n\n\nH = Handler('jalisco')\ngeogrid_data = H.get_geogrid_data()\nheatmap = griddify(geogrid_data,shapefile,columns=['log_VIVTOT'],buffer_percent=3)\nheatmap = heatmap[~heatmap['log_VIVTOT'].isna()]\nheatmap.to_file('/Users/username/Downloads/14_Manzanas_INV2016_shp/HEATMAP.shp')\n"})}),"\n",(0,t.jsx)(n.p,{children:"And once the heatmap file has been saved, all you need to do deploy the indicator is:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"from brix import Handler, StaticHeatmap\nN = StaticHeatmap('/Users/username/Downloads/14_Manzanas_INV2016_shp/HEATMAP.shp',columns=['log_VIVTOT'])\nH = Handler('jalisco')\nH.add_indicator(N)\nH.listen()\n"})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>s});var t=i(6540);const a={},r=t.createContext(a);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/cf9c09d8.82466f9a.js b/build/assets/js/cf9c09d8.82466f9a.js
deleted file mode 100644
index f6df6774..00000000
--- a/build/assets/js/cf9c09d8.82466f9a.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[49],{5431:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>a});var t=i(4848),o=i(8453);const s={id:"Build"},c="Building",r={id:"archive/cityio/Build",title:"Build",description:"From version 3, the Dockerfile inside the repository can be used for",source:"@site/docs/archive/cityio/build.md",sourceDirName:"archive/cityio",slug:"/archive/cityio/Build",permalink:"/archive/cityio/Build",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/cityio/build.md",tags:[],version:"current",frontMatter:{id:"Build"},sidebar:"sidebar",previous:{title:"API",permalink:"/archive/cityio/API"},next:{title:"Internal_Note",permalink:"/archive/cityio/Internal_Note"}},d={},a=[];function l(e){const n={code:"code",h1:"h1",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"From version 3, the Dockerfile inside the repository can be used for\neasy deployment through docker."}),"\n",(0,t.jsxs)(n.p,{children:["It is a two step process, ",(0,t.jsx)(n.code,{children:"building"})," and ",(0,t.jsx)(n.code,{children:"running"}),"."]}),"\n",(0,t.jsx)(n.h1,{id:"building",children:"Building"}),"\n",(0,t.jsx)(n.p,{children:"(make sure you have docker in your system)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"git clone https://github.com/CityScope/CS_CityIO cityio\ncd cityio\ndocker build -t cityio .\n"})}),"\n",(0,t.jsxs)(n.p,{children:["This will build the container image to the latest version. ",(0,t.jsx)(n.code,{children:"git pull"})," to\nupdate the code."]}),"\n",(0,t.jsx)(n.h1,{id:"running",children:"Running"}),"\n",(0,t.jsxs)(n.p,{children:["The cityio container assumes that a redis instance is running in\n",(0,t.jsx)(n.code,{children:"127.0.0.1:6379"})," (the default), this can be a docker container itself,\nif redis is running inside a different address or/and port, you can\nchange the what is written in the DockerFile."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-text",children:"ENV REDIS_ADDR=127.0.0.1\nENV REDIS_PORT=6379\n"})}),"\n",(0,t.jsx)(n.p,{children:"With that, the container can run by the following command."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"docker run -p 8080:8080 --net=host cityio\n"})}),"\n",(0,t.jsxs)(n.p,{children:["the ",(0,t.jsx)(n.code,{children:"--net=host"})," option is for the container to access the host side\nlocalhosts' ports, to have the container access redis."]}),"\n",(0,t.jsxs)(n.p,{children:["This will output the logs in that session, where we usually run cityio\nin a tmux session for realtime observation. The ",(0,t.jsx)(n.code,{children:"-d"})," option can be added\nto run in deamon mode."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>c,x:()=>r});var t=i(6540);const o={},s=t.createContext(o);function c(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/d9dcfff4.db04efc0.js b/build/assets/js/d9dcfff4.db04efc0.js
deleted file mode 100644
index 157b2d1e..00000000
--- a/build/assets/js/d9dcfff4.db04efc0.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[743],{5485:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={sidebar_position:3},r=void 0,a={id:"cityscopejs/Project view",title:"Project view",description:"When you open a project, CityScopeJS will present you with the project view. This page aims to provide a workspace where you can manage your projects and visualize the outputs of modules. It consists of a navigation bar at the top of the screen, where you can click on different buttons to open several windows with various functionalities. The available options are:",source:"@site/docs/cityscopejs/Project view.md",sourceDirName:"cityscopejs",slug:"/cityscopejs/Project view",permalink:"/cityscopejs/Project view",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/cityscopejs/Project view.md",tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"sidebar",previous:{title:"Opening a project",permalink:"/cityscopejs/Opening a project"},next:{title:"Modules",permalink:"/category/modules"}},c={},l=[];function d(e){const t={img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"When you open a project, CityScopeJS will present you with the project view. This page aims to provide a workspace where you can manage your projects and visualize the outputs of modules. It consists of a navigation bar at the top of the screen, where you can click on different buttons to open several windows with various functionalities. The available options are:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Edit Mode:"})," In this mode, you can modify the configuration of a city by editing the land uses of the grid that represents the city."]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Scenarios:"})," In the scenarios menu, you can save the current configuration of the city by assigning it a name and a description. Later in the process, you can switch between different scenarios of your city to study the impact of various interventions on the land, or simply to save different possibilities and analyze the metrics afterward."]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Layers:"})," In the layers menu, you can select which layers of the visualization you want to see and adjust the opacity of each one. This feature is particularly useful when working with complex visualizations, as it enables you to focus on specific elements."]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"View:"})," This menu allows us to toggle different visibility settings for the map."]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Radar Chart:"})," In the radar chart window, you can display various metrics and KPIs related to your project. Initially, this will be empty; you must connect a module to the project in order to see data displayed."]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Land Use:"})," In this menu, you can see the current distribution of land uses within the project."]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Bar Chart:"})," In the bar chart window, you can display various metrics and KPIs related to your project using a bar plot. Initially, this will be empty; you must connect a module to the project in order to see data displayed."]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.strong,{children:"Modules:"})," In the modules window, you can view and select always-available modules that are independent of the projects. When selecting a module, it will compute the results for your project and display them in the interface."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"CityScopeJS Project View",src:n(8990).A+"",width:"1202",height:"772"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8990:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/project-view-dbe152589b18a5c4493e6b2c2f68f830.png"},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/eab65581.7bf14c4c.js b/build/assets/js/eab65581.7bf14c4c.js
deleted file mode 100644
index e01b2845..00000000
--- a/build/assets/js/eab65581.7bf14c4c.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[338],{3505:(n,e,i)=>{i.r(e),i.d(e,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>c});var s=i(4848),l=i(8453);const t={id:"Types System",title:"Types System",position:1},a=void 0,d={id:"modules/Types System",title:"Types System",description:"CityScope (CS) Types are the basic land-use units that can be combined and arranged to represent urban environments within the CityScope platform. CS Types are assigned to each cell within the grid that is overlaid over the urban area of enquiry. The grid provides unified segmentation, scale and a level of abstraction that can be easily manipulated by users. Each cell within the grid can either be fixed or dynamic, depending on project limits; fixed cells within a grid are not intended to be changeable by users; dynamic cells are intended for manipulation to interact with the CityScope platform. Interactions take place as users manipulate Types within the project area.",source:"@site/docs/modules/types.md",sourceDirName:"modules",slug:"/modules/Types System",permalink:"/modules/Types System",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/modules/types.md",tags:[],version:"current",frontMatter:{id:"Types System",title:"Types System",position:1},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/modules/Core Modules/Introduction"},next:{title:"CityIO",permalink:"/category/cityio"}},r={},c=[{value:"Schema Description:",id:"schema-description",level:2},{value:"chema Description:",id:"chema-description",level:2},{value:"Park",id:"park",level:2},{value:"Household activities (Residential activities)",id:"household-activities-residential-activities",level:2},{value:"Mixed use Building (Finance + Public Administration + Shopping + Restaurants)",id:"mixed-use-building-finance--public-administration--shopping--restaurants",level:2},{value:"LBCS and NAICS Crosspath",id:"lbcs-and-naics-crosspath",level:2},{value:"Typical HOUSING types",id:"typical-housing-types",level:3},{value:"Popular AMENITYAMENITIES types",id:"popular-amenityamenities-types",level:3},{value:"PARK",id:"park-1",level:3},{value:"TRANSPORTATION",id:"transportation",level:3},{value:"SAFETY AND SECURITY",id:"safety-and-security",level:3},{value:"WELLBEING",id:"wellbeing",level:3},{value:"OFFICE",id:"office",level:3},{value:"INDUSTRY",id:"industry",level:3},{value:"NATURE",id:"nature",level:3},{value:"Mixed use building",id:"mixed-use-building",level:2},{value:"Residential Type (100% detached units)",id:"residential-type-100-detached-units",level:2},{value:"Residential Type (detached units) with ground-level grocery store",id:"residential-type-detached-units-with-ground-level-grocery-store",level:2}];function o(n){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.R)(),...n.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(e.h3,{id:""}),"\n",(0,s.jsx)(e.p,{children:"CityScope (CS) Types are the basic land-use units that can be combined and arranged to represent urban environments within the CityScope platform. CS Types are assigned to each cell within the grid that is overlaid over the urban area of enquiry. The grid provides unified segmentation, scale and a level of abstraction that can be easily manipulated by users. Each cell within the grid can either be fixed or dynamic, depending on project limits; fixed cells within a grid are not intended to be changeable by users; dynamic cells are intended for manipulation to interact with the CityScope platform. Interactions take place as users manipulate Types within the project area."}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"CS BOXEL. Photo: Ariel Noyman",src:i(3861).A+"",width:"347",height:"1159"})}),"\n",(0,s.jsx)(e.p,{children:"CS Types are represented by tiles that are set within the cells of a grid. At minimum, each tile must include land use and economic activity data, which can be complemented with additional dimensions of information that are assigned by users during the commissioning of a table. Additional information that can be assigned to a CS Type includes, but is not limited to, the acoustic characteristics, demographic information, and/or the utilization of a type."}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"CS LEGO 3Types. Photo: Luis Alonso",src:i(5560).A+"",width:"4032",height:"3024"})}),"\n",(0,s.jsx)(e.p,{children:"To standardize the analysis and visualization modules, the CityScope platform uses unified data classifications to define each Type. CS Types may differ from project to project depending on the programming and intervention under investigation. To standardize how CS Types are defined, the classification uses unified dictionary of attributes that include, but are not limited to, land-use and economic activity, as defined by the American Planning Association, Land-Based Classification Standards or LBCS, and the North American Industry Classification System or NAICS, for the associated economic activity. Additional characteristics can be added when project specific modules are being used."}),"\n",(0,s.jsx)(e.h1,{id:"lbcs---land-use-classification-notation",children:"LBCS - Land Use Classification Notation:"}),"\n",(0,s.jsx)(e.p,{children:"The LBCS classification system extends the notion of land uses by refining traditional categories into multiple dimensions, including activity, function, building type, site development character, and ownership constraints. Each dimension has its own set of categories and subcategories for classifying land uses. By classifying every land-use across multiple dimensions, users can have precise control of land-use classifications. Codes are generated using a numerical classification outlined in the LBCS manual:"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.a,{href:"https://planning-org-uploaded-media.s3.amazonaws.com/document/LBCS.pdf",children:"https://planning-org-uploaded-media.s3.amazonaws.com/document/LBCS.pdf"})}),"\n",(0,s.jsx)(e.h2,{id:"schema-description",children:"Schema Description:"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"X 0 0 0 - First level classification - General"}),"\n",(0,s.jsx)(e.li,{children:"XX 0 0 - 2nd level - Type"}),"\n",(0,s.jsx)(e.li,{children:"XXX 0 - 3rd level - Activity"}),"\n",(0,s.jsx)(e.li,{children:"XXXX - 4th level - Specific Activity"}),"\n"]}),"\n",(0,s.jsx)(e.p,{children:"Most CS Types may only include Activity dimensions, however additional LBCS information can be added."}),"\n",(0,s.jsx)(e.h1,{id:"naics---economic-activity-classification-notation",children:"NAICS - Economic Activity Classification Notation:"}),"\n",(0,s.jsx)(e.p,{children:"In addition to the LBCS classifications, the NAICS codes are a standard used by Federal statistical agencies in classifying business establishments for the purpose of collecting, analyzing, and publishing statistical data related to the U.S. business economy.Codes are generated using a numerical classification outlined in the NAICS manual:"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.a,{href:"https://www.census.gov/eos/www/naics/2017NAICS/2017_NAICS_Manual.pdf",children:"https://www.census.gov/eos/www/naics/2017NAICS/2017_NAICS_Manual.pdf"})}),"\n",(0,s.jsx)(e.h2,{id:"chema-description",children:"chema Description:"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"X 0 0 0 0 - First level classification - Industry Sector (20 broad sectors up from 10 SIC)"}),"\n",(0,s.jsx)(e.li,{children:"XX 0 0 0 - 2nd level - Industry Sub sector"}),"\n",(0,s.jsx)(e.li,{children:"XXX 0 0 - 3rd level - Industry Group"}),"\n",(0,s.jsx)(e.li,{children:"XXXX 0 - 4th level - Industry"}),"\n"]}),"\n",(0,s.jsx)(e.h1,{id:"sample-cs-types",children:"Sample CS Types:"}),"\n",(0,s.jsx)(e.p,{children:"As an example exercise we will define 3 of the most popular CS types: A simple single use tile like a park, a single use tile of housing, and a multi use tail mixing office and shopping:"}),"\n",(0,s.jsx)(e.h2,{id:"park",children:"Park"}),"\n",(0,s.jsx)(e.p,{children:"No floors, 100% of park activity. NAICS mapping = 712190. LBCS mapping = 7000"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"CS LEGO Park. Photo: Luis Alonso",src:i(7388).A+"",width:"4032",height:"3024"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",children:'{\n "NAICS": [\n {\n "P": 1,\n "use": [\n {\n "712190": 1\n }\n ],\n "LBCS": [\n {\n "P": 1,\n "use": [\n {\n "7000": 1\n }\n ]\n }\n ]\n}\n'})}),"\n",(0,s.jsx)(e.h2,{id:"household-activities-residential-activities",children:"Household activities (Residential activities)"}),"\n",(0,s.jsx)(e.p,{children:'Individual housing building, 100% of Residential activities. NAICS mapping = null (Since NAICS is the "standard used by Federal statistical agencies in classifying business establishments"; housing doesn\'t have a correlation in NAICS). LBCS mapping = 1100'}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"CS LEGO House. Photo: Luis Alonso",src:i(4230).A+"",width:"4032",height:"2606"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",children:'{\n "NAICS": null,\n "LBCS": [\n {\n "P": 1,\n "use": [\n {\n "1100": 1\n }\n ]\n }\n ]\n}\n'})}),"\n",(0,s.jsx)(e.h2,{id:"mixed-use-building-finance--public-administration--shopping--restaurants",children:"Mixed use Building (Finance + Public Administration + Shopping + Restaurants)"}),"\n",(0,s.jsx)(e.p,{children:"Office and Shopping building: 80% of Financial activities, 20% of Restaurant and shopping activities. NAICS mapping = 520000 finance, 920000 Public Administration, 440000 + 45000 shopping, and 720000 restaurant. LBCS mapping = 2200 finance, 6200 + 6300 Public Administration, 2100 shopping, and 2500 restaurant"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"The lower 20% of floors are devoted to a mix of shopping 75% and restaurants 25%"}),"\n",(0,s.jsx)(e.li,{children:"The upper 80% of floors and is devoted to a mix of finance 50% and Public Administration 50%"}),"\n"]}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"CS LEGO Office. Photo: Luis Alonso",src:i(8228).A+"",width:"4032",height:"2850"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",children:'{\n "NAICS": [\n {\n "P": 0.2,\n "use": [\n {\n "720000": 0.25,\n "440000": 0.40,\n "450000": 0.35\n }\n ]\n },\n {\n "P": 0.8,\n "use": [\n {\n "520000": 0.5,\n "920000": 0.5\n }\n ],\n "LBCS": [\n {\n "P": 0.2,\n "use": [\n {\n "2100": 0.5,\n "2500": 0.5\n }\n ]\n },\n {\n "P": 0.8,\n "use": [\n {\n "2200": 0.5,\n "6200": 0.25,\n "6300": 0.25\n }\n ]\n }\n ]\n}\n'})}),"\n",(0,s.jsx)(e.h1,{id:"references",children:"References"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.a,{href:"https://planning-org-uploaded-media.s3.amazonaws.com/legacy_resources/lbcs/background/QLBCSConvFunction2NAICS.TXT",children:"https://planning-org-uploaded-media.s3.amazonaws.com/legacy_resources/lbcs/background/QLBCSConvFunction2NAICS.TXT"})}),"\n",(0,s.jsxs)(e.p,{children:[(0,s.jsx)(e.a,{href:"https://planning-org-uploaded-media.s3.amazonaws.com/legacy_resources/lbcs/background/pdf/rslucm2sic2naics.pdf",children:"https://planning-org-uploaded-media.s3.amazonaws.com/legacy_resources/lbcs/background/pdf/rslucm2sic2naics.pdf"}),"."]}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.a,{href:"https://planning-org-uploaded-media.s3.amazonaws.com/legacy_resources/lbcs/background/pdf/rslucm2sic2naicsnotext.pdf",children:"https://planning-org-uploaded-media.s3.amazonaws.com/legacy_resources/lbcs/background/pdf/rslucm2sic2naicsnotext.pdf"})}),"\n",(0,s.jsx)(e.hr,{}),"\n",(0,s.jsx)(e.h1,{id:"anex",children:"ANEX"}),"\n",(0,s.jsx)(e.h2,{id:"lbcs-and-naics-crosspath",children:"LBCS and NAICS Crosspath"}),"\n",(0,s.jsx)(e.p,{children:"Mapping Correlation between LBCS and NAICS: Here is a shortcut for finding the correlation between LBCS and NAICS in the most popular land uses:"}),"\n",(0,s.jsx)(e.h3,{id:"typical-housing-types",children:"Typical HOUSING types"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"1 | Household activities (Residential activities)"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 1100"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = null"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"2 | Transient living (Residential activities)"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 1200"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = null"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"3 | Institutional living (Residential activities)"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 1300"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = null"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"popular-amenityamenities-types",children:"Popular AMENITYAMENITIES types"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"4 | Hotels"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 1300"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 721110"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"5 | Restaurants"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 2500"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 720000"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"6 | Night live"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 2540"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 620000"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"7 | Leisure and Wellness"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 6500"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 722500"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"8 | Culture"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 5000"}),"\n",(0,s.jsx)(e.li,{children:"NAICS =710000"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"9 | Shopping Centers"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 2100 + 2500"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 440000 + 450000"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"10 | Banks"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 2200"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 450000"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"11 | Educational"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 6100"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 610000"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"park-1",children:"PARK"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["12 | Parks","\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 7000"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 712190"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"transportation",children:"TRANSPORTATION"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["13 | Transportation hubs (Air, Water, rail, road transport and infrastructures as well as local urban and interurban transit systems, etc.)","\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 4000"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 480000"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"safety-and-security",children:"SAFETY AND SECURITY"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["14 | Public Safety","\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 6400"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 480000"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"wellbeing",children:"WELLBEING"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["15 | Health Care","\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 6500"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 620000"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"office",children:"OFFICE"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"16 | Public Administration"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 6200 + 6300"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 920000"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"17 | Finance"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 2200"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 520000"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(e.li,{children:["\n",(0,s.jsx)(e.p,{children:"18 | Scientific and Technical"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 2400"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 540000"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"industry",children:"INDUSTRY"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["19 | Manufacturing","\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 3000"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 320000 + 330000"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.h3,{id:"nature",children:"NATURE"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsxs)(e.li,{children:["20 | Nature","\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"LBCS = 9000"}),"\n",(0,s.jsx)(e.li,{children:"NAICS = 712190"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(e.hr,{}),"\n",(0,s.jsx)(e.h1,{id:"more-advanced-types-examples",children:"More advanced Types Examples"}),"\n",(0,s.jsx)(e.p,{children:"Below are some more examples of CityScope types. These can be copy and pasted or modified for use in different CityScope projects:\nA single grid-cell may contain multiple LBCS and multiple NAICS on different floors or even on the same floor. Therefore, the value of each attribute is formatted as a list of objects. The object in the list represents a grouping of floors starting with the lower-most floors. Each object contains the mix of uses within that floor-group. For example, the following represents the NAICS attribute for a grid cell where:"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"CS LEGO scheme. Photo: Ariel Noyman",src:i(9973).A+"",width:"1600",height:"1109"})}),"\n",(0,s.jsx)(e.h2,{id:"mixed-use-building",children:"Mixed use building"}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:'The lower 30% of floors are devoted to a mix of "541310" (architectural services) and "541330" (engineering services).'}),"\n",(0,s.jsx)(e.li,{children:'The upper 70% of floors and is devoted to a mix of "23" (Construction), "42" (Wholesale) and "61" (Education).'}),"\n"]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",children:'{\n "NAICS": [\n {\n "P": 0.3,\n "use": [\n {\n "541310": 0.5,\n "541330": 0.5\n }\n ]\n },\n {\n "P": 0.7,\n "use": [\n {\n "23": 0.3,\n "42": 0.4,\n "61": 0.3\n }\n ]\n }\n ]\n}\n'})}),"\n",(0,s.jsx)(e.p,{children:'The number of floors is independent of the type and specified separately by the user. Therefore, if the user assigns 10 floors to this grid cell, the lower 2 floors will be a mix of 541310 and 541330 and the upper 10 floors will be a mix of 23, 42 and 61.\nIn most cases, the type specification will not require such a detailed level of partitioning of types. If for example, the grid cell has only a single usage type, the same data format will be used but the list will only contain 1 object of length 1. For example, the following represents the NAICS attribute for a grid cell solely devoted to "54" (Professional, Scientific and Technical Services).'}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",children:'{\n "NAICS": [\n {\n "P": 1,\n "use": [\n {\n "54": 1\n }\n ]\n }\n ]\n}\n'})}),"\n",(0,s.jsx)(e.h2,{id:"residential-type-100-detached-units",children:"Residential Type (100% detached units)"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",children:'{\n "NAICS": null,\n "LBCS": [\n {\n "P": 1,\n "use": [\n {\n "1120": 1\n }\n ]\n }\n ]\n}\n'})}),"\n",(0,s.jsx)(e.h2,{id:"residential-type-detached-units-with-ground-level-grocery-store",children:"Residential Type (detached units) with ground-level grocery store"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",children:'{\n "NAICS": [\n {\n "P": 0.1,\n "use": [\n {\n "4451": 1\n }\n ]\n },\n {\n "P": 0.9,\n "use": null\n }\n ],\n "LBCS": [\n {\n "P": 0.1,\n "use": [\n {\n "2150": 1\n }\n ]\n },\n {\n "P": 0.9,\n "use": [\n {\n "1120": 1\n }\n ]\n }\n ]\n}\n'})})]})}function h(n={}){const{wrapper:e}={...(0,l.R)(),...n.components};return e?(0,s.jsx)(e,{...n,children:(0,s.jsx)(o,{...n})}):o(n)}},3861:(n,e,i)=>{i.d(e,{A:()=>s});const s=i.p+"assets/images/BOXEL_Scheme-d1cbf30ad7555493c80cc4206fb80c30.jpg"},4230:(n,e,i)=>{i.d(e,{A:()=>s});const s=i.p+"assets/images/Type_House-98f14c2db41d983f2ef3fc933e5f6736.jpg"},8228:(n,e,i)=>{i.d(e,{A:()=>s});const s=i.p+"assets/images/Type_Office-f695054fae45ec69f5d8b0ee3cfd46bb.jpg"},7388:(n,e,i)=>{i.d(e,{A:()=>s});const s=i.p+"assets/images/Type_Park-6de8b19ee6f1af59f0163282543d1669.jpg"},9973:(n,e,i)=>{i.d(e,{A:()=>s});const s=i.p+"assets/images/Type_scheme-9fbe5b8f7e202e63d3f19aa4d5d5db10.jpg"},5560:(n,e,i)=>{i.d(e,{A:()=>s});const s=i.p+"assets/images/Types_examples-7e0f322f70968ac0ded9951db648ec30.jpg"},8453:(n,e,i)=>{i.d(e,{R:()=>a,x:()=>d});var s=i(6540);const l={},t=s.createContext(l);function a(n){const e=s.useContext(t);return s.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function d(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(l):n.components||l:a(n.components),s.createElement(t.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/f30f61d4.14328f35.js b/build/assets/js/f30f61d4.14328f35.js
deleted file mode 100644
index 8c3bb4bc..00000000
--- a/build/assets/js/f30f61d4.14328f35.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[783],{2179:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var n=t(4848),o=t(8453);const a={id:"GAMA"},r="Introduction",s={id:"archive/brix/GAMA",title:"GAMA",description:"Agent-Based Model developped in the CityScience group using Gama Platform and integrated in CityScope",source:"@site/docs/archive/brix/GAMA.md",sourceDirName:"archive/brix",slug:"/archive/brix/GAMA",permalink:"/archive/brix/GAMA",draft:!1,unlisted:!1,editUrl:"https://github.com/CityScope/cityscope.github.io/docs/archive/brix/GAMA.md",tags:[],version:"current",frontMatter:{id:"GAMA"},sidebar:"sidebar",previous:{title:"Examples",permalink:"/archive/brix/Examples/"},next:{title:"Tutorials",permalink:"/archive/brix/Tutorial/"}},l={},c=[{value:"Basics of building a CityScope indicator in GAMA",id:"basics-of-building-a-cityscope-indicator-in-gama",level:2},{value:"GAMABrix for cs-brix users",id:"gamabrix-for-cs-brix-users",level:2},{value:"The CityIO global",id:"the-cityio-global",level:2},{value:"Let's talk input",id:"lets-talk-input",level:2},{value:"Building an indicator (output)",id:"building-an-indicator-output",level:2},{value:"Deploy your indicator",id:"deploy-your-indicator",level:2},{value:"Basic numeric indicator",id:"basic-numeric-indicator",level:2},{value:"Basic heatmap indicator",id:"basic-heatmap-indicator",level:2},{value:"Basic agent indicator",id:"basic-agent-indicator",level:2},{value:"Full module example (with comments)",id:"full-module-example-with-comments",level:2}];function d(e){const i={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(i.p,{children:["Agent-Based Model developped in the ",(0,n.jsx)(i.a,{href:"https://www.media.mit.edu/groups/city-science/overview/",children:"CityScience"})," group using ",(0,n.jsx)(i.a,{href:"https://gama-platform.github.io/",children:"Gama Platform"})," and integrated in ",(0,n.jsx)(i.a,{href:"https://www.media.mit.edu/projects/cityscope/overview/",children:"CityScope"})]}),"\n",(0,n.jsx)(i.h1,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsxs)(i.p,{children:["What is this library for? If you have never heard of a CityScope before, you might want to stop reading and learn about them ",(0,n.jsx)(i.a,{href:"https://cityscope.media.mit.edu/",children:"here"}),". CityScope is an awesome way to interact, explore, and co-create urban interventions in a way that can be accessed by multiple people with different background. If you know what they are, please keep reading."]}),"\n",(0,n.jsx)(i.p,{children:"What is a CityScope table? a \u2018table\u2019 is our way of describing a CityScope project. Why table then? Since historically, most CityScope instances were composed of a mesh between a physical table-top 3D model of a city, augmented with projections, software, and other interface hardware. So a table => project."}),"\n",(0,n.jsx)(i.p,{children:"What is an indicator? An indicator is the result of running a module for CityScope. Indicators work by listening for updated from the CityScope table they are linked to, calculating some values by using a model, some function of the data, or a simulation, and then post the result of the calculations to CityIO to be displayed in the table."}),"\n",(0,n.jsx)(i.p,{children:"What are the types of indicators you can build? Indicators can be anything that could be displayed on a CityScope table, including the supporting screens associated to it. For the purpose of this library, we distinguish three types of indicator: numeric, heatmap, simulation."}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"Numeric: Numeric indicators are just a number or set of numbers. They are usually displayed in a chart (bar chart, radar chart, etc) next to the table. The most common numeric indicator are the numbers that go in the radar plot, which display information about density, diversity, and proximity."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"Heatmap: These indicators are geodata. They are made up of geometries (points, lines, or polygons) and properties associated to them. These indicators are displayed as layers directly on the CityScope table."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"Agent: These type of indicators are also displayed on the table but they are the result of an agent based simulation and are therefore displayed as a dynamic layer. They change over time like a short movie."}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(i.h1,{id:"setup",children:"Setup"}),"\n",(0,n.jsxs)(i.p,{children:["To setup GAMABrix copy the file ",(0,n.jsx)(i.code,{children:"GAMABrix.gaml"})," into your model directory and import it into your model. You can download ",(0,n.jsx)(i.code,{children:"GAMABrix.gaml"})," from ",(0,n.jsx)(i.a,{href:"https://github.com/CityScope/CS_Simulation_GAMA/blob/master/CS_CityScope_GAMA/models/cityIO/models/GAMABrix.gaml",children:"here"})," Right after declaring your model, import the necessary species and functions by running:"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'import "GAMABrix.gaml"\n'})}),"\n",(0,n.jsxs)(i.p,{children:["This will add to ",(0,n.jsx)(i.code,{children:"global"})," the necessary functions to communicate with ",(0,n.jsx)(i.code,{children:"CityIO"})," and two very important species that you will use to give your agents the properties they need to also live in CityIO: ",(0,n.jsx)(i.code,{children:"cityio_numeric_indicator"})," and ",(0,n.jsx)(i.code,{children:"cityio_agent"}),". Additionally, it sets up a series of ",(0,n.jsx)(i.code,{children:"brix"})," agents that will ensure your world is a copy of the world in the table you have selected."]}),"\n",(0,n.jsx)(i.h1,{id:"tutorial",children:"Tutorial"}),"\n",(0,n.jsx)(i.h2,{id:"basics-of-building-a-cityscope-indicator-in-gama",children:"Basics of building a CityScope indicator in GAMA"}),"\n",(0,n.jsxs)(i.p,{children:["Let\u2019s get to it. First, what table are you building for? If you don\u2019t have a specific table, that is totally okay and you can create one ",(0,n.jsx)(i.a,{href:"https://cityscope.media.mit.edu/CS_cityscopeJS/",children:"here"}),". Note: by the time you read this, CityScope might pose some limitations on new projects (",(0,n.jsx)(i.code,{children:"tables"}),"). Please follow instructions in the link above."]}),"\n",(0,n.jsxs)(i.p,{children:["For this tutorial, we crated one called ",(0,n.jsx)(i.code,{children:"dungeonmaster"}),"."]}),"\n",(0,n.jsxs)(i.p,{children:["An indicator will basically take in the properties of the ",(0,n.jsx)(i.code,{children:"brix"})," agents in the world or the properties of any other simulated agent and produce a result. Each new indicator is built as an subclass of the ",(0,n.jsx)(i.code,{children:"cityio_agent"})," class. ",(0,n.jsx)(i.code,{children:"cityio_agent"})," is your friend, so we'll spend some time discussing it here."]}),"\n",(0,n.jsxs)(i.p,{children:["When you setup a model by importing ",(0,n.jsx)(i.code,{children:"GAMABrix"}),", the model will run for one whole day of simulation, then posts the results of this simulation to cityio, and then stay idle waiting for an update from the table. This can be a bit annoying when you are only starting to build your model, so you can turn off this behavior and just keep the local grid update."]}),"\n",(0,n.jsxs)(i.p,{children:["Think of each indicator as an observer in your model that will report information back to CityIO. When it's a numeric indicator, the agent will just report a number that it calculates based on the ",(0,n.jsx)(i.code,{children:"brix"}),"s, when it's a heatmap indicator, the agent will report some numbers along with its location, and when it's an agent, the agent will report it's location over time. ",(0,n.jsx)(i.code,{children:"cityio_agent"})," is used as the parent class of any species that you want to visualize in CityIO. There are some specific parameters your sub-species needs to define to set the agent as a numeric, heatmap, or agent indicator."]}),"\n",(0,n.jsxs)(i.h2,{id:"gamabrix-for-cs-brix-users",children:["GAMABrix for ",(0,n.jsx)(i.code,{children:"cs-brix"})," users"]}),"\n",(0,n.jsxs)(i.p,{children:["If you are familiar with the python library ",(0,n.jsx)(i.a,{href:"https://cityscope.media.mit.edu/CS_Brix/",children:"cs-brix"}),", keep reading. Otherwise, skip to the next section of the tutorial. ",(0,n.jsx)(i.code,{children:"brix"})," is relies on defining classes that contain functions that take ",(0,n.jsx)(i.code,{children:"geogrid_data"})," as an input. For ",(0,n.jsx)(i.code,{children:"GAMABrix"})," this is not necessary. Since ",(0,n.jsx)(i.code,{children:"GAMA"})," relies on setting up a world with agents, the input data is already in the world in the form of ",(0,n.jsx)(i.code,{children:"brix"}),". Therefore, when building urban indicators in ",(0,n.jsx)(i.code,{children:"GAMA"})," you do not need to worry about input, and you can just get the necessary information from the ",(0,n.jsx)(i.code,{children:"brix"})," agents that will be automatically created in your world."]}),"\n",(0,n.jsxs)(i.p,{children:["In terms of output, ",(0,n.jsx)(i.code,{children:"brix"})," relies on a series of return functions passed to a ",(0,n.jsx)(i.code,{children:"Handler"})," class. In ",(0,n.jsx)(i.code,{children:"GAMA"}),", the world itself acts as the ",(0,n.jsx)(i.code,{children:"Handler"})," class, so there is no need to explicitly add your indicators to the ",(0,n.jsx)(i.code,{children:"Handler"})," as they are already contained in the ",(0,n.jsx)(i.code,{children:"global"})," species. The way to flag your indicators to be sent to ",(0,n.jsx)(i.code,{children:"cityIO"})," is to define them as a subclass of ",(0,n.jsx)(i.code,{children:"cityio_agent"}),"."]}),"\n",(0,n.jsxs)(i.p,{children:["While ",(0,n.jsx)(i.code,{children:"brix"})," can handle multiple tables at the same time by creating multiple threads for each ",(0,n.jsx)(i.code,{children:"Handler"}),", ",(0,n.jsx)(i.code,{children:"GAMA"})," is constrained to one table per model."]}),"\n",(0,n.jsx)(i.h2,{id:"the-cityio-global",children:"The CityIO global"}),"\n",(0,n.jsxs)(i.p,{children:["To connect your world to a table you need to declare the table name inside your ",(0,n.jsx)(i.code,{children:"global"})," and set the geometry of your world based on this table. For example, we named our table ",(0,n.jsx)(i.code,{children:"dungeonmaster"}),":"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'string city_io_table<-"dungeonmaster";\ngeometry shape <- envelope(setup_cityio_world());\n'})}),"\n",(0,n.jsxs)(i.p,{children:["While you are building your model, we recommend turning off ",(0,n.jsx)(i.code,{children:"GAMABrix"})," to speed up the process (the default). By setting ",(0,n.jsx)(i.code,{children:"post_on<-false"}),", the model will only update your local grid without posting any of the indicators to cityio. In other words, you will only be ",(0,n.jsx)(i.em,{children:"getting"})," from ",(0,n.jsx)(i.code,{children:"cityIO"})," not ",(0,n.jsx)(i.em,{children:"posting"}),". This will reduce your bandwidth usage and allow you to debug your model faster. By doing this, the model will still keep track of the day and enter idle mode once the day is over."]}),"\n",(0,n.jsxs)(i.p,{children:["For early stages of model building, you might also want to set ",(0,n.jsx)(i.code,{children:"pull_only<-true"}),". This will tell turn off most of the functionality of the module and just make sure you are updating the local grid by pulling from your table. The simulation will not enter idle mode and the day will never reset."]}),"\n",(0,n.jsx)(i.p,{children:"Once you are done and want to deploy, change:"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"bool post_on<-true;\n"})}),"\n",(0,n.jsxs)(i.p,{children:["Additionally, the following variables can be defined in the ",(0,n.jsx)(i.code,{children:"global"})," and allow for a finer control of how the ",(0,n.jsx)(i.code,{children:"global"})," communicates with ",(0,n.jsx)(i.code,{children:"cityIO"}),". You do not need to set them up now, as the default should work fine."]}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"city_io_table"}),": String, name of the table to connect to."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"post_on"}),": Boolean, used to turn the posting feature on or off. Keep it off while building the model and turn it on to post to the table."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"update_frequency"}),": Intenger, frequency, in number of simulation ticks, by which to update local grid by checking for changes in gridhash. This is not the posting frequency. Optional, and defaults to ",(0,n.jsx)(i.code,{children:"10"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"send_first_batch"}),": Boolean, if ",(0,n.jsx)(i.code,{children:"false"})," it will only send the results of the simulation once the full day has run. Optional and defaults to ",(0,n.jsx)(i.code,{children:"true"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"cycle_first_batch"}),": Integer, simulation tick in which to send the first batch of data to the server. Optional and defaults to ",(0,n.jsx)(i.code,{children:"100"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"step"}),": Float, time between two simulation ticks. Defaults to ",(0,n.jsx)(i.code,{children:"60 #sec"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"saveLocationInterval"}),": Float, frequency in second by which to save locally the location of agents. This is not the post frequency. Optional and defaults to ",(0,n.jsx)(i.code,{children:"10"})," steps."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"totalTimeInSec"}),": Integer, total time in seconds that the simulation will run for. Defaults to a whole day. Please note that ",(0,n.jsx)(i.code,{children:"CityIO"})," will not render more than 1 day of simulation."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"idle_update_frequency"}),": Float, time in real world seconds (not simulation seconds) between two get requests to check hash when in idle mode."]}),"\n",(0,n.jsxs)(i.li,{children:[(0,n.jsx)(i.code,{children:"pull_only"}),": Boolean, used to use GAMABrix only to update the local grid. This is very useful for the early stages of model building."]}),"\n"]}),"\n",(0,n.jsxs)(i.p,{children:["When you import ",(0,n.jsx)(i.code,{children:"GAMABrix"})," you will also see an additional experiment called ",(0,n.jsx)(i.code,{children:"CityScopeHeadless"}),". This experiment is used to run your model as a headless process in a server."]}),"\n",(0,n.jsxs)(i.p,{children:["By default, ",(0,n.jsx)(i.code,{children:"GAMABrix"})," will run its init (which creates the grid) right after your model's init. This means that you will not have access to any ",(0,n.jsx)(i.code,{children:"brix"})," object inside your init. You can always change this behavior by forcing ",(0,n.jsx)(i.code,{children:"GAMABrix"})," to run its init earlyer by adding ",(0,n.jsx)(i.code,{children:"do brix_init"})," where needed."]}),"\n",(0,n.jsx)(i.h2,{id:"lets-talk-input",children:"Let's talk input"}),"\n",(0,n.jsxs)(i.p,{children:[(0,n.jsx)(i.code,{children:"GAMA"})," will keep a copy of the ",(0,n.jsx)(i.code,{children:"cityIO"})," grid locally by creating the necessary ",(0,n.jsx)(i.code,{children:"brix"})," agents. This makes all the grid information accessible to all the agents by interacting with the ",(0,n.jsx)(i.code,{children:"brix"})," agents."]}),"\n",(0,n.jsxs)(i.p,{children:["The main properties that ",(0,n.jsx)(i.code,{children:"brix"})," agents have are:"]}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["type: String that identifies the type of the block. This is editable (e.g. ",(0,n.jsx)(i.code,{children:"Residential"}),")."]}),"\n",(0,n.jsx)(i.li,{children:"height: Float, height of the block."}),"\n",(0,n.jsx)(i.li,{children:"color: RGB object."}),"\n",(0,n.jsxs)(i.li,{children:["block_lbcs: ",(0,n.jsx)(i.code,{children:"map"})," Map that connects strings (LBCS codes) and float (proportion of the block in each code)."]}),"\n",(0,n.jsxs)(i.li,{children:["block_naics: ",(0,n.jsx)(i.code,{children:"map"})," Map that connects strings (NAICS codes) and float (proportion of the block in each code)."]}),"\n"]}),"\n",(0,n.jsxs)(i.p,{children:["Note that ",(0,n.jsx)(i.code,{children:"block_lbcs"})," and ",(0,n.jsx)(i.code,{children:"block_naics"})," are the same for each ",(0,n.jsx)(i.code,{children:"type"})," and are defined when you create the table."]}),"\n",(0,n.jsx)(i.h2,{id:"building-an-indicator-output",children:"Building an indicator (output)"}),"\n",(0,n.jsxs)(i.p,{children:["Now, we'll turn some agents into observers that will report information to ",(0,n.jsx)(i.code,{children:"cityIO"}),". All three different types of indicators report different types of information, and an agent can be reporting any type of information to ",(0,n.jsx)(i.code,{children:"cityIO"}),"."]}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["Numeric: Reports numbers (e.g. average commuting time, total energy consumption, etc.). Turn this on by setting ",(0,n.jsx)(i.code,{children:"is_numeric<-true"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:["Heatmap: Reports numbers with location (e.g. traffic in a particular intersection, total sunlight in a specific location). Turn this on by setting ",(0,n.jsx)(i.code,{children:"is_heatmap<-true"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:["Agent: Report all their locations during one whole day of simulation. Turn this on by setting ",(0,n.jsx)(i.code,{children:"is_visible<-true"}),". Note that the variable ",(0,n.jsx)(i.code,{children:"is_visible"})," refers only to wether you'll see the agent in your CityScope table. You still need to ",(0,n.jsx)(i.code,{children:"display"})," them in your local GAMA interfase if you want to see them."]}),"\n"]}),"\n",(0,n.jsxs)(i.p,{children:["When creating a numeric indicator you need to write a ",(0,n.jsx)(i.code,{children:"reflex"})," for your agent that updates either ",(0,n.jsx)(i.code,{children:"numeric_values"})," or ",(0,n.jsx)(i.code,{children:"heatmap_values"}),". These two variables should be ",(0,n.jsx)(i.code,{children:"map"}),". Here is a simple example that ",(0,n.jsx)(i.code,{children:"numeric_values"})," with the number of blocks."]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'reflex update_numeric {\n\tnumeric_values<-[];\n\tnumeric_values<+"Number of blocks"::length(brix);\n}\n'})}),"\n",(0,n.jsxs)(i.p,{children:["Similarly, here is another example that updates ",(0,n.jsx)(i.code,{children:"heatmap_values"})," with two layers, ",(0,n.jsx)(i.code,{children:"heat"})," and ",(0,n.jsx)(i.code,{children:"map"})," defined as random numbers:"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'reflex update_heatmap {\n\theatmap_values<-[];\n\theatmap_values<+ "heat"::rnd(10);\n\theatmap_values<+ "map"::rnd(10);\n}\n'})}),"\n",(0,n.jsxs)(i.p,{children:["For an agent indicator there is no value to be updated, as the indicator just reports its location. However, if your agent does not move, you will get a very boring dot so you might want to update the location. Here is a simple ",(0,n.jsx)(i.code,{children:"reflex"})," that updates the location:"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"reflex move{\n\tdo wander;\n}\n"})}),"\n",(0,n.jsxs)(i.p,{children:["Additionally, ",(0,n.jsx)(i.code,{children:"GAMABrix"})," provides a shortcut to create numeric indicators that do not require you to define a subspecies. This is meant for straightforward indicators that can be calculated in one line of code. To create a simple numeric indicator, just create and agent of the ",(0,n.jsx)(i.code,{children:"cityio_numeric_indicator"})," species and pass your function as a string to ",(0,n.jsx)(i.code,{children:"indicator_value"}),". For example, a numeric indicator that returns the average height of blocks:"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'create cityio_numeric_indicator with: (viz_type:"bar",indicator_name: "Mean Height", indicator_value: "mean(brix collect each.height)");\n'})}),"\n",(0,n.jsx)(i.h2,{id:"deploy-your-indicator",children:"Deploy your indicator"}),"\n",(0,n.jsx)(i.p,{children:"Let's say you finished writing your model and are ready to leave it running forever (in a server with ssh access, for example)."}),"\n",(0,n.jsx)(i.p,{children:"We highly recommend using a docker container to run headless GAMA on a server. This will take care of compatibility issues between platforms."}),"\n",(0,n.jsxs)(i.p,{children:["First, pull the image from dockerhub. This step only needs to be performed once per server. We will be using ",(0,n.jsx)(i.a,{href:"https://hub.docker.com/r/gamaplatform/gama",children:"this image"}),"."]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"> docker pull gamaplatform/gama\n"})}),"\n",(0,n.jsxs)(i.p,{children:["Second, we will build the ",(0,n.jsx)(i.code,{children:"xml"})," file with the model meta parameters. You will only need to do this once for each model. Ensure you model directory (the folder that contains models, results, etc) contains a ",(0,n.jsx)(i.code,{children:"headless"})," folder, and then run the following command adding the name of your gama file (",(0,n.jsx)(i.code,{children:"model_file.gaml"}),") where needed:"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'> docker run --rm -v "$(pwd)":/usr/lib/gama/headless/my_model gamaplatform/gama -xml CityScopeHeadless my_model/models/[model_file.gaml] my_model/headless/myHeadlessModel.xml\n'})}),"\n",(0,n.jsxs)(i.p,{children:["This creates a file called ",(0,n.jsx)(i.code,{children:"myHeadlessModel.xml"})," in your ",(0,n.jsx)(i.code,{children:"headless"})," folder. If you know how to edit this file, feel free to modify it now. For more information about this file, check the ",(0,n.jsx)(i.a,{href:"https://gama-platform.github.io/wiki/Headless",children:"documentation"}),". Please note that by default the simulation will only run 1000 steps. If you wish to change this, edit the ",(0,n.jsx)(i.code,{children:"xml"})," and change the ",(0,n.jsx)(i.code,{children:"finalStep"})," property to a higher number or just delete if you wish the model to run continuosly."]}),"\n",(0,n.jsx)(i.p,{children:"Finally, we will run this model inside a container. This final step is what you will repeat everytime you modify your model. Run the following command, again from your model director:"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'> docker run --rm -v "$(pwd)":/usr/lib/gama/headless/my_model gamaplatform/gama my_model/headless/myHeadlessModel.xml my_model/results/\n'})}),"\n",(0,n.jsx)(i.h1,{id:"examples",children:"Examples"}),"\n",(0,n.jsx)(i.h2,{id:"basic-numeric-indicator",children:"Basic numeric indicator"}),"\n",(0,n.jsxs)(i.p,{children:["To create a numeric indicator, the recommended way is to define a species of agents that will act as ",(0,n.jsx)(i.em,{children:"observers"})," that will report the information to ",(0,n.jsx)(i.code,{children:"cityIO"}),". This species needs to have ",(0,n.jsx)(i.code,{children:"cityio_agent"})," as parent species."]}),"\n",(0,n.jsx)(i.p,{children:"You need to define four things:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["Set ",(0,n.jsx)(i.code,{children:"is_numeric"})," to ",(0,n.jsx)(i.code,{children:"true"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:["Define a reflex that updates the ",(0,n.jsx)(i.code,{children:"numeric_values"})," map (",(0,n.jsx)(i.code,{children:"map"}),")."]}),"\n",(0,n.jsxs)(i.li,{children:["Define an ",(0,n.jsx)(i.code,{children:"indicator_name"})," either in the species definition or in the create statement."]}),"\n",(0,n.jsxs)(i.li,{children:["Set the ",(0,n.jsx)(i.code,{children:"viz_type"})," to either ",(0,n.jsx)(i.code,{children:"bar"})," or ",(0,n.jsx)(i.code,{children:"radar"})," (defaults to ",(0,n.jsx)(i.code,{children:"bar"})," if you don't change it)."]}),"\n"]}),"\n",(0,n.jsx)(i.p,{children:"Here's a simple example:"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'species my_numeric_indicator parent: cityio_agent {\n\tbool is_numeric<-true;\n\tstring viz_type <- "bar";\n\tstring indicator_name<-"Table Size";\n\t\n\treflex update_numeric {\n\t\tnumeric_values<-[];\n\t\tnumeric_values<+indicator_name::length(brix);\n\t}\n}\n'})}),"\n",(0,n.jsxs)(i.p,{children:["Don't forget to create an agent of this species in the ",(0,n.jsx)(i.code,{children:"global"})," ",(0,n.jsx)(i.code,{children:"init"}),"."]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"create my_numeric_indicator;\n"})}),"\n",(0,n.jsxs)(i.p,{children:["For simple indicators, you can rely on creating an agent of the ",(0,n.jsx)(i.code,{children:"cityio_numeric_indicator"})," species in your ",(0,n.jsx)(i.code,{children:"global"})," ",(0,n.jsx)(i.code,{children:"init"}),". Here's an example:"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'create cityio_numeric_indicator with: (viz_type:"bar", indicator_name: "Max Height", indicator_value: "max(brix collect each.height)");\n'})}),"\n",(0,n.jsx)(i.h2,{id:"basic-heatmap-indicator",children:"Basic heatmap indicator"}),"\n",(0,n.jsxs)(i.p,{children:["To create a heatmap indicator, define a species of agents that will act as ",(0,n.jsx)(i.em,{children:"observers"})," that will report the information to ",(0,n.jsx)(i.code,{children:"cityIO"}),". These agents need to have a location assigned to them. This species needs to have ",(0,n.jsx)(i.code,{children:"cityio_agent"})," as parent species."]}),"\n",(0,n.jsx)(i.p,{children:"You need to define three things:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["Set ",(0,n.jsx)(i.code,{children:"is_heatmap"})," to ",(0,n.jsx)(i.code,{children:"true"}),"."]}),"\n",(0,n.jsxs)(i.li,{children:["Define a reflex that updates the ",(0,n.jsx)(i.code,{children:"heatmap_values"})," map (",(0,n.jsx)(i.code,{children:"map"}),")."]}),"\n",(0,n.jsxs)(i.li,{children:["Define an ",(0,n.jsx)(i.code,{children:"indicator_name"})," either in the species definition or in the create statement."]}),"\n"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'species thermometer parent: cityio_agent {\n\tbool is_heatmap<-true;\n\tstring indicator_name<-"thermometer";\n\t\n\treflex update_heatmap {\n\t\theatmap_values<-[];\n\t\theatmap_values<+ "heat"::rnd(10);\n\t\theatmap_values<+ "map"::rnd(10);\n\t}\t\n}\n'})}),"\n",(0,n.jsx)(i.h2,{id:"basic-agent-indicator",children:"Basic agent indicator"}),"\n",(0,n.jsxs)(i.p,{children:["Finally, you can easily add agents to be displayed in ",(0,n.jsx)(i.code,{children:"cityIO"}),". Interestingly, these are the easiest indicators to define. In fact, you can turn any species into a ",(0,n.jsx)(i.code,{children:"cityio_agent"})," by defining their parent class."]}),"\n",(0,n.jsx)(i.p,{children:"You need to is_visible two things:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["Set ",(0,n.jsx)(i.code,{children:"is_heatmap"})," to ",(0,n.jsx)(i.code,{children:"true"}),"."]}),"\n",(0,n.jsx)(i.li,{children:"Define a reflex that updates the agent's location."}),"\n"]}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:"species people parent: cityio_agent skills:[moving]{ \n\tbool is_visible<-true;\n\t\n\treflex move{\n\t\tdo wander;\n\t}\n}\n"})}),"\n",(0,n.jsxs)(i.p,{children:["Additionally, you can define the integers ",(0,n.jsx)(i.code,{children:"profile"})," and ",(0,n.jsx)(i.code,{children:"mode"})," that will control the way they are displayed in the front end. You can also define reflexes that update these two properties. For example, you can differentiate between drivers and walkers, or between day workers and night workers, etc."]}),"\n",(0,n.jsx)(i.h2,{id:"full-module-example-with-comments",children:"Full module example (with comments)"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{children:'model citIOGAMA\n\n// Import GAMABrix (this needs to be in the same directory as your model)\nimport "GAMABrix.gaml" \n\nglobal {\n\t// Define the table you\'ll be working with\n\tstring city_io_table<-"dungeonmaster";\n geometry shape <- envelope(setup_cityio_world());\n\n // Set post to true so that GAMABrix can post to cityIO\n\tbool post_on<-true;\n\t\n\tinit {\n\t\t// Create people based on species defined below\n\t\tcreate people number:10; \n\n\t\t// Create 100 points of a heatmap indicator (species defined below)\n\t\tcreate thermometer number:100;\n\n\t\t// Use cityio_numeric_indicator to define a mean block height numeric indicator\n\t\tcreate cityio_numeric_indicator with: (viz_type:"bar",indicator_name: "Mean Height", indicator_value: "mean(brix collect each.height)");\n\t\t\n\t\t// Create a numeric indicator based on the species defined below\n\t\tcreate my_numeric_indicator with: (viz_type:"bar",indicator_name: "Number of blocks");\n\t}\n\t\n\t\n}\n\n// Define a custom numeric indicator\nspecies my_numeric_indicator parent: cityio_agent {\n\t// Set the indicator as numeric\n\tbool is_numeric<-true;\n\n\t// Visualize it as a bar chart\n\tstring viz_type <- "bar";\n\t\n\t// Define reflex that updates numeric_values\n\treflex update_numeric {\n\t\tnumeric_values<-[];\n\t\tnumeric_values<+indicator_name::length(brix);\n\t}\n}\n\n// Define custom heatmap indicator\nspecies thermometer parent: cityio_agent {\n\t// Set the indicator as heatmap\n\tbool is_heatmap<-true;\n\n\t// Define reflex that updates heatmap_values\n\treflex update_heatmap {\n\t\theatmap_values<-[];\n\t\theatmap_values<+ "heat"::rnd(10);\n\t\theatmap_values<+ "map"::rnd(10);\n\t}\t\n}\n\n// Define people, to be used as agent indicators\nspecies people parent: cityio_agent skills:[moving]{ \n\t// Set agents as visible in cityIO\n\tbool is_visible<-true;\n\t\n\t// Update the agents location at every step\n\treflex move{\n\t\tdo wander;\n\t}\n\t\n\t// Set base aspect to visualize in GAMA GUI\n\taspect base{\n\t\tdraw circle(10) color:#blue;\n\t}\n}\n\n// Define a experiment to visualize in GUI\nexperiment CityScope type: gui autorun:false{\n\toutput {\n\t\tdisplay map_mode type:opengl background:#black{\t\n\t\t\tspecies brix aspect:base;\n\t\t\tspecies people aspect:base position:{0,0,0.1};\n\t\t}\n\t}\n}\n'})})]})}function h(e={}){const{wrapper:i}={...(0,o.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,i,t)=>{t.d(i,{R:()=>r,x:()=>s});var n=t(6540);const o={},a=n.createContext(o);function r(e){const i=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(a.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/build/assets/js/main.1f802b69.js b/build/assets/js/main.1f802b69.js
deleted file mode 100644
index cbb678c9..00000000
--- a/build/assets/js/main.1f802b69.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! For license information please see main.1f802b69.js.LICENSE.txt */
-(self.webpackChunkcityscope_docs=self.webpackChunkcityscope_docs||[]).push([[792],{8328:(e,t,n)=>{"use strict";n.d(t,{A:()=>p});n(6540);var r=n(3259),a=n.n(r),o=n(4054);const i={"02b7a71d":[()=>n.e(123).then(n.bind(n,3386)),"@site/docs/cityio/CityIO - UI.md",3386],"0952c0dc":[()=>n.e(157).then(n.t.bind(n,1966,19)),"/Users/noyman/GIT/cityscope.github.io/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",1966],"0a23f7ce":[()=>n.e(394).then(n.t.bind(n,4455,19)),"~docs/default/category-sidebar-category-cityio-936.json",4455],"1438b9ab":[()=>n.e(735).then(n.bind(n,6292)),"@site/docs/archive/brix/Tutorial/Tutorial.md",6292],"14eb3368":[()=>Promise.all([n.e(869),n.e(969)]).then(n.bind(n,7247)),"@theme/DocCategoryGeneratedIndexPage",7247],17896441:[()=>Promise.all([n.e(869),n.e(401)]).then(n.bind(n,6041)),"@theme/DocItem",6041],"2eb856f7":[()=>n.e(370).then(n.bind(n,4979)),"@site/docs/cityscopejs/Introduction.md",4979],"3027556f":[()=>n.e(793).then(n.bind(n,614)),"@site/docs/cityio/Introduction.md",614],"3c6077be":[()=>n.e(694).then(n.bind(n,8408)),"@site/docs/modules/brix/Module example.md",8408],"40e175d5":[()=>n.e(132).then(n.bind(n,756)),"@site/docs/tanglibe user interfaces/specs.md",756],"41d6af12":[()=>n.e(408).then(n.t.bind(n,3301,19)),"~docs/default/category-sidebar-category-archive-034.json",3301],"4206db4b":[()=>n.e(887).then(n.bind(n,2635)),"@site/docs/archive/cityio/api.md",2635],"4a555622":[()=>n.e(117).then(n.bind(n,3635)),"@site/docs/cityio/CityIO - Core.md",3635],"4e15b2cd":[()=>n.e(861).then(n.bind(n,5621)),"@site/docs/modules/brix/DeckGL Modules.md",5621],"57aa5823":[()=>n.e(459).then(n.bind(n,2384)),"@site/docs/cityio/CityIO - Module.md",2384],"5a7a18e6":[()=>n.e(383).then(n.bind(n,7020)),"@site/docs/cityio/API.md",7020],"5e95c892":[()=>n.e(647).then(n.bind(n,7121)),"@theme/DocsRoot",7121],62455296:[()=>n.e(710).then(n.bind(n,8686)),"@site/docs/archive/cityio/notes.md",8686],"6dfefd1c":[()=>n.e(440).then(n.bind(n,8400)),"@site/docs/intro/github.md",8400],"6f967107":[()=>n.e(261).then(n.bind(n,8268)),"@site/docs/archive/h3/h3.md",8268],"70b71d1a":[()=>n.e(730).then(n.bind(n,977)),"@site/docs/cityio/Architecture.md",977],"7332f3ba":[()=>n.e(860).then(n.bind(n,6842)),"@site/docs/modules/brix/Introduction.md",6842],"7365a548":[()=>n.e(376).then(n.t.bind(n,484,19)),"~docs/default/category-sidebar-category-brix-78f.json",484],"78363d9c":[()=>n.e(760).then(n.bind(n,1468)),"@site/docs/tanglibe user interfaces/RoboScope.md",1468],"7980bb0e":[()=>n.e(418).then(n.t.bind(n,3139,19)),"~docs/default/category-sidebar-category-tangible-user-interfaces-b4d.json",3139],"7d744e69":[()=>n.e(741).then(n.bind(n,9433)),"@site/docs/intro/intro.md",9433],"8529a1a6":[()=>n.e(374).then(n.bind(n,784)),"@site/docs/archive/brix/Brix.md",784],"89ac796e":[()=>n.e(949).then(n.bind(n,8649)),"@site/docs/tanglibe user interfaces/CityScoPy.md",8649],"8a98b319":[()=>n.e(898).then(n.t.bind(n,7781,19)),"~docs/default/category-sidebar-category-cityscopejs-a97.json",7781],"8fd40d43":[()=>n.e(402).then(n.bind(n,4358)),"@site/docs/intro/system.md",4358],"935f2afb":[()=>n.e(581).then(n.t.bind(n,5610,19)),"~docs/default/version-current-metadata-prop-751.json",5610],"9576d6be":[()=>n.e(379).then(n.bind(n,1452)),"@site/docs/archive/cityio/cityio.md",1452],"969018c5":[()=>n.e(890).then(n.t.bind(n,5622,19)),"~docs/default/category-sidebar-category-modules-885.json",5622],a38df249:[()=>n.e(946).then(n.bind(n,3833)),"@site/docs/cityscopejs/Opening a project.md",3833],a7bd4aaa:[()=>n.e(98).then(n.bind(n,4532)),"@theme/DocVersionRoot",4532],a94703ab:[()=>Promise.all([n.e(869),n.e(48)]).then(n.bind(n,2559)),"@theme/DocRoot",2559],b632e823:[()=>n.e(666).then(n.bind(n,9931)),"@site/docs/modules/Core Modules/Introduction.md",9931],b87b04f0:[()=>n.e(852).then(n.bind(n,990)),"@site/docs/archive/brix/Examples/Examples.md",990],cf9c09d8:[()=>n.e(49).then(n.bind(n,5431)),"@site/docs/archive/cityio/build.md",5431],d9dcfff4:[()=>n.e(743).then(n.bind(n,5485)),"@site/docs/cityscopejs/Project view.md",5485],eab65581:[()=>n.e(338).then(n.bind(n,3505)),"@site/docs/modules/types.md",3505],f30f61d4:[()=>n.e(783).then(n.bind(n,2179)),"@site/docs/archive/brix/GAMA.md",2179]};var l=n(4848);function s(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,l.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,l.jsx)("p",{children:String(t)}),(0,l.jsx)("div",{children:(0,l.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,l.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,l.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,l.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,l.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,l.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,l.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,l.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,l.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,l.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var u=n(6921),c=n(3102);function d(e,t){if("*"===e)return a()({loading:s,loader:()=>n.e(237).then(n.bind(n,2237)),modules:["@theme/NotFound"],webpack:()=>[2237],render(e,t){const n=e.default;return(0,l.jsx)(c.W,{value:{plugin:{name:"native",id:"default"}},children:(0,l.jsx)(n,{...t})})}});const r=o[e+"-"+t],d={},p=[],f=[],m=(0,u.A)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),a().Map({loading:s,loader:d,modules:p,webpack:()=>f,render(t,n){const a=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const o=r.default;if(!o)throw new Error("The page component at "+e+" doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.");"object"!=typeof o&&"function"!=typeof o||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{o[e]=r[e]}));let i=a;const l=n.split(".");l.slice(0,-1).forEach((e=>{i=i[e]})),i[l[l.length-1]]=o}));const o=a.__comp;delete a.__comp;const i=a.__context;return delete a.__context,(0,l.jsx)(c.W,{value:i,children:(0,l.jsx)(o,{...a,...n})})}})}const p=[{path:"/",component:d("/","958"),routes:[{path:"/",component:d("/","3b5"),routes:[{path:"/",component:d("/","fd7"),routes:[{path:"/archive/brix/",component:d("/archive/brix/","140"),exact:!0,sidebar:"sidebar"},{path:"/archive/brix/Examples/",component:d("/archive/brix/Examples/","442"),exact:!0,sidebar:"sidebar"},{path:"/archive/brix/GAMA",component:d("/archive/brix/GAMA","ae8"),exact:!0,sidebar:"sidebar"},{path:"/archive/brix/Tutorial/",component:d("/archive/brix/Tutorial/","c50"),exact:!0,sidebar:"sidebar"},{path:"/archive/cityio/",component:d("/archive/cityio/","e6a"),exact:!0,sidebar:"sidebar"},{path:"/archive/cityio/API",component:d("/archive/cityio/API","6aa"),exact:!0,sidebar:"sidebar"},{path:"/archive/cityio/Build",component:d("/archive/cityio/Build","95e"),exact:!0,sidebar:"sidebar"},{path:"/archive/cityio/Internal_Note",component:d("/archive/cityio/Internal_Note","6f4"),exact:!0,sidebar:"sidebar"},{path:"/archive/h3/",component:d("/archive/h3/","932"),exact:!0,sidebar:"sidebar"},{path:"/category/archive",component:d("/category/archive","e51"),exact:!0,sidebar:"sidebar"},{path:"/category/brix",component:d("/category/brix","3b5"),exact:!0,sidebar:"sidebar"},{path:"/category/cityio",component:d("/category/cityio","165"),exact:!0,sidebar:"sidebar"},{path:"/category/cityscopejs",component:d("/category/cityscopejs","2a7"),exact:!0,sidebar:"sidebar"},{path:"/category/modules",component:d("/category/modules","784"),exact:!0,sidebar:"sidebar"},{path:"/category/tangible-user-interfaces",component:d("/category/tangible-user-interfaces","4f9"),exact:!0,sidebar:"sidebar"},{path:"/cityio/API",component:d("/cityio/API","c37"),exact:!0,sidebar:"sidebar"},{path:"/cityio/Architecture",component:d("/cityio/Architecture","aa5"),exact:!0,sidebar:"sidebar"},{path:"/cityio/CityIO - Core",component:d("/cityio/CityIO - Core","aa1"),exact:!0,sidebar:"sidebar"},{path:"/cityio/CityIO - Module",component:d("/cityio/CityIO - Module","5dd"),exact:!0,sidebar:"sidebar"},{path:"/cityio/CityIO - UI",component:d("/cityio/CityIO - UI","6ae"),exact:!0,sidebar:"sidebar"},{path:"/cityio/Introduction",component:d("/cityio/Introduction","0eb"),exact:!0,sidebar:"sidebar"},{path:"/cityscopejs/Introduction",component:d("/cityscopejs/Introduction","389"),exact:!0,sidebar:"sidebar"},{path:"/cityscopejs/Opening a project",component:d("/cityscopejs/Opening a project","f07"),exact:!0,sidebar:"sidebar"},{path:"/cityscopejs/Project view",component:d("/cityscopejs/Project view","55f"),exact:!0,sidebar:"sidebar"},{path:"/intro/github",component:d("/intro/github","55e"),exact:!0,sidebar:"sidebar"},{path:"/intro/system",component:d("/intro/system","bc2"),exact:!0,sidebar:"sidebar"},{path:"/modules/brix/DeckGL Modules",component:d("/modules/brix/DeckGL Modules","261"),exact:!0,sidebar:"sidebar"},{path:"/modules/brix/Introduction",component:d("/modules/brix/Introduction","cb3"),exact:!0,sidebar:"sidebar"},{path:"/modules/brix/Module example",component:d("/modules/brix/Module example","170"),exact:!0,sidebar:"sidebar"},{path:"/modules/Core Modules/Introduction",component:d("/modules/Core Modules/Introduction","ccd"),exact:!0,sidebar:"sidebar"},{path:"/modules/Types System",component:d("/modules/Types System","3c9"),exact:!0,sidebar:"sidebar"},{path:"/tanglibe user interfaces/CityScope Table Design",component:d("/tanglibe user interfaces/CityScope Table Design","189"),exact:!0,sidebar:"sidebar"},{path:"/tanglibe user interfaces/CityScoPy",component:d("/tanglibe user interfaces/CityScoPy","a24"),exact:!0,sidebar:"sidebar"},{path:"/tanglibe user interfaces/RoboScope",component:d("/tanglibe user interfaces/RoboScope","560"),exact:!0,sidebar:"sidebar"},{path:"/",component:d("/","e98"),exact:!0,sidebar:"sidebar"}]}]}]},{path:"*",component:d("*")}]},6125:(e,t,n)=>{"use strict";n.d(t,{o:()=>o,x:()=>i});var r=n(6540),a=n(4848);const o=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,a.jsx)(o.Provider,{value:n,children:t})}},8536:(e,t,n)=>{"use strict";var r=n(6540),a=n(5338),o=n(4625),i=n(545),l=n(8193);const s=[n(119),n(6134),n(6294)];var u=n(8328),c=n(6347),d=n(2831),p=n(4848);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var m=n(5260),h=n(4586),g=n(6025),y=n(6342),b=n(1003),v=n(2131),w=n(4090),k=n(2967),x=n(440),S=n(1463);function E(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.A)(),r=(0,v.o)(),a=n[e].htmlLang,o=e=>e.replace("-","_");return(0,p.jsxs)(m.A,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:o(a)}),Object.values(n).filter((e=>a!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:o(e.htmlLang)},"meta-og-"+e.htmlLang)))]})}function C(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.A)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.A)(),{pathname:r}=(0,c.zy)();return e+(0,x.applyTrailingSlash)((0,g.A)(r),{trailingSlash:n,baseUrl:t})}(),a=t?""+n+t:r;return(0,p.jsxs)(m.A,{children:[(0,p.jsx)("meta",{property:"og:url",content:a}),(0,p.jsx)("link",{rel:"canonical",href:a})]})}function _(){const{i18n:{currentLocale:e}}=(0,h.A)(),{metadata:t,image:n}=(0,y.p)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(m.A,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:w.w})]}),n&&(0,p.jsx)(b.be,{image:n}),(0,p.jsx)(C,{}),(0,p.jsx)(E,{}),(0,p.jsx)(S.A,{tag:k.Cy,locale:e}),(0,p.jsx)(m.A,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const A=new Map;function T(e){if(A.has(e.pathname))return{...e,pathname:A.get(e.pathname)};if((0,d.u)(u.A,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return A.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return A.set(e.pathname,t),{...e,pathname:t}}var j=n(6125),N=n(6988),L=n(205);function P(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{var r,a;const o=null!=(r=null==(a=t.default)?void 0:a[e])?r:t[e];return null==o?void 0:o(...n)}));return()=>a.forEach((e=>null==e?void 0:e()))}const R=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,L.A)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);null==t||t.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),P("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.u)(u.A,e))).flat();return Promise.all(t.map((e=>null==e.route.component.preload?void 0:e.route.component.preload())))}class I extends r.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=l.A.canUseDOM?P("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=P("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,p.jsx)(R,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(c.qh,{location:t,render:()=>e})})}}const D=I,M="__docusaurus-base-url-issue-banner-container",F="__docusaurus-base-url-issue-banner",z="__docusaurus-base-url-issue-banner-suggestion-container";function B(e){return"\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '"+M+"';\n var bannerHtml = "+JSON.stringify(function(e){return'\n
WebSockets provide a way for two-way communication between a client and a server over a single, long-lived connection. This is different from the traditional HTTP request-response model, where each request opens a new connection (or reuses an existing connection in a limited way), and the server cannot send messages to the client unless explicitly requested. WebSockets allow the server to send messages to the client at any time, facilitating real-time data transfer and interactive applications.
-
In our scenario, CityIO is a message broker that collects, processes, and distributes urban data, and CityScopeJS is a web-based user interface that visualizes this data for analysis and decision-making.
-
Using WebSockets CityScopeJS establishes a WebSocket connection to CityIO when a user opens a project. This single connection stays open for the duration of the user's session. Whenever CityIO has new data or updates, it can immediately push this data to CityScopeJS over the WebSocket connection. CityScopeJS receives the data in real-time and updates the visualizations accordingly. This setup minimizes network overhead, reduces server load, and provides a seamless, real-time user experience.
The WebSocket messages exchanged between CityIO, the user interfaces (UIs), and the modules will adhere to the following structure, which is represented as a JSON schema:
The property type will indicate what type of message is sending the entity.
-
the property content will differ depending on the type of the message; should contain the information needed for the destination entity to process the message.
-
-
Upon reception of a message, the CityScope entity (CityIO, User Interfaces, or Modules) will follow the next steps:
-
-
Parses the message as a JSON, using the previous schema.
-
Reads the type property:
-
-
If the type is recognized, reads the content property and executes the proper action.
CityIO features an HTTP API that enables users to access a wide range of information about various projects. The REST API is designed to maintain compatibility with the previous version of CityIO, ensuring that older modules can seamlessly communicate with this new component.
To integrate a core module into the CityScope network, the module can establish a connection via the /module/core endpoint. Upon successful connection, the module should send a CORE_MODULE_REGISTRATION message containing information to identify the module.
When a user, through a user interface, wishes to connect a module to a project, they send a request to CityIO. This request is then forwarded to the core module as a SUBSCRIPTION_REQUEST message. If the module is available, the core module should respond by sending a SUBSCRIBE message to CityIO, including the identifier of the grid that requires the module's services. Upon receiving the grid information, the core module should calculate the necessary indicator and transmit this data back to CityIO.
If a user wishes to disconnect a module from a project, they can send a module removal request to CityIO. This request will be forwarded to the Core Module as a SUBSCRIPTION_REMOVAL_REQUEST. Upon receiving this message, the Core Module should then UNSUBSCRIBE from the project.
The aim of this interface is to enable user modules to access information about the grids created in CityIO, calculate Key Performance Indicators (KPIs), and then transmit them to the user interfaces.
-
Brix can be utilized as Middleware to facilitate interaction with this interface.
To add a user-defined module to a project, the interface /module can initiate a WebSocket channel. Once the connection is established, the module can send a SUBSCRIBE request to CityIO to acquire grid information. After receiving the grid details, the module should calculate the indicator and then send the information back to CityIO.
The objective of this interface is to enable user interfaces to access information about the grids created in CityIO, as well as the Key Performance Indicators (KPIs) computed by the modules. Additionally, this interface will permit users to make changes to the grids.
-
This WebSocket interface is independent of the User Interface's implementation, making it possible to utilize this WebSocket channel in CityScopeJS, Tangible User Interfaces (TUIs), and any forthcoming UI proposals.
When a user interface seeks to establish a connection with CityIO to send and receive information from a project, it initiates a request to /interface, which will be upgraded to a WebSocket. Following this, the UI can designate the specific grid (project) it wishes to connect to, and as a result, the UI will receive the grid's data. Subsequently, the User Interface can request the list of scenarios associated with that project, as well as the list of available core modules.
When the user interface aims to save the current state of the project as a scenario at a user's request, it can send a SEND_SCENARIO message to CityIO, including the name of the scenario and its description.
When the user interface seeks to delete or restore a scenario based on a user's request, it can send a MODIFY_SCENARIO message, with the property isInBin set to true or false, depending on whether the scenario should be placed in the bin or restored.
The purpose of this section is to outline the architecture and interfaces of CityIOWS, an updated version of CityIO that utilizes WebSockets for communication with modules and user interfaces.
-
The diagram below illustrates the various components that interact with CityIOWS, including modules, core modules, and user interfaces. Communication among these components is facilitated through CityIO, serving as a broker. A WebSocket channel is established for each connection.
-
-
-
\ No newline at end of file
diff --git a/build/cityscopejs/.DS_Store b/build/cityscopejs/.DS_Store
deleted file mode 100644
index 6e1ebd12..00000000
Binary files a/build/cityscopejs/.DS_Store and /dev/null differ
diff --git a/build/cityscopejs/Introduction/index.html b/build/cityscopejs/Introduction/index.html
deleted file mode 100644
index 780318ad..00000000
--- a/build/cityscopejs/Introduction/index.html
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-Introduction | Here We Build CityScope
-
-
-
-
-
CityScopeJS is the unified front-end for the MIT CityScope project. CityScopeJS allows users to examine different urban-design alternatives and observe their impact through different KPIs and matrices. CityScopeJS brings together different urban analytics modules, such as traffic simulation, ABM, noise, storm-water, access.
CityScopeJS is an online tool with a web interface or tangible user interface (TUI). Using the tool, users can input land uses, buildings, open spaces or transport routes, categorize them and enrich their description with details on usability, density and other parameters. This input forms the basis for calculating the various modules and indicators.
-
This tool also enables collaboration among people within the City Science Network. By using a single tool for defining projects and visualizations, individuals can easily exchange processes, best practices, and even modules.
CityScopeJS exposes two main features: CityScopeJS Grid Editor and CityScopeJS Palyground
-
CSjs Playground
-
CSjs Playground is where users interact with the design of urban areas. The tool is built to allow snappy, real-time intervention with various land-uses. The design is then evaluated using different urban analytics modules.
To explore the app for a known CityScope project, add a CityScope project name to this page URL (for example, __URL__/?cityscope=corktown will run CityScopeJS Corktown project). You can also explore a list of active CityScope projects here.
-
When in the app, edit the grid using the editing tool, and explore the different analytics updating
Minimal data for initiation is a valid GeoJson FeatureCollection of at least one Polygon feature.
-Ideally, this field should be read once on init, due to its size and static state. User should not iterate over it.
interactive_mapping: maps the grid cells that are interactable via the HCI/TUI CityScope interface or web/mobile UI. This allow mixing of different interactions without overwriting. Format
-
-
\ No newline at end of file
diff --git a/build/cityscopejs/Opening a project/index.html b/build/cityscopejs/Opening a project/index.html
deleted file mode 100644
index 210cde0a..00000000
--- a/build/cityscopejs/Opening a project/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-Opening a project | Here We Build CityScope
-
-
-
-
-
When you open a project, CityScopeJS will present you with the project view. This page aims to provide a workspace where you can manage your projects and visualize the outputs of modules. It consists of a navigation bar at the top of the screen, where you can click on different buttons to open several windows with various functionalities. The available options are:
-
-
-
Edit Mode: In this mode, you can modify the configuration of a city by editing the land uses of the grid that represents the city.
-
-
-
Scenarios: In the scenarios menu, you can save the current configuration of the city by assigning it a name and a description. Later in the process, you can switch between different scenarios of your city to study the impact of various interventions on the land, or simply to save different possibilities and analyze the metrics afterward.
-
-
-
Layers: In the layers menu, you can select which layers of the visualization you want to see and adjust the opacity of each one. This feature is particularly useful when working with complex visualizations, as it enables you to focus on specific elements.
-
-
-
View: This menu allows us to toggle different visibility settings for the map.
-
-
-
Radar Chart: In the radar chart window, you can display various metrics and KPIs related to your project. Initially, this will be empty; you must connect a module to the project in order to see data displayed.
-
-
-
Land Use: In this menu, you can see the current distribution of land uses within the project.
-
-
-
Bar Chart: In the bar chart window, you can display various metrics and KPIs related to your project using a bar plot. Initially, this will be empty; you must connect a module to the project in order to see data displayed.
-
-
-
Modules: In the modules window, you can view and select always-available modules that are independent of the projects. When selecting a module, it will compute the results for your project and display them in the interface.
-
-
-
-
-
\ No newline at end of file
diff --git a/build/img/.DS_Store b/build/img/.DS_Store
deleted file mode 100644
index dfffa010..00000000
Binary files a/build/img/.DS_Store and /dev/null differ
diff --git a/build/img/cityio/.DS_Store b/build/img/cityio/.DS_Store
deleted file mode 100644
index 3c91d8f8..00000000
Binary files a/build/img/cityio/.DS_Store and /dev/null differ
diff --git a/build/img/img/.DS_Store b/build/img/img/.DS_Store
deleted file mode 100644
index b6224ee5..00000000
Binary files a/build/img/img/.DS_Store and /dev/null differ
diff --git a/build/index.html b/build/index.html
deleted file mode 100644
index f03cdbc2..00000000
--- a/build/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-Introduction | Here We Build CityScope
-
-
-
-
-
CityScope is a project conducted at the MIT Media Lab City Science group. It includes a slew of tangible and digital platforms dedicated to solving spatial design and urban planning challenges. The tools range from simulations that quantify the impact of disruptive interventions in cities to community engagement systems. We develop and deploy these tools around the world and maintain free and open-source community for the majority of our work.
-
Note
CityScope documentation and the software it describes are works in progress. The content of the documentation or the software may change without prior notice.
-
-
Figure: CityScope in Andorra La-Vella (Photo: Ariel Noyman)
-
-
-
\ No newline at end of file
diff --git a/build/intro/.DS_Store b/build/intro/.DS_Store
deleted file mode 100644
index 76655170..00000000
Binary files a/build/intro/.DS_Store and /dev/null differ
diff --git a/build/intro/github/index.html b/build/intro/github/index.html
deleted file mode 100644
index 2632f3c7..00000000
--- a/build/intro/github/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-Development on GitHub | Here We Build CityScope
-
-
-
-
-
CityScope is open-source software and is primarily hosted on GitHub. The organization structure is designed to facilitate the development and deployment of CityScope projects. The organization consists of two types of repositories: tools and cities.
-
The image below illustrates the components currently available in the CityScope Beta Software architecture. Additional components can be incorporated as required in the future.
There are many different repositories in the CityScope organization, and each one may have its own development guidelines, license, and contributing guidelines. However, there are some general guidelines that apply to all repositories:
-
-
contact the maintainers of the repository to make sure your contribution is in line with the project's goals
-
Fork the repository and make your changes in your fork
CityScope is composed of a series of tools loosely connected to each other. The tools are developed in different languages and frameworks, and they communicate through a central server, CityIO.
CityScopeJS includes several other modules for building, testing and deploying an end-to-end CityScope platform. Each module is developed as a standalone part of the system with minimal dependency on others. Data flow between modules is done using cityIO, which operates between the different modules.
Different analysis modules calculate various indicators on urban performance, such as noise, mobility, energy and others. These analysis modules are developed by experts in each evaluation field.
CityIO is a server program that saves tables to have different software (visualization, simulation) read/write information. It exposes an API to serve JSON files representing table info.
-
-
Enables the communication between the different components of the system.
-
Saves the projects to access them seamlessly in all the components.
-
Rebuilt to allow real-time communication, using WebSockets.
CityScope also includes tangible user interfaces (TUIs) that allow users to interact with the system in a physical way. These interfaces are developed using the CityScopeJS platform.
CityScope (CS) Types are the basic land-use units that can be combined and arranged to represent urban environments within the CityScope platform. CS Types are assigned to each cell within the grid that is overlaid over the urban area of enquiry. The grid provides unified segmentation, scale and a level of abstraction that can be easily manipulated by users. Each cell within the grid can either be fixed or dynamic, depending on project limits; fixed cells within a grid are not intended to be changeable by users; dynamic cells are intended for manipulation to interact with the CityScope platform. Interactions take place as users manipulate Types within the project area.
-
-
CS Types are represented by tiles that are set within the cells of a grid. At minimum, each tile must include land use and economic activity data, which can be complemented with additional dimensions of information that are assigned by users during the commissioning of a table. Additional information that can be assigned to a CS Type includes, but is not limited to, the acoustic characteristics, demographic information, and/or the utilization of a type.
-
-
To standardize the analysis and visualization modules, the CityScope platform uses unified data classifications to define each Type. CS Types may differ from project to project depending on the programming and intervention under investigation. To standardize how CS Types are defined, the classification uses unified dictionary of attributes that include, but are not limited to, land-use and economic activity, as defined by the American Planning Association, Land-Based Classification Standards or LBCS, and the North American Industry Classification System or NAICS, for the associated economic activity. Additional characteristics can be added when project specific modules are being used.
-
LBCS - Land Use Classification Notation:
-
The LBCS classification system extends the notion of land uses by refining traditional categories into multiple dimensions, including activity, function, building type, site development character, and ownership constraints. Each dimension has its own set of categories and subcategories for classifying land uses. By classifying every land-use across multiple dimensions, users can have precise control of land-use classifications. Codes are generated using a numerical classification outlined in the LBCS manual:
In addition to the LBCS classifications, the NAICS codes are a standard used by Federal statistical agencies in classifying business establishments for the purpose of collecting, analyzing, and publishing statistical data related to the U.S. business economy.Codes are generated using a numerical classification outlined in the NAICS manual:
X 0 0 0 0 - First level classification - Industry Sector (20 broad sectors up from 10 SIC)
-
XX 0 0 0 - 2nd level - Industry Sub sector
-
XXX 0 0 - 3rd level - Industry Group
-
XXXX 0 - 4th level - Industry
-
-
Sample CS Types:
-
As an example exercise we will define 3 of the most popular CS types: A simple single use tile like a park, a single use tile of housing, and a multi use tail mixing office and shopping:
Individual housing building, 100% of Residential activities. NAICS mapping = null (Since NAICS is the "standard used by Federal statistical agencies in classifying business establishments"; housing doesn't have a correlation in NAICS). LBCS mapping = 1100
Below are some more examples of CityScope types. These can be copy and pasted or modified for use in different CityScope projects:
-A single grid-cell may contain multiple LBCS and multiple NAICS on different floors or even on the same floor. Therefore, the value of each attribute is formatted as a list of objects. The object in the list represents a grouping of floors starting with the lower-most floors. Each object contains the mix of uses within that floor-group. For example, the following represents the NAICS attribute for a grid cell where:
The number of floors is independent of the type and specified separately by the user. Therefore, if the user assigns 10 floors to this grid cell, the lower 2 floors will be a mix of 541310 and 541330 and the upper 10 floors will be a mix of 23, 42 and 61.
-In most cases, the type specification will not require such a detailed level of partitioning of types. If for example, the grid cell has only a single usage type, the same data format will be used but the list will only contain 1 object of length 1. For example, the following represents the NAICS attribute for a grid cell solely devoted to "54" (Professional, Scientific and Technical Services).
The main difference in using Brix WS compared to the previous version of Brix is the method of sending data to CityScope for visualization. The previous version of Brix allowed for various pre-defined visualizations, such as numeric with bars or graphs, heatmaps, or ABM, among others. While this was useful, it didn't offer enough flexibility for module makers to create complex visualizations with a variety of different elements. They were always constrained to using the same method to display data.
-
To address this issue, Brix WS introduces DeckGL modules, a new type of module that can harness the full power of DeckGL and create robust visualizations using multiple DeckGL layers.
-
The structure of the data that DeckGL modules should follow is an array of objects, where each object represents one layer of the visualization. Every layer always has the same three properties:
-
-
type: The type of the layer.
-
data: The data to be represented.
-
properties: Additional properties to configure the visualization of the layer.
This list will grow over time to include all the layers in DeckGL. In each of the links, you can view an example of the visualization that the layer creates.
This documentation is under construction. The content of the documentation may change without prior notice.
-
Brix is a Python library that manages communication with CityIO and CityScopeJS. This enables module makers to focus on their projects without the necessity of directly interacting with CityIO or the UI.
-
As depicted in the following image, module makers only need to concern themselves with the code in their modules, the utilization of Brix, and the results obtained in CityScopeJS. All internal communication mechanisms and updates are managed by the CityScope platform.
In this section, we present how to code an example DeckGL module on Brix WS that connects with a project in CityScopeJS and displays various visualizations.
-
Currently, Brix WS is not published as a Python library available through pip. Consequently, the first step would be to download the code from GitHub.
The basic structure of any module will be as follows:
-
from brix.classes import DeckGLIndicator import random from numpy import mean classExampleModule(DeckGLIndicator): defsetup(self): self.name ='example' defload_module(self): pass defreturn_indicator(self, geogrid_data): # Module code
-
The setup function will be used to define the values of some variables, such as the name of the module.
-
Data loading actions should go in the load_module function
-
return_indicator will be the main function of any module, in this one, you can read the data of the grid realted to the project, executed the necessary calculations to obtain the module output, and return it in a proper structure to be sent back to CityIO.
In order to generate a DeckGL module, we need to send back to CityIO all the layers that will compose the visualization in CityScopeJS. In this example, we use different types of layers to generate a random indicator: heatmaps, columns, arc, and geojson.
-
defreturn_indicator(self, geogrid_data): data =[] #HEATMAP features =[] for cell in geogrid_data: feature ={} lat,lon =zip(*cell['geometry']['coordinates'][0]) lat,lon = mean(lat),mean(lon) feature['coordinates']=[lat,lon] feature['weight']= random.random()*10 features.append(feature) data.append({"type":"heatmap","data":features,"properties":{}}) #ARC arc_data =[{ 'inbound':72633, 'outbound':74735, 'from':{ 'name':'MIT Media Lab', 'coordinates':[-71.08727713271684,42.36041314214483] }, 'to':{ 'name':'MIT CSAIL', 'coordinates':[-71.09060913355545,42.36168851347742] } }] data.append({"type":"arc","data":arc_data,"properties":{"width":1}}) #COLUMNS features_columns =[] for cell in geogrid_data: feature ={} lat,lon =zip(*cell['geometry']['coordinates'][0]) lat,lon = mean(lat),mean(lon) feature['centroid']=[lat,lon] feature['value']= random.random()*300 features_columns.append(feature) data.append({"type":"column","data":features_columns,"properties":{}}) #GEOJSON geojson_data ={"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"coordinates":[[[-71.09236362469034,42.35778603125499],[-71.08986747898945,42.3585765398804],[-71.0901949616614,42.35911429516614],[-71.09076987568574,42.358931458885564],[-71.09126473839052,42.35978648280218],[-71.09261105604213,42.35938317108344],[-71.09214530290863,42.3584421003398],[-71.09268382996976,42.35830766051154],[-71.09236362469034,42.35778603125499]]],"type":"Polygon"}}]} data.append({"type":"geojsonbase","data":geojson_data,"properties":{}}) return data
-
The straightforward solution is, for each layer, calculate the necessary data, and then append the layer to the ouput array.
-
It is important to note that this method could be follow with any set of the available layers.
Connecting a module to a CityScope project will only require to create a Handler, indicating the name of the table that you want to connect to. Then, add the indicator (module) previously defined to the handler, and start it.
-
from brix.classes import Handler indicator = ExampleModule() H = Handler(quietly=False, table_name='walkability') H.add_indicators([ indicator ]) H.listen()
-
-
\ No newline at end of file
diff --git a/build/sitemap.xml b/build/sitemap.xml
deleted file mode 100644
index 6bb62032..00000000
--- a/build/sitemap.xml
+++ /dev/null
@@ -1 +0,0 @@
-https://cityscope.media.mit.edu/archive/brix/weekly0.5https://cityscope.media.mit.edu/archive/brix/Examples/weekly0.5https://cityscope.media.mit.edu/archive/brix/GAMAweekly0.5https://cityscope.media.mit.edu/archive/brix/Tutorial/weekly0.5https://cityscope.media.mit.edu/archive/cityio/weekly0.5https://cityscope.media.mit.edu/archive/cityio/APIweekly0.5https://cityscope.media.mit.edu/archive/cityio/Buildweekly0.5https://cityscope.media.mit.edu/archive/cityio/Internal_Noteweekly0.5https://cityscope.media.mit.edu/archive/h3/weekly0.5https://cityscope.media.mit.edu/category/archiveweekly0.5https://cityscope.media.mit.edu/category/brixweekly0.5https://cityscope.media.mit.edu/category/cityioweekly0.5https://cityscope.media.mit.edu/category/cityscopejsweekly0.5https://cityscope.media.mit.edu/category/modulesweekly0.5https://cityscope.media.mit.edu/category/tangible-user-interfacesweekly0.5https://cityscope.media.mit.edu/cityio/APIweekly0.5https://cityscope.media.mit.edu/cityio/Architectureweekly0.5https://cityscope.media.mit.edu/cityio/CityIO%20-%20Coreweekly0.5https://cityscope.media.mit.edu/cityio/CityIO%20-%20Moduleweekly0.5https://cityscope.media.mit.edu/cityio/CityIO%20-%20UIweekly0.5https://cityscope.media.mit.edu/cityio/Introductionweekly0.5https://cityscope.media.mit.edu/cityscopejs/Introductionweekly0.5https://cityscope.media.mit.edu/cityscopejs/Opening%20a%20projectweekly0.5https://cityscope.media.mit.edu/cityscopejs/Project%20viewweekly0.5https://cityscope.media.mit.edu/intro/githubweekly0.5https://cityscope.media.mit.edu/intro/systemweekly0.5https://cityscope.media.mit.edu/modules/brix/DeckGL%20Modulesweekly0.5https://cityscope.media.mit.edu/modules/brix/Introductionweekly0.5https://cityscope.media.mit.edu/modules/brix/Module%20exampleweekly0.5https://cityscope.media.mit.edu/modules/Core%20Modules/Introductionweekly0.5https://cityscope.media.mit.edu/modules/Types%20Systemweekly0.5https://cityscope.media.mit.edu/tanglibe%20user%20interfaces/CityScope%20Table%20Designweekly0.5https://cityscope.media.mit.edu/tanglibe%20user%20interfaces/CityScoPyweekly0.5https://cityscope.media.mit.edu/tanglibe%20user%20interfaces/RoboScopeweekly0.5https://cityscope.media.mit.edu/weekly0.5
\ No newline at end of file
diff --git a/build/tanglibe user interfaces/.DS_Store b/build/tanglibe user interfaces/.DS_Store
deleted file mode 100644
index f4c05d10..00000000
Binary files a/build/tanglibe user interfaces/.DS_Store and /dev/null differ
diff --git a/build/tanglibe user interfaces/CityScoPy/index.html b/build/tanglibe user interfaces/CityScoPy/index.html
deleted file mode 100644
index 831cbe30..00000000
--- a/build/tanglibe user interfaces/CityScoPy/index.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-CityScoPy | Here We Build CityScope
-
-
-
-
-
A tool for scanning interactions with a tangible LEGO grid and networking MIT CityScope Projects in Python
-
CityScoPy is the main component of an interactive MIT CityScope table.
-It is used for initiating and later run a interactive CityScope instance in any arbitrary geolocated area in the world. CityScoPy can capture, key-stone, scan and send uniquely tagged arrays of 2-dimension physical bricks.
$ git clone https://github.com/CityScope/CS_CityScoPy.git $ cd CS_CityScoPy
-
-
install packages. To produce a list of needed packages, use pipreqs, follow instructions https://github.com/bndr/pipreqs. Or, simply run the app and install packages as they appear as missing.
-
tweak __settings__.json to fit your cityIO table setup. Read cityIO documentation for proper data structure
use one or more of the main methods. 'Blocking' means the method will run forever (while true loop). Advanced users can parallel blocking methods using multithreading.
the tool will start given a cam is connected and working
-
Select 4 corners [up right, up left, bottom right, bottom left, at this order] of keystone region
-Note: no need to exactly select the corners, as these are only initial guides for scanner method
Scanner will detect colors in arrays of 2d-pixel arrays. Then, these color arrays will be compared to list of tags attribute of a given __settings__.json file. Then the tool will return a list of type and rotation for each of the scanned arrays. This list is then converted to cityIO acceptable JSON format and can be sent using POST request.
{ "cityscopy": { "cityscope_project_name": "cityscopy", // table name "type": ["0", "1", "2", ...], // types names "rotation": ["0", "1", "2", "3"], // default rotations (0, 90, 180, 270) "nrows": 10, // number of columns to scan "ncols": 10, // number of rows to scan "cell_gap": 10, // spacing between grid fields when using physical grid "camId": 0, // openCV will pick `camID` camera (usually 0) "interval": 250, // in ms, how many time should this send the packet "gui": true, // toggle GUI display "cityio": true, // toggle UDP or cityIO delivery "tags": [ // 16 digit strings of types being scanned [`1000000100000000`] "0000000000000000", "1111111111111111", "1111111100000000", ... ], "mirror_cam": false } }
-
Tool will start scanning using whatever keystone data was stored in keystone.txt
-make corrections to the key stone using the sliders or keyboard using 1,2,3,4 to select a corner and [w,a,s,d] to move [up,left,down,right] the selected corner. Press k to save change to file and ctrl-c twice [in the terminal window] to exit program
the app will attempt sending the resulted scan to cityIO server. If successful, the following JSON format data will appear on the cityIO endpoint defined in settings.json
-
{ "grid": [ [1, 0], [1, 0], [0, 0], [4, 0], [-1, -1], [-1, -1], // no type was found will return -1 as type and -1 as rotation ... ], ... other cityIO data ... }
OS, Python versions, openCV and peripheral devices such as webcams can sometimes cause issues. If you found and issue, please report it as a Github issue. Here're some encountered issues and their solutions:
-
-
-
Mac OSX High Sierra blocks multithreading
-
-
issue: objc[67570]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
Not every deployment uses this table configuration, often times its just a table with the most important transparent top and grid, this is often made from acrylic and laser cut.
Scanner (gets input from camera converts it to information that can be parsed through various simulation)
-currently this functionality is provided using one of below:
-
-
-
Rhinoceros 3D (win only)
-
Unity game engine
-
Browser, JavaScript
-
-
-
Simulation / Visualization
-this differs largely on what to simulate, or the research question on focus.
-In fact, some CityScope table has multiple simulations and visualizations living together.
-
-
\ No newline at end of file
diff --git a/build/tanglibe user interfaces/RoboScope/index.html b/build/tanglibe user interfaces/RoboScope/index.html
deleted file mode 100644
index 8708b9bb..00000000
--- a/build/tanglibe user interfaces/RoboScope/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-RoboScope | Here We Build CityScope
-
-
-
-
-