Teaching and doing digital history.

In Brief: The Digital Past – Fall 2014

This semester, I’ve adjusted my H390 – Digital Past syllabus to focus student projects on Gilded Age/Progressive Era Chicago.

My last two classes, which consisted of mostly non-majors, struggled with the breadth of  my “pick a topic in history” final project instructions. I also found that since I am not an expert on all possible historical topics, I spent a great deal of grading time validating basic factual information and immersing myself in their topics so that I could adequately grade them. I’m hoping this is easier for me as well.

Additionally, I find that digital resources on Chicago during this time are quite prevalent. I already teach the Homicide Project Database out of Northwestern University Law School, so adjusting the rest of my in-class exercises worked out well.

The best part about teaching with technology? It’s a constant state of learning and adjustment.

Beyond a Reasonable Doubt

I gave a presentation at the inaugural Women’s History in the Digital World conference  at Bryn Mawr a couple of weeks ago. In the spirit of openness, they posted it to their online repository. It’s available here.

How I Learned to Read Class Materials on my iPad

I’ve always been a paper person. I like to print articles and mark them up in multi-colored highlighters. I write notes in the margins. I employ a complicated symbol system of stars, boxes, brackets and arrows to help me keep track of my thoughts.  The process of writing it down helps me to clarify my thoughts. It helps me remember. I’ve always done it this way.

It occurred to me that it’s a little insane to call myself a “digital” person when I don’t fully employ the technology or the tools available to me. I got an iPad for my birthday in June and until now I only used it for social media. This semester, I decided to experiment with reading articles online instead of wasting the paper to print them. I’d already organized my Zotero libraries to keep track of my sources. I also had purchased GoodReader (at the encouragement of several friends) to help me annotate pdfs, so I don’t lose the note-taking capability.

So far, to keep myself organized between my laptop and my iPad, I’ve been using GoodReader and Dropbox. These apps help me get the articles on my iPad and annotate like a fiend.  It’s pretty efficient. In the event that this system may help others, here is what I did.

Set up Dropbox

Install Dropbox on your computer. (Accounts are free for up to 2GB of storage.)

Open the Dropbox folder and create a new folder. Mine is called “Goodreader Sync.” The only items I put in here are items I plan to read on my iPad.

Set up GoodReader

Once you’ve installed GoodReader ($4.99), open it and select “Connect to Servers” > “Add” > “Dropbox” and input your account information.

Now it’s time to set up the sync: select “Connect to Servers,” click on Dropbox, name your connection–I named mine “Readings.” Tap the folder to connect to Dropbox and sign in with your  login information. Select the Dropbox folder you want to sync,  and select “Sync” from the buttons at the bottom of the window.

Click “Proceed”. GoodReader will then ask you to either create a new folder or “Download Here and Sync”. If you select “download here” all of your readings will populate your general GoodReader folder. I created a special folder in GoodReader to eliminate clutter, but it’s up to you.

Sync Thyself

That’s it! You can now use the green “Sync” button to connect the two. (Remember, you need to be connected to the Internet to sync your files.)

goodreader

So far, my work flow consists of collecting all the week’s pdf readings from the browser on my laptop and organizing them into my “GoodReader Sync” folder in Dropbox. Once I sync from GoodReader, I’m ready to annotate for class.

Anyone else have a way to manage this? As this is the year I organize myself digitally, I’m always looking for suggestions.

Using JavaScript Libraries: Download or Link?

There are numerous open-source JavaScript libraries floating around the web that can be of particular use to historians. Google hosts quite a few of these, including the very popular jQuery and jQueryUI. For data visualization, some good options for historians include: Stanford University’s D3, or MIT’s SIMILE Widgets such as TimelineExhibit andTimePlotTimeMap combines the functionality of Timeline with popular mapping APIs to provide an easy way to plot geographic and chronological events in context.

Once you find a library and decide you want to use it, you need to make a decision, do you download and install the library on your own server or do you just link to the hosted library?  Your answer will depend on a variety of issues.

Linking
Libraries that are hosted elsewhere are handy, there are no files to install and a simple line of script can bring you all the functionality you’d want without you having to architect the file structure on your own servers. To load a hosted library, copy and paste the code snippet for that library (shown below) in your web page. For instance, to load jQuery, embed the <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> snippet in the <head> tag of your HTML page.

However, it’s important to note that any JavaScript that gets included in your webpage runs  within the context of your entire domain and can access any data contained therein. Using a library from a known and frequently-validated entity, such as Google, isn’t likely to cause problems, but it you’re looking to grab functionality from a third-party that isn’t as well-known, these files might cause issues on your own site. Always use code (whether you opt to link to it or download it) from sources you trust.

Additionally, the hosts of the library you’d like to use might not appreciate the additional server load that is created when you link to their libraries. Always read the documentation for instructions how best to use their library. In these cases, you should consider downloading the library to run from your own server. But where do you put it once you have it on your local machine?

Downloading
If you opt to download a JavaScript library, you’ll need (eventually) to upload the entire library to your web server. For ease of organization, you can create a separate “javascript” or “js” folder at the root level of your site to house all of your libraries.

“js” is the folder and contains only JavaScript files and other libraries. You’ll notice here that I’ve installed the “timemap” library. I’ve organized all of my libraries into distinct folders, so that I can keep track of my files. Some of these libraries come with dozens of separate files, so keeping them organized becomes critical as you use more and more of them.

Most library documentation is helpful and includes instructions on how to download, but if you happen upon one that does not, these basic instructions apply:

1. Download the entire library to your local machine.
2. Unzip it and FTP it to the “javascript” or “js” folder on your web server.

That’s it. The library is now available for you to use on any page on your site.

To call your library, you’ll need to include all the appropriate <script> tags in the <head> tag of your HTML page. For example, to load TimeMap, one would need to call five different JavaScript files. In the example below the Google Maps API v3 is being called by a URL, while the rest are pulling from the local server by using the relative path “../js/timemap/lib/” code as seen below.

Troubleshooting
You can use multiple JavaScript libraries, but you should be aware of any possible conflicts. Always check the library documentation for issues of library incompatibilities. You can check for known JavaScript Library conflicts by searching Google for your library name and “conflict,” (e.g., jquery conflict)

To ensure your library is loading correctly, you can use any of the popular in-browser debugging tools like Firebug or Chrome Developer Tools. For example, if one incorrectly types the file name for the Timeline JavaScript file in the <script> tags, the page will fail to load. By using Chrome Developer Tools, it’s easy to see the Internal Server Error is due to a non-existent file on the server; the tool even gives the number of the problematic line of code causing the issue.

JavaScript libraries are a convenient way to harness the power of JavaScript functionality without having to write all the code yourself. Happy coding!

Great Expectations

I had partial success with my mapping project this weekend.

I had originally planned to map each state with little popup boxes showing details on the numbers for each state. It turns out that I greatly underestimated both my skills with JSON files and the Google APIv3 for maps.

But let me back up. I did have success mapping multiple points on a map. I also successfully mapped a point on a map with a detail window on click (click on the marker to see the details.) However, when I tried to map multiple points on a map with detail boxes, that’s where the train went off the rails.

Apparently, the Google Maps API has issues with looping through a long list of details to set markers and info boxes. It only pulls the last info box in the list. There are a nice bunch of tutorials on how to fix the issue, BUT since I am not as well schooled in javascript and calling JSON information, I could not get it to work.. although I did try. My attempt to get it to work is avail here and frankly, I think it’s a big old mess. For one, I’m not sure how to call the separate JSON file. [The tutorial I was using is here. I have his book and his examples were working well for me up until this point, which makes me think it’s a js/json problem.]

For reference, here is my JSON data.

 

I’ll continue to try to debug and hack at it to get it to work, but I’m finding the online documentation only partially helpful. One big problem is that I’m not totally confident that I know how to code the start and end to each file. So when I find code snippets of “solutions” to common problems, I’m not entirely sure where to put the code. Since the order is really important, I’m sure I have some things out of order.

Full code examples would be more helpful so that I can see it in context, but I know this is a learning curve problem, and that it will diminish with time. These “help” blog posts are written for experienced coders and right now I’m a hack at best. So for the time being, I’m embracing my hack status and putting this to the side as a problem for another day.

Getting Ready to Map

I started the evening ready to tutorialize myself in Google APIs and mapping examples. I read two paragraphs and realized that I’d better do some prep work on my own data before I continue.

I also realized that I can organize myself better if I set some goals for my coding work. I have one goal this week: Successfully map all the executions in the database with fancy little popup boxes showing the details for each state. That’s it.

Once I get that to work, for my tutorial in two weeks, I’ll drill down into Virginia, Maryland and DC to show more detailed local information. But, don’t let me get ahead of myself.

On the prepping side, every tutorial I looked at pleaded with the reader NOT to geocode the latitude and longitude information on the server, but to do it in the source database whenever possible.  Since I only have 51 states to deal with and the information is static, adding in lat/long for each execution in the database wasn’t going to require that much brain damage. I created a new table of state lat/long information and populated the appropriate general state lat/long information. [Like everything I do in phpMyAdmin, I did one state by hand and looked at the SQL commands to replicate for the other 50 states. (After 8 weeks, I am beginning to realize that I learn by trial and error–useful, but incredibly frustrating.)] Per Google’s request, I created my lat and long fields in the new table as FLOATS with the size of (10,6), which will allow me to store 6 digits after the decimal, plus up to 4 digits before the decimal, e.g. -123.456789 degrees. I then joined this new table to my main executions table with a new foreign key between my original executions table and the id from the statelatlong table.

I then needed to make sure I actually understood how to JOIN these tables, so I walked through a tutorial (on Wikipedia noless), replaced their fields with my own and TA DA! it worked. For reference, all the information in the results, save lat and long, are located in my original table. The lat long coordinates are stored in the new table. (The code I used is here on my github.)

Now I feel like I’m ready to actually start trying to get my maps to work… the results of which, I’ll describe in a new post. Once I get there.

Getting Answers from Your Data

My assignment this week was was to run the queries I “designed” last week. (*I am, of course, using the term “design” very loosely, as last week was full of hand wringing and general PHP consternation.)

This week, I ran 4 total queries. I am pretty happy with how they turned out:

  1. Total numbers of executions of women with details and counts by race and crime.
  2. Counts of executions of women by state.
  3. Details of executions of women in Virginia with details and counts by race and crime.
  4. Counts of executions of women by year.

I had hoped not only to pull results, but also to display them in a way that made sense. The two biggest challenges proved to be pulling details from each execution into a table and displaying the count for individual variables in the state, year, race and crime fields. Because of the nature of what I was trying to learn, I found my PHP code remained relatively simple, whereas my SQL queries got increasingly more complicated.

Tables

I pulled some code from Jeri and from an online tutorial, but when I ran the php, I was creating an individual table for each row of results. By removing the HTML for the table and header rows from the PHP and using generic html tags, I was able to create one large table.

[sourcecode language=”css”]

<p><h2>Details</h2></p>
<p>Details of all the executions of women, in chronological order.</p>
<p><table border=’1′ cellpadding=’10’>
<tr><th>First Name</th><th>Last Name</th><th>Crime</th><th>Method</th><th>State</th><th>Year</th></tr>

<?php

/* Requery # of women total */
$result = mysql_query("SELECT * FROM executions WHERE sex=’F’ ORDER BY executions.year ASC ", $connection);
if (!$result) {
die("Database query failed: ");
}

/* Organize results of Query into a table */
while($row = mysql_fetch_array($result)) {

// set up a row for each record
echo "<tr>";
echo "<td>" . $row[‘first’] . "</td>";
echo "<td>" . $row[‘last’] . "</td>";
echo "<td>" . $row[‘crime’]. "</td>";
echo "<td>" . $row[‘method’]. "</td>";
echo "<td>" . $row[‘state’]. "</td>";
echo "<td>" . $row[‘year’]. "</td>";
echo "</tr>";

}

?>

</table></p>

[/sourcecode]

Counts and Group By

The other queries were created with complex mysql queries. A fun little function in PHPMyAdmin “show PHP” allowed me to see how the query worked. From there I was able to figure out how to phrase the query and the order in which it should appear. To be honest, this was a long process of trial and error, but once I got the syntax, it is easy to cut and paste and adapt for all of my complex queries.

Thanks to Laura for showing me how to phrase my search, I was able to do some Googling to find good examples of successful Count and Grouped queries.

[sourcecode language=”css”]
<?php
/* Query # of women by race in Virginia */
$result = mysql_query("SELECT crime, count(crime) AS crimeCount FROM executions WHERE sex=’F’ AND state=’VA’ GROUP BY crime ORDER BY crimeCount DESC", $connection);
if (!$result) {
die("Database query failed: ");
}

/* Answer */
while($row = mysql_fetch_array($result)){
echo ($row[‘crime’]) . ": " . ($row[‘crimeCount’]) . "<br />";

}
?>
[/sourcecode]

I was surprised by several of the results that came back. I’m now really looking forward to visualizing these results!

Asking Questions of Your Data

Now that my data is normalized and I have a good idea of what is contained in my database, it’s time to start asking questions of my data. What do I want to know? Which queries are only for me? Which would I like to embed into a web page? While they don’t seem like tough questions, it is beginning to dawn on me that my issues with PHP may be more than just a learning curve. It isn’t so much the learning of the language (although, I am struggling with that), it’s also the fact that I don’t sit down and think about what I want it to do BEFORE I start coding.

I dive right in, copy examples and start changing variables and functions without even thinking about what I want it to do, let alone what this code snippet was programmed to do. The maddening part of PHP is that it’s so personal and subjective–each coder has written into the code their own logic and language. What is mine?

<crickets>

Honestly, I don’t know. I do know the questions I want to ask.

  1. How many women were executed in the United States?
  2. For what crimes? (Cluster the crimes)
  3. In what states? (Cluster both the state numbers AND the crimes by state)
  4. Are there any moments in time where there were an abnormally large group of women executed?
  5. Are there any states in which more women were executed over others?
  6. What of Virginia? What happened here?
  7. What overall trends can I see?
  8. What is missing?

Some of these questions are really specific and easy to both code and show. Others are not. All of this is to say that I’m still working on figuring this out. I admit that this “paralysis by analysis” affected my productivity this week. My output wasn’t what I had been hoping. Still, this is all part of the process, right? Right?

PHP Tango

Oh PHP. How you vex me.

Our assignment this week was to play with PHP, specifically to create a working data entry form using HTML, PHP and MySQL. I can report that, with very generous help from my Clio class, I did all of that.

My simple, but working form is here.
My simple, but functional PHP code is here.

I’m still not sure I totally understand WHY it works. I am told this is natural and to be expected. That with time and increased familiarity, my comprehension will improve. I look forward to that day. I will continue to plug away at it if you promise me you won’t judge or mock me for doing a happy dance every time I can actually make something work.

Deal?

Adventures in Programming

My third year as a PhD student began this week and I’m excited to be taking both Feminist Philosophy & Theory and Programming for Historians. (There’s something ironic and fun about reading The Second Sex in the same week that I’m learning how to create my own databases from scratch.)

As part of our assignment for Clio 3, as we’re affectionately calling our programming class, we’ll be creating technical tutorials for programminghistorian.org. There’ll be a wide variety of topics from my classmates including, creating databases, PHP, web scraping and theory modeling, among others. I’m on the hook for mapping and data visualization, so I’ll be sure to post links to those when they go up. In the meantime, I’ll be putting my development successes and failures in Sandbox.. for all to see. God help me.