JUPYTER / PYTHON / DATA-DRIVEN DESIGN

Earthquake: Data into Space

2025–26 / Bartlett School design project · Data-driven design

Earthquake: Data into Space

A design workflow connecting Jupyter, Python, Blender, and Processing

This earthquake study turns visual features, narrative signals, and geophysical records into computable design variables. Collection, cleaning, analysis, and fusion in Jupyter lead to Python-driven architectural fragments, ground fractures, and animated scenes in Blender, followed by particles, waves, and real-time feedback in Processing.

My contribution
Python data processing, design mappings, and spatial visualisation
Project stage
Multimodal analysis, procedural modelling, and real-time visualisation
01

From data to design

How can earthquake data become rules for spatial form and dynamic behaviour?

Statistics, photographs, and news each describe different aspects of earthquakes. This project converts those descriptions into computable features and a shared parameter interface, connecting analysis, procedural modelling, and real-time visualisation across tools.

240cleaned images
232news titles and summaries
240fusion design samples
20spatial instances
  1. 01 / Jupyter · Python

    Collect and clean

    Collect images, text, and seismic records; remove duplicates and structure the data.

  2. 02 / Python

    Analyse and fuse

    Extract features, standardise, cluster, and reduce dimensions into shared design parameters.

  3. 03 / Blender · Python

    Rules and space

    Translate parameters into fragments, ground displacement, fractures, waves, and dust.

  4. 04 / Processing

    Behaviour and feedback

    Read records sequentially to drive particles, propagating waves, and a data panel.

The spatial field: shared rules generate distinct, comparable instances.
02

Images and visual features

icrawler collects images of collapsed buildings, urban rubble, and rescue operations. Invalid files and hash-based duplicates are removed. OpenCV and PIL extract average brightness, grayscale contrast, and Canny edge density from the remaining 240 images.

Image-sample collage: from visual references to computable features.
Brightness distribution
Edge-density distribution
Visual fragmentation proxy

Edge density, contrast, and darkness form damage_proxy, a design cue for fragmentation. It is an approximation based on visual features, rather than a measured structural-damage rating. Standardised features enter four K-means groups, with PCA used to inspect their distribution.

Four cluster counts: 71 / 54 / 78 / 37.
PCA projection reveals relationships between visual features.
Inspect the original Python feature and clustering logic
df_img["darkness"] = 255 - df_img["brightness"]
df_img["damage_proxy"] = (
    df_img["edge_density"] * 0.5
    + (df_img["contrast"] / df_img["contrast"].max()) * 0.3
    + (df_img["darkness"] / df_img["darkness"].max()) * 0.2
)

features = df_img[["brightness", "contrast", "edge_density", "damage_proxy"]]
X = StandardScaler().fit_transform(features)
df_img["cluster"] = KMeans(n_clusters=4, random_state=42).fit_predict(X)

Introduce human presence

YOLOv8 records person_count and total_objects, adding signals for later fragment density and spatial complexity.

Detected people
Detected objects
03

Text and narrative signals

Earthquake-related headlines and summaries are combined, deduplicated, and cleaned into 232 records. Keywords such as damage, death, rescue, and collapse are extracted. TextBlob polarity distinguishes positive, neutral, and negative wording, turning narrative content into design variables.

News keyword frequencies
Text polarity describes wording; it does not measure affected people’s emotions.

Count Vectorizer and TF-IDF representations are compared. TF-IDF features enter four K-means clusters, and PCA displays a two-dimensional projection. Keywords suggest instability and collapse, while clusters and polarity introduce variation in form and motion.

Text groups
Two-dimensional text-feature projection
04

Seismic records and data fusion

Date, magnitude, depth, latitude, and longitude come from the Significant Earthquakes, 1965–2016 dataset. Pandas removes invalid records and normalises variables with different units into a shared numerical interface.

Magnitude distribution in the sample
Depth and magnitude: inspect the ranges and distribution of variables.

The fusion notebook adds disaster-text samples and satellite-tile features, comparing TF-IDF, Sentence-BERT, and image representations. Reduced features are standardised alongside numerical variables and emotion-intensity signals before five-group K-means clustering. The output contains 240 design samples.

Five clusters after multimodal fusion
Longitude, latitude, and magnitude in three dimensions
Semantic labels generated by rules or a model
Keyword distribution of the disaster-text sample

Scope of the fusion

Image and news analyses are separate branches. The final fusion pairs seismic records, disaster texts, and image features by sample without establishing a time-and-location match to the same event. Emotion and fragmentation signals explore design parameters in a data-driven generative experiment.

05

Python design mappings

Data translation makes the connection between features and design tools explicit. Each parameter has an input, a mapping, and a spatial effect. CSV acts as the interface between Jupyter, Blender, and Processing. Select a source sample below to inspect how magnitude and depth change its parameters.

DATA → PARAMETERS

Select a record to inspect its design parameters

240 design samples
01002003004005006007005.566.577.588.59Depth / kmMagnitude 1965-04-27 / M 6.1 / 60 km1965-06-11 / M 5.6 / 35 km1965-07-29 / M 5.7 / 15 km1965-08-11 / M 7.6 / 30 km1965-09-01 / M 5.8 / 100 km1965-09-16 / M 6 / 160 km1965-10-07 / M 5.9 / 20 km1966-06-27 / M 5.6 / 115 km1966-08-17 / M 5.6 / 41.9 km1966-08-28 / M 5.7 / 170 km1967-03-19 / M 6.2 / 97.7 km1967-06-23 / M 5.8 / 90 km1968-07-05 / M 6.3 / 47 km1968-09-14 / M 6.2 / 25 km1968-12-14 / M 5.9 / 25 km1969-11-20 / M 5.7 / 15 km1970-02-07 / M 6 / 15 km1970-05-27 / M 5.9 / 10 km1970-05-29 / M 6 / 10 km1971-05-21 / M 5.6 / 27.5 km1972-01-22 / M 5.8 / 72.8 km1972-06-06 / M 5.5 / 47.5 km1972-08-20 / M 5.6 / 15 km1972-10-14 / M 5.9 / 35 km1972-12-18 / M 5.9 / 31.5 km1973-03-14 / M 5.8 / 64 km1973-06-17 / M 5.6 / 32 km1974-01-15 / M 5.6 / 114 km1974-02-03 / M 5.9 / 30 km1974-10-20 / M 5.7 / 43 km1974-11-02 / M 6.7 / 0 km1974-11-12 / M 5.8 / 54 km1974-11-19 / M 5.7 / 44 km1975-04-02 / M 5.6 / 33 km1975-07-08 / M 6.5 / 33 km1975-10-02 / M 5.8 / 75 km1976-03-28 / M 5.5 / 179 km1976-05-19 / M 5.8 / 72 km1976-05-22 / M 5.8 / 31 km1976-05-24 / M 5.7 / 33 km1976-06-08 / M 5.6 / 13 km1976-08-29 / M 5.6 / 33 km1976-09-25 / M 5.5 / 33 km1977-03-24 / M 5.5 / 35 km1977-04-20 / M 7.5 / 33 km1977-05-28 / M 5.9 / 54 km1977-08-29 / M 6.2 / 12 km1977-10-12 / M 5.6 / 33 km1977-11-21 / M 5.6 / 33 km1978-01-20 / M 5.8 / 51 km1978-06-27 / M 5.7 / 35 km1978-08-10 / M 6 / 10 km1979-01-11 / M 6.2 / 32 km1979-06-10 / M 6 / 10 km1979-06-24 / M 5.6 / 33 km1979-07-09 / M 5.5 / 11 km1979-11-04 / M 5.5 / 27 km1979-11-09 / M 5.5 / 564 km1979-11-13 / M 6.3 / 47 km1979-12-01 / M 5.5 / 10 km1980-04-16 / M 5.7 / 80 km1980-07-09 / M 5.9 / 37 km1981-08-17 / M 5.6 / 34.7 km1981-09-28 / M 5.7 / 33 km1981-10-17 / M 5.9 / 26 km1981-10-18 / M 6 / 0 km1981-10-18 / M 5.7 / 33 km1981-12-19 / M 7.2 / 10 km1982-02-21 / M 5.5 / 27 km1982-03-27 / M 5.5 / 73 km1982-07-04 / M 5.5 / 53.5 km1982-07-10 / M 5.5 / 10 km1982-07-20 / M 5.6 / 145.8 km1982-09-25 / M 5.5 / 42 km1982-12-28 / M 5.6 / 33 km1983-01-05 / M 5.6 / 33 km1983-01-18 / M 6.5 / 56 km1983-04-08 / M 6.7 / 10 km1983-04-12 / M 7 / 104.2 km1983-04-13 / M 5.9 / 33 km1983-06-24 / M 6.7 / 44.1 km1983-07-22 / M 5.6 / 41.3 km1984-03-01 / M 6 / 10 km1984-07-09 / M 5.5 / 10 km1984-09-01 / M 5.7 / 478.3 km1984-10-10 / M 5.6 / 10 km1984-11-15 / M 6.3 / 348.1 km1984-11-21 / M 6.4 / 23.4 km1985-03-18 / M 5.5 / 33 km1985-04-08 / M 5.9 / 47.7 km1985-06-01 / M 5.6 / 23.1 km1985-06-02 / M 5.8 / 370.2 km1985-06-03 / M 6.3 / 65.5 km1985-08-15 / M 5.6 / 10 km1986-07-20 / M 5.84 / 4.01 km1986-10-21 / M 5.7 / 33 km1986-11-06 / M 5.7 / 588.5 km1987-02-17 / M 5.7 / 33 km1987-04-25 / M 6.9 / 107 km1987-06-24 / M 5.8 / 33 km1987-10-06 / M 7.3 / 16 km1987-10-16 / M 7.4 / 47.8 km1987-11-24 / M 6.6 / 11.181 km1988-10-31 / M 5.6 / 12 km1988-11-23 / M 5.5 / 41.1 km1989-05-29 / M 5.6 / 32 km1989-08-14 / M 5.5 / 33 km1989-09-06 / M 5.6 / 10 km1989-11-04 / M 5.5 / 10 km1989-11-29 / M 6.3 / 70.8 km1989-12-01 / M 5.6 / 43.1 km1990-06-01 / M 6.3 / 67 km1990-11-23 / M 5.7 / 61.8 km1991-01-10 / M 5.7 / 22.6 km1991-12-26 / M 5.6 / 10 km1992-04-18 / M 5.5 / 32.1 km1992-04-24 / M 5.5 / 22.5 km1992-06-21 / M 6.2 / 10 km1992-07-17 / M 5.6 / 18.9 km1992-07-18 / M 5.5 / 30.8 km1992-08-12 / M 5.8 / 33 km1992-11-21 / M 5.9 / 65 km1992-11-24 / M 5.7 / 10 km1993-03-06 / M 6.6 / 18.2 km1993-04-19 / M 6.8 / 23.6 km1993-04-25 / M 6 / 33 km1993-05-25 / M 6.2 / 36.8 km1993-08-28 / M 5.9 / 132.8 km1993-09-15 / M 5.6 / 27.9 km1993-09-16 / M 5.5 / 33 km1993-09-21 / M 6 / 11 km1993-12-12 / M 5.6 / 21.9 km1994-02-12 / M 6.7 / 15 km1994-04-12 / M 5.5 / 30.9 km1994-05-25 / M 5.9 / 24.6 km1994-11-20 / M 6.3 / 16 km1995-03-22 / M 5.5 / 39 km1995-04-28 / M 5.5 / 9.2 km1995-07-13 / M 5.9 / 13.6 km1995-09-23 / M 6 / 27.1 km1995-11-30 / M 6.3 / 23.4 km1995-12-02 / M 6.6 / 18.1 km1995-12-03 / M 5.5 / 33 km1995-12-25 / M 6.1 / 14.8 km1996-01-30 / M 6.1 / 14.2 km1996-07-29 / M 5.5 / 74.3 km1997-02-04 / M 5.5 / 10 km1997-02-21 / M 6.1 / 33 km1997-08-08 / M 6.6 / 10 km1997-10-18 / M 5.5 / 35.6 km1997-11-10 / M 5.6 / 10 km1998-08-14 / M 5.8 / 57.6 km1998-09-09 / M 5.6 / 10 km1998-10-03 / M 6.2 / 226.6 km1999-08-18 / M 5.7 / 155 km1999-09-07 / M 5.5 / 10 km1999-11-01 / M 6.3 / 33 km2000-01-05 / M 5.5 / 33 km2000-02-25 / M 7.1 / 33 km2000-04-01 / M 5.6 / 608.1 km2000-06-14 / M 5.7 / 63 km2000-06-14 / M 5.9 / 196.5 km2000-09-14 / M 6.2 / 33 km2000-09-23 / M 5.5 / 125 km2000-10-20 / M 5.5 / 10 km2000-10-21 / M 5.9 / 10 km2000-11-16 / M 5.5 / 33 km2000-12-20 / M 5.5 / 33 km2001-02-24 / M 7.1 / 35 km2001-06-10 / M 5.6 / 33 km2001-06-14 / M 5.9 / 33 km2001-09-29 / M 6.4 / 33 km2001-10-08 / M 6.5 / 48.5 km2002-04-24 / M 6.2 / 10 km2002-05-08 / M 5.9 / 39 km2002-11-11 / M 5.7 / 539.9 km2003-01-07 / M 5.7 / 33 km2003-03-17 / M 5.8 / 10 km2003-07-25 / M 5.5 / 10 km2003-08-21 / M 5.9 / 20.2 km2004-06-10 / M 5.9 / 10 km2004-06-14 / M 5.9 / 10 km2004-07-10 / M 5.7 / 10 km2004-11-20 / M 6.4 / 16 km2004-11-23 / M 5.5 / 15.4 km2004-12-27 / M 5.6 / 19 km2004-12-29 / M 5.7 / 47.7 km2005-01-15 / M 5.5 / 25.7 km2005-03-19 / M 6.3 / 598.7 km2005-04-19 / M 5.5 / 18.7 km2005-07-11 / M 6 / 10 km2005-12-10 / M 5.6 / 506.5 km2006-06-09 / M 6.1 / 564.4 km2006-06-24 / M 6.3 / 26 km2006-06-27 / M 5.8 / 9 km2006-07-17 / M 5.5 / 10 km2006-07-19 / M 6.1 / 45 km2007-04-09 / M 5.8 / 36 km2007-04-21 / M 6.1 / 40.7 km2007-06-05 / M 5.7 / 10 km2007-10-25 / M 5.5 / 29.7 km2008-01-09 / M 6.1 / 10 km2008-02-13 / M 6.2 / 19 km2008-06-25 / M 5.7 / 16 km2008-10-03 / M 5.6 / 10 km2008-11-29 / M 6 / 386 km2008-12-20 / M 6.3 / 19 km2009-03-26 / M 5.9 / 159.5 km2009-09-05 / M 5.8 / 210.2 km2009-10-10 / M 6 / 112 km2009-11-12 / M 5.8 / 570.6 km2009-11-13 / M 5.8 / 608 km2010-01-12 / M 6 / 10 km2010-06-16 / M 7 / 18 km2010-06-29 / M 5.5 / 17 km2010-07-29 / M 6.6 / 618 km2010-10-09 / M 5.8 / 91 km2011-01-26 / M 6.1 / 23 km2011-02-05 / M 5.8 / 28.9 km2011-03-11 / M 5.5 / 4.7 km2011-03-11 / M 6.2 / 9.3 km2011-03-20 / M 5.7 / 321 km2011-05-24 / M 5.8 / 16 km2012-11-02 / M 5.5 / 9.1 km2013-02-07 / M 6.7 / 11 km2013-02-16 / M 6.1 / 105 km2013-03-31 / M 5.6 / 10 km2013-11-03 / M 5.9 / 532 km2013-11-13 / M 5.8 / 20 km2013-11-17 / M 7.7 / 10 km2014-02-03 / M 5.6 / 109 km2014-03-31 / M 5.6 / 114.5 km2014-06-19 / M 6.2 / 36 km2014-08-23 / M 5.6 / 100 km2014-11-29 / M 5.6 / 10 km2014-12-22 / M 5.8 / 14 km2015-09-21 / M 5.5 / 26.95 km2016-01-02 / M 5.8 / 585.47 km2016-01-31 / M 5.7 / 10 km2016-05-31 / M 5.9 / 18.37 km
Cluster 0Cluster 1Cluster 2Cluster 3Cluster 4
001 / 240
Magnitude
6.1
Depth
60.0 km
Geometry scale
1.667 ×
Vertical offset
-0.087
Fragmentation
0.600
Material group
3
scale = 1 + magnitude_norm × 4
z = −depth_norm

Values come directly from the original final_fusion_data.csv. Clusters combine numerical, semantic, and image features. Sample pairings are design experiments, rather than verified matches to the same earthquake event.

Input variableMapping ruleDesign effect
magnitude_norm1 + magnitude_norm × 4Geometry scale and shake amplitude
depth_normz = −depth_normVertical displacement
longitude_norm / latitude_normx / yNormalised spatial coordinates
emotion_intensityfragmentation / noiseFragmentation and disturbance intensity
emotion_labelrotation_chaosRotation and motion behaviour
cluster_idmaterial_indexMaterial or asset family
Inspect the original Python mapping and export logic
fusion_df['x'] = fusion_df['longitude_norm']
fusion_df['y'] = fusion_df['latitude_norm']
fusion_df['z'] = -fusion_df['depth_norm']
fusion_df['scale'] = 1 + fusion_df['magnitude_norm'] * 4
fusion_df['fragmentation'] = fusion_df['emotion_intensity']
fusion_df['rotation_chaos'] = np.where(
    fusion_df['emotion_label'].eq('panic'),
    fusion_df['emotion_intensity'],
    fusion_df['emotion_intensity'] * 0.4
)
fusion_df['material_index'] = fusion_df['cluster_id']
fusion_df.to_csv(OUTPUT_DIR / 'final_fusion_data.csv', index=False)
Download the numerical design samples ↗
06

Data-driven spatial generation

Python imports the data into Blender. Height extrusion and planar distribution first test the mappings; clustering density, structural fracture, emissive cracks, and epicentral waves follow. These five complete model views from the report show the progression from direct mapping to integrated spatial composition.

01

Direct extrusion

Test the relationship between values and height.

02

Spatial distribution

Spread individual objects into a comparable spatial field.

03

Clustering and density

Use grouping and density to organise local structures.

04

Fragmentation and instability

Introduce variation in orientation, fracture, and irregularity.

05

Integrated composition

Integrate height, density, fractures, and waves in one scene.

From one scene to multiple instances

After testing the rules, 20 parameter combinations form a grid for comparison. Each instance combines architectural fragments, displaced ground, fractures, waves, rubble, and dust. Data influences scene density, deformation, and motion intensity.

Compare different data conditions under shared rules.
Images become surface textures; data parameters drive scale and disturbance.
Inspect Blender Python programming and scene development
07

From space to live behaviour

The exported Blender model and final_fusion_data.csv enter Processing. Every 25 frames, the program reads a record. Magnitude controls particle count, emission force, colour, and wave speed; depth and coordinates appear in the data panel. Automatic scene rotation turns static data into an observable temporal process.

Complete sequence: read data → release energy → expand waves → dissipate particles.

Capabilities demonstrated

Python structures disparate sources into analysable tables. Feature extraction, standardisation, clustering, and dimension reduction explain variation. Numerical values become reusable spatial rules, with CSV connecting analysis, modelling, animation, and real-time feedback.

Jupyter / Pandas / NumPy / OpenCV / scikit-learn / Blender Python / Processing