Archive | November, 2012

Architectural Criticism

29 Nov

Make no little plans. They have no magic to stir men’s blood and probably themselves will not be realized…Think big. –Daniel Burnham

Architectural Criticism is dead, and so is the architectural critic. We just don’t read about architecture. I pre-ordered Alexandra Lange’s book “Writing About Architecture.” I even wrote a short piece on it at The Urban Times. I care about the built environment but I am not an architect. And I know far too many architects who have no interest in architectural criticism. Who think Ada Louise Huxtable was Bill Cosby’s wife on the Cosby Show and that Bjarke Ingels wore a swan dress to the 73rd Academy Awards.

Bjork: Icelandic Singer

Bjarke: Danish Architect

If architects show little interest in the current state of their field, why should the rest of us? Because we are forced to live in it, to look at it, to work in it. Architecture affects our lives more than almost any other discipline. What gets built is of crucial importance to all of us. It is the role of the architecture critic to educate us, the non-architects, about what is built and why we should or shouldn’t like it.

Do I need Paul Goldberger to tell me whether a building is good or bad? While he may provide a context or background I was unaware of, I can come to my own conclusions as to the aesthetic of the building. If I think it’s ugly, Goldberger is not going to change my mind. What he, and so many other architecture critics are doing, is writing for each other, for the architect, for the intellectual. The rest of us don’t know all the jargon. I couldn’t tell you Bauhaus from my house. The jargon and the pseudo-intellectualism is the primary reason that we do not read about architecture.

Another reason that we don’t read architecture is because we don’t care about a building in Qatar or China – even if it is by Hadid or Gehry. Did you know Zaha Hadid is designing the new National Stadium in Japan? Did you care? Does this change the way you live your life? Do you now have a strange desire to see all buildings NURBy? Buildings go up in every city. The majority of which receive no fanfare. They are designed and built by local architects, that nobody could name. There are no movies about these architects. They are not celebrities. But they impact our lives. These are the architects we should care about. That we should be reading about. I spend more time in Home Depot than the Bird’s Nest Stadium. Should a critic write a review of Home Depot or Starbucks?

Beijing National Stadium: The Bird’s Nest

Architectural critics write about new buildings by starchitects. Goldberger, in a speech “Architectural Criticism in the Age of Twitter,” said:

Crowdsourcing is not the express train to wisdom. The most popular is not always the best. The new is not always easy to understand. And the last word will always be history’s. But this is always the critic’s challenge. In an age in which attention spans are ever shorter, it is the critic’s job to take the long view.

This sounds fantastic! The critic takes the long view. But does he? He reviews a building when it’s built, or maybe when it was designed and planned. But does he ever go back and re-review the building. Does the building function? How has the building aged? Does it still function as intended or was it modified? His long view is one of more thought – not just initial reactions and tweets of images. But this intellectual thought does not improve the building. In a few years we will all know what we think of the building and nobody will remember the critics review.

If a building is a failure, does criticism prevent the same mistakes in the future, or are we too late? A failure of a building is an expensive mistake that we must live with for decades. If criticism doesn’t educate us, it does nothing.

Pruitt-Igoe: A massive failure that lasted 20 years.

While we may not be reading about architecture, we are reading about the City and the Urban. Maybe this larger view is the future of architectural criticism. The design of buildings is important in what they contribute or take away from the system. Some critics and writers, Lewis Mumford and Jane Jacobs, have always looked at the surroundings of a building – the impact that it had on the city. Jane Jacobs also has more of a mass appeal than Paul Goldberger. The rest of us care about our surroundings. But we see them as larger than a single address. They are our cities and towns. This is the puzzle we are putting together and trying to understand.

Architects and critics need to expand their view. To look beyond the property line.

…..to think Big.

Advertisements

D3.js and MongoDB

28 Nov

I have not been shy in my love of MongoDB. The honeymoon is not over. Now I want to graph and visualize my data from MongoDB. I just started looking at D3 – I’m coming to the party a bit late – and it is perfect for this task. I have thrown together a super simple, absurd even, example using a DB I had already populated and some left over CherryPy code. Let me say that reusing code is a good idea – when I can find what I’m looking for. It allows me to throw something together quickly. These are not production samples, but just for me to see that I can get it to work. Enough already. Here is a bar chart using D3 and MongoDB.

d3

A Bar Chart, that should be in SVG, from MongoDB data in D3.js

I have not put this on OpenShift yet, but may.  This bar chart is a simple python script using CherryPy and committing my favorite sin – passing HTML as a variable in a return. One reason to put it on OpenShift is so I can template it in Jinja.  Here is the code:

import cherrypy
from pymongo import Connection

class mongocherry(object):

def index(self):
db=Connection().geo
output =[]
output.append(‘<HTML><HEAD><TITLE>D3 and MONGODB</TITLE><script type=”text/javascript” src=”http://d3js.org/d3.v2.min.js”></script><style type=”text/css”>div.bar {display: inline-block;width: 20px;height: 75px;margin-right: 2px;background-color: teal;}</style></HEAD><BODY><h1>D3 and MongoDB</h1>’)
output.append(‘<script type=”text/javascript”>var dataset=[‘)

for x in db.places.find():
output.append(str(x[“loc”][0])+’,’)
output.append(‘0];’+”\n”+’d3.select(“body”).selectAll(“div”).data(dataset).enter().append(“div”).attr(“class”, “bar”).style(“height”, function(d) {var barHeight = d * 5;return barHeight + “px”;});</script></body></html>’)

i=0
html=””
while i<len(output):
html+=str(output[i])
i+=1

return html

index.exposed = True

cherrypy.config.update({‘server.socket_host’: ‘127.0.0.1’,
‘server.socket_port’: 8000,
})

cherrypy.quickstart(mongocherry())

The Python code prints out HTML that looks like this:

<HTML><HEAD><TITLE>D3 and MONGODB</TITLE>
<script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script>
<style type="text/css">
div.bar {
display: inline-block;
width: 20px;
height: 75px;
margin-right: 2px;
background-color: teal;}
</style>
</HEAD><BODY>
<h1>D3 and MongoDB</h1>
<script type="text/javascript">
var dataset=[35,35.8,38,39,30,31,31,31,33,25,33,0];
d3.select("body")
.selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", function(d) {var barHeight = d * 5;return barHeight + "px";});
</script></body></html>

Not much going on here, just a simple D3.js bar chart – not even done in SVG. The MongoDB part is in the variable dataset[..]. While writing the HTML, the python code loops through my mongodb with for x in db.places.find(): and it grabs the latitude of the data I have with x[“loc”][0] prints it out in the JavaScript variable dataset[]. I add a 0 at the end because I get a trailing comma. Sloppy, but oh well.

I return all the HTML and you get the page displayed at the top of this post. The cool part of marrying D3.js and MongoDB is JSON. I have JSON in my DB and D3 takes JSON.

OpenShift: Leaflet.js, MongoDB, and Flask

28 Nov
Leaflet Map

My simple application on OpenShift. Pulling data from MongoDB and presented using Leaflet.js

PaaS: Platform as a Service

I write a lot of small applications and scripts to improve my programming skills and to hopefully use in my work. Unfortunately, I cannot share most of them because  I don’t have access to a server – almost all of my apps run on a WAMP stack using localhost:8080.  Recenlty, I saw a tweet about a service by Red Hat – I remembered them from my Linux club days in college – called OpenShift. OpenShift is a Platform as a Service (PaaS) that “manages the stack so you can focus on your code.” It promised a way to for me to run all the new technologies my web host won’t allow. I had to try it out.

What I Want to Build

I make a lot of maps. Just simple point maps with a polygon here or there. No real geoprocessing or analysis. Just for displaying data. My application needed to display a map. My front-end of choice is Leaflet.js – a JavaScript library- and I have to be able to use it.

I am not a programmer but dabble in a few languages. Python is the one I am most comfortable with and I am more fluent in it than any other language. It is also a language I enjoy and having an interactive shell makes my coding go much faster. I can test solutions before they ever go in my program. If I am going to have a chance at success, I have to use Python.

All of my Python programming on the web has been using CherryPy. It is a minimal framework that was easy to install and to learn. I only need to do simple things like route and pass data so why go Django or Pylons – Pyramid now?

I really like  MongoDB. You may think spatial is special and get all PostGIS on me, but for what I need and what I like to do, I am all about MongoDB right now. So I need to be able to install it.

To summarize, I need – or want:

  1. Leaflet.js
  2. Python
  3. CherryPy
  4. MongoDB

Getting Started

Go to OpenShift and setup an account.

I am not a reader of manuals – OpenShift has a good one – but more of an experimenter and skimmer.  I used the OpenShift getting started and a blog post – REST web services with Python, MongoDB, and Spatial data in the Cloud – to get up and running. The blog used Flask, which I have never used before, but it does the same thing I was using CherryPy for, so I used it. In reading more about Flask, I found that it has a templating engine called Jinja2 available. When pushing my code to GIT, I saw that Jinja was already on OpenShift. I will admit, I am bad about templating and put all my HTML in a variable and have a function ‘return HTML.’ With this application, I wanted to break that bad habit.

After getting the Ruby Installer and Git, I followed all the instructions in the getting started and the blog and was left looking at a folder on my computer with some stuff inside of it. Now it’s time to play.

Coding the Application

The stuff in my folder is an application using Flask that I grabbed from GIT.  The important part is in the WSGI folder. The MyFlaskApp file has code that grabs data from a MongoDB and dumps it out to a webpage. This is the file I will edit to make my app.

Before I do anything else, I want to write my webpage. It will be nothing more than a simple Leaflet map with one marker at a point retrieved from MongoDB. It will also be a Jinja Template.

Here is the code for my webpage.

<!doctype html>
<head><title>OpenShift: Leaflet, MongoDB, Python. Jinja2</title>
<link rel=’stylesheet’ href=’http://cdn.leafletjs.com/leaflet-0.4/leaflet.css&#8217; />
</head>
<div id=’map’ style=’width: 900px; height: 350px’></div>
<script src=’http://cdn.leafletjs.com/leaflet-0.4/leaflet.js’></script&gt;
<script>
var map = L.map(‘map’).setView([40.71367, -73.99364 ], 13);
L.tileLayer(‘http://{s}.tile.cloudmade.com/API-KEY/997/256/{z}/{x}/{y}.png’,{attribution:’Paul Crickard’, maxZoom: 18 }).addTo(map);
L.marker({{ coord[“pos”] }}).addTo(map)
</script>

This file needs to be put in a folder in WSGI called TEMPLATES. You will notice another folder in the directory called STATIC. This is where you can put CSS and JS files.

The code is straight HTML and JavaScript with the exception of   {{ coord[“pos’ }}. This is the Jinja part of the template. In the Flask Application, I will pass coord to the template.

Let’s take a look at a simple Flask application that will grab the point from MongoDB and send it to my Jinja Template. Here it is:

from flask import render_template

@app.route(“/ws/albuquerque”)
def albuquerque():
conn = pymongo.Connection(os.environ[‘OPENSHIFT_MONGODB_DB_URL’])
db = conn.parks
for z in db.location.find():
q=z
return render_template(‘map2.html’,coord=q)

The file I modified already has several import statements but you will need to add render_template to use Jinja. I changed the route to /albuquerque – I was going to use some local data but decided for a test I would use the parks JSON file so now the Albuquerque doesn’t make much sense. Then I grab a cursor and pass a point to q. Lastly, I call the render_template and hand it q as coord. Now in my HTML/Jinja Template, I can call coord. For the future, I would run a loop in the Template that grabbed all the points. A loop in Jinja looks like this:

{% for x in json %}
   Do something with X: 
   L.marker({{ x }}).addTo(map) 
{% endfor %}

Now go to my RHCloud.com and see it in action. It seems rather simple – I need to add some popups – but there is some powerful technology behind this. MongoDB has some spatial features like $near, $box or $within $center of a circle. This should somewhat please the spatial is special crowd. One of the things I love is that I can have an object {“pos”:[35,-106],”name”:”ABQ”} and I can have another {“pos”:[33,-106],”name”:”LL”, “visitors”: 50}. In a table, every record has the same fields – I don’t have to do that in MongoDB. I see MongoDB as much more flexible for my needs.

Next Steps

What functionality would I like to add to this?

  1. A form that allows the user to select either all the data or a subset using simple radio buttons or combo boxes.
  2. A way to download a report of the data selected.
  3. A form for users to enter new data.
  4. Popups with additional data. This should only require adding .bindPopup( {{coord["popupContent']}} )

One last thing: It runs on mobile. My HTML is not very good, but a mobile Leaflet app is simple. I have one that uses your phone’s current location on my website.

My App Running on Mobile

Flask App Running on iPhone 4S

MongoDB and Shapely

18 Nov

I wanted to connect my mongoDB to Shapely so that I could create buffers and do some other things, like spit out my points and buffers as WKT. Here is what I came up with.

from pymongo import Connection,GEO2D
from shapely.geometry import asShape,Point
db=Connection().a
db.b.create_index([(“loc”,GEO2D)])

db.b.insert({“loc”:[-106,35]})
db.b.insert({“loc”:[-109,39]})

for q in db.b.find({“loc”:{“$near”:[-106,35]}}).limit(1):
point=Point(q[“loc”][0],q[“loc”][1])  #this is passing mongoDB to Shapely

point.x    #just checking I didn’t make a mistake

point.y

t=point.buffer(2)
t.area  #checking. Result is 12.a lot of number

point.wkt

t.wkt

Now I can use mongoDB and find all the points in a bounding box or near another point or near a point where type=Coffee Shop, then send that to Shapely for a buffer or to measure distance or whatever, then spit it out as WKT. Saw a tutorial on using shapely with GDAL/OGR and Fiona. Goodle that and see how to send it all back to a shapefile.

Store Email in MongoDB

16 Nov

I want to store all the information about an architectural project in a database. I have all the building information in mongoDB but I also want other information – like change orders or all the emails about the project. In this post, I will load my email from Outlook in to MongoDB.

In Outlook, you can export a folder to Excel. Go to File>Import and Export

Select A FILE, then choose Excel. Lastly, select the folder where you have placed all your project emails.

You should now have an Excel sheet with email information. I am only interested in the Subject, Body, and who it is from. Using Python, Pymongo, and XLRD, I converted the Excel to MongoDB:

from pymongo import Connection
from xlrd import open_workbook

wb=open_workbook(‘mailxls.xls’)
sheet=wb.sheet_by_index(0)

db=connection=Connection().building

for rownum in range(sheet.nrows):
subject=sheet.cell(rownum,0).value
body=sheet.cell(rownum,1).value
fromname=sheet.cell(rownum,2).value
db.building.email.insert({“subject”:subject,”body”:body,”from”:fromname})

db.building.email.remove({“body”:”Body”})

 

Because rownum starts at 0 and 0 is my headers, I use the last line to remove the headers. You could probably delete them out of the Excel file, or adjust your loop when you read the file. This was a quick solution since I accidentally put them in already.

Now you have emails in MongoDB and can query away. This is a good start to a project management system using mongoDB. Wondering what the value of a BIM in mongoDB would be. Do we need to maintain the relation nature of the model, or can a document model work?

 

Convert MongoDB to GeoJSON: Use in Leaflet.js

16 Nov

Leaflet.js is my favorite tool for making quick web maps. Using GeoJSON, you can feed data to Leaflet either by pasting it in to your code or by making it a variable and saving it as a .JS and importing it. How you do it is up to you, but in this example I am going to copy and paste in my GeoJSON text. My GeoJSON will be generated from a mongoDB using Python.
I created a mongoDB with a series of points (Long, Lat). Then I wrote a Python script to grab all those points and dump them in to a GeoJSON file. Lastly, I paste that as a variable in my Leaflet code.
Taking this project further, try using the select near, or select near where type:coffee shop, features in mongoDB. You could use bounding boxes too.

Here is the python code to convert mongoDB to GeoJSON:

from pymongo import Connection,GEO2D
db=Connection().geo

geojson=open(“mongoLoop.json”,”w”)
geojson.write(‘{ “type”: “FeatureCollection”,’+”\n”)
geojson.write(‘”features”: [‘+”\n”)

x=0
d=db.places.count()

for i in db.places.find():
if x < d-1:
geojson.write(‘{ “type”: “Feature”,’+”\n”)
geojson.write(‘”properties”: {“popup”: “value0”},’)
geojson.write(‘ “geometry”: {“type”: “Point”, “coordinates”: [‘)
p1=i[“loc”][0]
p2=i[“loc”][1]
geojson.write(str(p1)+’,’+str(p2)+’]}},’+”\n”)
x=x+1
print “x =” + str(x)
else:
geojson.write(‘{ “type”: “Feature”,’+”\n”)
geojson.write(‘”properties”: {“popup”: “value0”},’)
geojson.write(‘ “geometry”: {“type”: “Point”, “coordinates”: [‘)
p1=i[“loc”][0]
p2=i[“loc”][1]
geojson.write(str(p1)+’,’+str(p2)+’]}}’+”\n”)
print “Last Loop”

geojson.write(‘]}’)
geojson.close()

And the output:

{ “type”: “FeatureCollection”,
“features”: [
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [35,-106]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [35.8,-106.8]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [38,-108]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [39,-109]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [30,-100]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [31,-101]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [31,-102]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [31,-103]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [33,-100]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [25,-102]}}
]}

Lastly the HTML to create the Leaflet map – input your API Key:

<!DOCTYPE html>
<html>
<head>
<title>My Map</title>
<meta charset=”utf-8″ />

<link rel=”stylesheet” href=”http://cdn.leafletjs.com/leaflet-0.4/leaflet.css&#8221; />
<!–[if lte IE 8]><link rel=”stylesheet” href=”http://cdn.leafletjs.com/leaflet-0.4/leaflet.css&#8221; /><![endif]–>
</head>
<body>
<div id=”map” style=”width: 600px; height: 400px”></div>

<script src=”http://cdn.leafletjs.com/leaflet-0.4/leaflet.js”></script&gt;

<script>

var map = L.map(‘map’).setView([35, -106], 13);

L.tileLayer(‘http://{s}.tile.cloudmade.com/API-KEY/997/256/{z}/{x}/{y}.png’, {
attribution: ‘Map data &copy; <a href=”http://openstreetmap.org”>OpenStreetMap</a&gt; contributors, <a href=”http://creativecommons.org/licenses/by-sa/2.0/”>CC-BY-SA</a&gt;, Imagery © <a href=”http://cloudmade.com”>CloudMade</a>&#8217;,
maxZoom: 18
}).addTo(map);

var mongo = { “type”: “FeatureCollection”,
“features”: [
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [-106, 35]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [-106.8,35]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [-108, 38]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [-109, 39]}},
{ “type”: “Feature”,
“properties”: {“popup”: “value0”}, “geometry”: {“type”: “Point”, “coordinates”: [30,-100]}}
]};

var myLayer = L.geoJson().addTo(map);
myLayer.addData(mongo);

</script>
</body>
</html>

Web Based Spreadsheet with CherryPy and XLWT

15 Nov

An example of a simple spreadsheet through the web. Uses a Table and Form.

The code:

import cherrypy
from cherrypy.lib.static import serve_file
import xlwt

class SHP(object):

def index(self):
return “””<HTML><HEAD><TITLE>SPREADSHEET</TITLE></HEAD>
<BODY><FORM NAME=’sheet’ action=’paul’>
<table border=’1′>
<tr><td><input type=”text” name=”r0c0″></td><td><input type=”text” name=”r0c1″></td><td><input type=”text” name=”r0c2″></td></tr>
<tr><td><input type=”text” name=”r1c0″></td><td><input type=”text” name=”r1c1″></td><td><input type=”text” name=”r1c2″></td></tr>
<tr><td><input type=”text” name=”r2c0″></td><td><input type=”text” name=”r2c1″></td><td><input type=”text” name=”r2c2″></td></tr>
</table><BR>
<input type=’submit’ Value=’SUBMIT’>”””

index.exposed = True

def paul(self,r0c0,r0c1,r0c2,r1c0,r1c1,r1c2,r2c0,r2c1,r2c2):
wb=xlwt.Workbook()
ws=wb.add_sheet(‘Web Sheet’)
ws.write(0,0,r0c0)
ws.write(0,1,r0c1)
ws.write(0,2,xlwt.Formula(r0c2))
ws.write(1,0,r1c0)
ws.write(1,1,r1c1)
ws.write(1,2,xlwt.Formula(r1c2))
ws.write(2,0,r2c0)
ws.write(2,1,r2c1)
ws.write(2,2,xlwt.Formula(r2c2))
wb.save(‘Spreadsheet.xls’)

return “Download Spreadsheet: <a href=’/get?filepath=C:\Documents and Settings\user\Desktop\Spreadsheet.xls’>Your Spreadsheet</a>”

paul.exposed = True

def get(self, filepath):
return serve_file(filepath, “application/x-download”, “attachment”)
get.exposed = True

cherrypy.config.update({‘server.socket_host’: ‘127.0.0.1’,
‘server.socket_port’: 8000,
})

cherrypy.quickstart(SHP())