Cranberries and Climate Change

The problem with global climate change and agriculture not only that it will probably make it harder to grow crops as the continents dry, but also that where you can grow thing will also change as ecological regions shift. Places where there are long traditions of crops such as sugar maples and cranberries will have to adapt, and often, adapting isn’t easy. This article from Marketplace looks at cranberries in Massachusetts.

Programming Agents

An artful spaceship.

For my programming elective, I thought I’d try to get students programming autonomous agents that we could all compile together into some type of game. Since it was, for most of them a first class in programming, this has proven a little too ambitious, and I’ve had to adjust a bit to build up to it.

Step 1: Build a spaceship/vehicle/agent.

A simple ship made of a sphere, ring, and pyramid, with a clear front end (pointed to the left: vector=(1,0,0).
  • We’re using VPython so we can build 3d ships. Students get to exercise their creativity a bit and learn how to place things in 3d co-ordinate space.
  • The ship must have a front end and all the parts must be put into a single frame so the whole thing can be moved as a unit.
  • Although it’s not required, I’ve added in the beginnings of a trail so we can track the motion of the spaceship
from visual import *

f = frame()
r = ring(frame=f, thickness=.25, axis=(0,1,0))
cabin = sphere(frame=f, radius=0.6, color=color.red)
front = pyramid(frame=f, height=1,width=1,length=2, color=color.blue)
trail = curve(pos=[f.pos,])

Step 2: Make the spaceship a class.

  • Putting the spaceship in a separate class, away from the rest of the code, makes it easier to move from one program to another. That means we can import everyone’s ships into a single program at the end.
from visual import *

class spaceship1:

    def __init__(self):

        self.f = frame()
        self.r = ring(frame=self.f, thickness=.25, axis=(0,1,0))
        self.cabin = sphere(frame=self.f, radius=0.6, color=color.red)
        self.front = pyramid(frame=self.f, height=1,width=1,length=2, color=color.blue)
        self.trail = curve(pos=[self.f.pos,])

ss = spaceship1()

Make the spaceship move

  • We’re going to control the movement of the spaceship using the arrow keys. Left and right to turn; up and down to accelerate and decelerate.
  • To allow movement, we’ll put the keyboard controls into an infinite loop, but to allow maximum flexibility (and to show how to use create methods in a class) we’re putting the actual movement in as methods in the class: the turning method is named turn_xz and movement is move_xz since all the motion is going to be restricted in the xz plane for now.
from visual import *

class spaceship1:

    def __init__(self):

        self.f = frame()
        self.r = ring(frame=self.f, thickness=.25, axis=(0,1,0))
        self.cabin = sphere(frame=self.f, radius=0.6, color=color.red)
        self.front = pyramid(frame=self.f, height=1,width=1,length=2, color=color.blue)
        self.trail = curve(pos=[self.f.pos,])

    def turn_xz(self, turn_rate):
        self.f.axis = rotate(self.f.axis, turn_rate, (0,1,0))

    def move_xz(self, speed):
        self.f.pos = self.f.pos + self.f.axis*speed
        self.trail.append(pos=self.f.pos)
                          
ss = spaceship1()
turn = 0.0
speed=0.0

while 1:
    rate(20)  #slows down execution of the loop

    ss.turn_xz(turn)
    ss.move_xz(speed)

    if scene.kb.keys: # event waiting to be processed?
        s = scene.kb.getkey() # get keyboard info

        if s == 'left':
            turn = turn + 0.01
        if s == 'right':
            turn = turn - 0.01

        if s == 'up':
            speed = speed + 0.01
        if s == 'down':
            speed = speed - 0.01

        if s == ' ':
            if turn <> 0:
                turn = 0
            elif speed <> 0:
                speed = 0

Fire missiles

  • We add in missiles by creating a class very similar to the spaceship. For now our missile is just a ball but I’m putting it into a frame anyway in case later on I want it to be a composite object.
  • Since we can fire multiple missiles, in the code I create a list to hold all the missiles.
  • Missiles are fired using the “a” key.
from visual import *

class spaceship1:

    def __init__(self):

        self.f = frame()
        self.r = ring(frame=self.f, thickness=.25, axis=(0,1,0))
        self.cabin = sphere(frame=self.f, radius=0.6, color=color.red)
        self.front = pyramid(frame=self.f, height=1,width=1,length=2, color=color.blue)
        self.trail = curve(pos=[self.f.pos,])

    def turn_xz(self, turn_rate):
        self.f.axis = rotate(self.f.axis, turn_rate, (0,1,0))

    def move_xz(self, speed):
        self.f.pos = self.f.pos + self.f.axis*speed
        self.trail.append(pos=self.f.pos)
          
class missile:
    def __init__(self, axis, pos):

        self.f = frame(axis=axis, pos=pos)
        self.r = sphere(frame=self.f, radius=0.2, color=color.green)
        self.speed = 0.5
        

    def move_xz(self):
        self.f.pos = self.f.pos + self.f.axis*self.speed

                
ss = spaceship1()
turn = 0.0
speed=0.0

missiles = []  #list for missiles

while 1:
    rate(20)  #slows down execution of the loop

    ss.turn_xz(turn)
    ss.move_xz(speed)

    #move missiles
    for i, m in enumerate(missiles):
        m.move_xz()

    if scene.kb.keys: # event waiting to be processed?
        s = scene.kb.getkey() # get keyboard info

        if s == 'left':
            turn = turn + 0.01
        if s == 'right':
            turn = turn - 0.01

        if s == 'up':
            speed = speed + 0.01
        if s == 'down':
            speed = speed - 0.01

        if s == ' ':
            if turn <> 0:
                turn = 0
            elif speed <> 0:
                speed = 0

        #fire missile
        if s == 'a':
            missiles.append(missile(ss.f.axis, ss.f.pos))

Final adjustments

  • Finally, I’m going to put in a boundary, and set it up to delete the missiles if they go out of bounds.
  • I’m also going to set an option so that the scene follows the ship, which makes it easier to keep track of things.
from visual import *

class spaceship1:

    def __init__(self):

        self.f = frame()
        self.r = ring(frame=self.f, thickness=.25, axis=(0,1,0))
        self.cabin = sphere(frame=self.f, radius=0.6, color=color.red)
        self.front = pyramid(frame=self.f, height=1,width=1,length=2, color=color.blue)
        self.trail = curve(pos=[self.f.pos,])

    def turn_xz(self, turn_rate):
        self.f.axis = rotate(self.f.axis, turn_rate, (0,1,0))

    def move_xz(self, speed):
        self.f.pos = self.f.pos + self.f.axis*speed
        self.trail.append(pos=self.f.pos)
                          

class missile:
    def __init__(self, axis, pos):

        self.f = frame(axis=axis, pos=pos)
        self.r = sphere(frame=self.f, radius=0.2, color=color.green)
        self.speed = 0.5
        

    def move_xz(self):
        self.f.pos = self.f.pos + self.f.axis*self.speed

class bounds:
    def __init__(self, boundary_distance):
        self.boundary_distance = boundary_distance
        self.border = curve(pos=[(-boundary_distance,0,-boundary_distance),
                                 (boundary_distance,0,-boundary_distance),
                                 (boundary_distance,0,boundary_distance),
                                 (-boundary_distance,0,boundary_distance),
                                 (-boundary_distance,0,-boundary_distance)])
    def in_bounds(self, pos):
        if ( pos.x < -self.boundary_distance or
             pos.x > self.boundary_distance or
             pos.z < -self.boundary_distance or
             pos.z > self.boundary_distance):
            return false
        else:
            return true
        

ss = spaceship1()
turn = 0.0
speed=0.0
l_track_ship = 1
scene.range=10
scene.forward = (0,-1,0)
missiles = []

boundary_distance = 100
boundary = bounds(boundary_distance)

while 1:
    rate(20)

    if l_track_ship > 0:
        scene.center = ss.f.pos
    
    ss.turn_xz(turn)
    ss.move_xz(speed)

    #move missiles
    del_list = []
    for i, m in enumerate(missiles):
        m.move_xz()

        #delete missile if out of bounds
        if boundary.in_bounds(m.f.pos) == False:
            del_list.append(i)
    for i in del_list:
        missiles[i].f.visible = False
        del missiles[i]
            
    
    #if m <> None:
    #    m.move_xz()

    if scene.kb.keys: # event waiting to be processed?
        s = scene.kb.getkey() # get keyboard info

        if s == 'left':
            turn = turn + 0.01
        if s == 'right':
            turn = turn - 0.01

        if s == 'up':
            speed = speed + 0.01
        if s == 'down':
            speed = speed - 0.01

        if s == ' ':
            if turn <> 0:
                turn = 0
            elif speed <> 0:
                speed = 0

        #fire missile
        if s == 'a':
            missiles.append(missile(ss.f.axis, ss.f.pos))
    

Next steps

Now that we’re cooking with charcoal — we have a functioning program — the next steps will be setting up a target to shoot at, and, if the students are ready, letting them program their ships to move autonomously. If they’re not ready then, as an example, I’ll program some opposition.

Eating Frankenfish

Ian Simpson has an interesting article on the movement to reduce the numbers of the invasive snakehead fish more appealing to restaurants and their customers.

[Snakeheads have] dense, meaty, white flesh with a mild taste that is ideal for anything from grilling to sauteing.

[But] the fish are air breathers that can last for days out of water. Even when gutted and with their throats cut, they gape for breath, said John Rorapaugh, director of sustainability and sales at ProFish, a Washington wholesaler.

“Once they get to mature size, they are on top of the food chain and are ravenous,” he said.

Josh Newhard, an expert on the snakehead with the U.S. Fish and Wildlife Service, said it was too early to say what the snakehead’s long-term impact would be on its invaded environment. … “The potential is really high for them to impact other fish species. The fact that people want to remove them from the system is really good,” he said.

–Simpson (2012): U.S. chefs’ solution for invading Frankenfish? Eat ’em from Reuters via Yahoo! News.

My middle-school students are reading Janet Kagan’s short story, “The Loch Moose Monster” as part of our discussion about genetics, ecology and educational environments. This article makes a nice complement.

Cross-Country

The ridge-top trail.

There’s a trail that runs along the forested ridge above the school. With summer phasing into fall, and the smell of winter in the air, I decided to offer cross-country running as my P.E. option this quarter.

Just getting to the ridge-top is a strenuous jog up a steep slope (note to self: I need to get the geometry students to calculate the slope), especially with the thick, slippery layer of this fall’s accumulated leaves to test the unwary, and I was a little surprised that about half a dozen students actually took me up on it.

Climbing the steep, slippery, leaf-covered slope is not trivial.

Indeed a few more students have accreted onto our group since we started, casualties of the other P.E. options for the most part. But I’d like to think that the beauty of the wooded landscape — brilliant elm and sugar maple leaves littering the ground; crisp, cool air against flushed skin; the fresh, decisive smells in the ridge-top air; the crack an crackle of leaves underfoot — may have also attracted some attention.

I’m looking forward to observing how the slope and forest change with the coming winter.

Autumn sunlight parses the forest.

Suffrage in the U.S.A.

Go back in time and see who would have won the last presidential election. BuzzFeed has an excellent set of maps showing who would have won the election if voting was restricted as it was in the past.

2012: The actual voting map. (Image from BuzzFeed).
1970: Adults over 24 years old (before the voting age was lowered to 18). (Image from BuzzFeed).
1920: Women’s sufferage. Only white voters (men and women). (Image from BuzzFeed).
1870: Only men can vote. (Image from BuzzFeed).
1850: When only white men could vote. (Image from BuzzFeed).

The video below gives a quick history of when voting rights were extended to different demographic groups.

Diwali

Dias in St. Louis.

I remember driving around town looking at the lights … arcs of dias sitting on split-bamboo trellises … everywhere. Hundreds and thousands of little flickering lights.

I remember refilling the oil in the dias and replacing the wicks as they went out.

I remember attending prayers, and eating good food — curry, dal, rice, roti — with my hands off banana leaves.

I found a new Indian/Pakistani grocery last week, just in time for Diwali. Diwali’s got elements of Thanksgiving (harvest feast), Christmas (lights and some present giving), and New Years (in some parts of India). Mostly, I remember it as the Festival of Lights. So, I picked up six dias at the store, and improvised with cooking oil and string (for the wicks), so my kids could have their chance to play with fire.

I think I’ll bring them into school too. Last week the middle schoolers attended a diversity conference. They didn’t seem to get too much out of it, so I’ve been trying to be a little more explicit about the subject.

Taking care of the dias on a cold, November night.

Invasive Species on Campus

A student helps Scott Woodbury uproot an invasive bush honeysuckle.

Last Friday, we were lucky enough to have a horticulturalist, Scott Woodbury, visit the Environmental Science class. Scott teaches the Native Plant School at the Shaw Nature Reserve, and spends a lot of effort dealing with invasive species.

The extent of the problem on our campus was quite sobering. The invasive trees, shrubs, and vines displace native plants, and animals as well because the native fauna are not adapted to them. A native elm might support somewhere around 300 species of caterpillar, while an imported bradford pear might have just a few; Douglas Tallamy has a good book, Bringing Nature Home, on the subject.

This beautiful bradford pear is one of half a dozen at the front of the building. They are quite aggressive however, and their progeny can be found all the way along the creek and up the slope.
A young bradford pear on the slope.

The bradford pears are quite pernicious. They were once favored by landscapers because of their beautiful spring flowers and brilliant fall colors. However, the birds spread their seeds far and wide, and now bradford pear saplings can be found all over the campus. They tend to do better in the grassy areas at the sides of the roads, as well as on the slope overlooking the school that’s still in the early stages of succession. The saplings can be cut down with hand saws, and I doubt anyone would notice that they were gone, but it’s probably going to be tricky getting permission to take down the half dozen mature trees on the front lawn that were planted when the school was built.

Bright orange berries on a vine of oriental bittersweet.

The dark secret about the oriental bittersweet vine that’s attacking the trees along the creek, is that they probably came from the Shaw Nature Reserve. Apparently there was a mistake at one of their sales, and one of our teachers bought the wrong species of bittersweet. Cutting the vines that are growing up the tree trunks should slow them down.

Scott Woodbury holds the long stem of a specimen of sericea lespedeza. The entire slope behind him is covered with the species.

Sericea lespedeza has pretty much taken over the slope above the school. This herb was imported for erosion control but was found to be extremely hard to control. On the plus side, while it does well in disturbed areas like the slope, since it is an early succession species, it will be succeeded by the tree species that are now growing up through it. It’s just going to take a number of years.

Bush honeysuckle.
Hand pulling a bush honeysuckle.

At least the bush honeysuckles, which can be found all along the creek, can be hand pulled if they’re small enough. However, we’ve got some pretty big specimens that are much harder to get rid of. They grow fast, leaf-out early, and crowd out the native shrubs.

Interestingly, all these four species are all from Asia. The latitude is similar to Missouri’s so species from that part of the world can thrive here where the climate is similar and they don’t have their native predators and pests. Scott did point out a couple of native species — eastern red cedars and sugar maples — that have become much more aggressive because of all the fire suppression over the last few hundred years, but that’s a story for another time.

Invasive versus native species.