James P Howard

Cardiology trainee in London

I'm a NIHR Academic clinical fellow in cardiology at Imperial College London.

Some of my key publications are listed below; others are visible on my Google Scholar profile and CV.

About this site

This site is created by a relatively simple Python script.

It's probably all pretty self-evident (code below). I create a list of papers, consisting of a title, journal, URL, Google Scholar identifier and description. The script simply echos HTML, then iterates through the list, calling the function display_paper() for each entry.

The display_paper() function reformats the entry as nice HTML, but also calls the function pull_citations(). This function accesses the Google Scholar page for the paper in question and looks for the words "Cited by ..." where '...' is a number. It then returns this value to the page, to show in real-time the number of citations listed for the paper on Google Scholar. The citation indices are grabbed by a similar method, scraping the html for identifying tags.

This is of course a very simple Python page, but illustrates the strength and versatility of using Python to render dynamic pages.


from flup.server.fcgi import WSGIServer
from cgi import escape
from datetime import timedelta
import sys, os, urllib2, sre

papers = [ 	["CONVERGE","Heart","http://heart.bmj.com/content/99/21/1579.short","CyuQ1RUAAAAJ:Y0pCki6q_DkC","Early renal denervation trials showed office blood pressure reductions of ~30 mmHg, yet reductions in ambulatory blood pressures appear to be several-fold smaller. This paper correctly predicted, through meta-analysis of drug trials, the startlingly lower results seen in the landmark SYMPLICITY-HTN 3 trial. Our work has been covered by <a href="http://www.forbes.com/sites/larryhusten/2014/01/09/pivotal-medtronic-trial-for-breakthrough-blood-pressure-device-goes-down-the-tubes/">Forbes</a>, <a href="http://www.medscape.com/viewarticle/819018#2">Medscape</a> and <a href="http://www.fool.com/investing/general/2014/01/09/medtronics-surprising-update-spikes-blood-pressure.aspx">the Motley Fool</a>" ],
			["Big day bias","International Journal of Cardiology","http://www.sciencedirect.com/science/article/pii/S0167527314000436","CyuQ1RUAAAAJ:SdhP9T11ey4C","After CONVERGE and Symplicity-HTN 3 demonstrated a huge disparity between results from unblinded/uncontrolled trials and the gold-standed double-blinded RCT trials, we wrote this paper to explain why and how researchers should minimise the effects of bias when designing hypertension trials."],
			["Removing the hype from hypertension","BMJ","http://www.bmj.com/content/348/bmj.g1937","CyuQ1RUAAAAJ:eq2jaN3J8jMC","An editorial published in the BMJ following the findings from the Symplicity-HTN 3 trial, re-iterating the importance of good trial design in hypertension."],
			["Early STEMI discharge","Heart","http://heart.bmj.com/content/98/23/1722.short","CyuQ1RUAAAAJ:2osOgNQ5qMEC","We investigated the safety and feasibility of very early discharge 2 days following PPCI in selected low risk STEMI patients. Our data suggest that discharge of such patients two days after successful PPCI is feasible and safe. Over 40% of all patients with STEMI may be suitable for early discharge with important implications for healthcare costs."],
			["Ascites in constrictive pericarditis","Frontline Gastroenterology","http://fg.bmj.com/content/3/4/233.short","CyuQ1RUAAAAJ:d1gkVwhDpl0C","An educational review and case series of constrictive pericarditis patients, emphasising how this disease may manifest in a variety of ways, leading to misdiagnosis. We covered two patients who were initially wrongly diagnosed as having hepatic or respiratory diseases."] ]

others = [	["My CV (PDF)","http://jamesphoward.com/CV.pdf","A bit more about my education, training and research interests to date."],
			["CardiologyTrials.org","http://cardiologytrials.org","My website covering the most important trials in cardiovascular medicine. Currently, with over 90 trials, it receives around 2000 visitors per month."],
			["NETFS Swap shop","/swapshop/","In 2011 the North East Thames Foundation school allowed foundation doctors to swap their F2 jobs in a 'swap shop' for the first time. Unfortunately 'round robin' emails about swaps from 100+ candidates made the system unusable. I realised the need for a more efficient system and created a simple PHP-powered database. Doctors were able to find their name in the database on the website, sign-in, and tick which jobs they were interested in swapping to. The system then highlighted to each doctor who was interested in swapping with them."],
			["FMCalc","/fmcalc.htm","Initially there were no good medical calculators for Windows Phone 7. I therefore worked to create a free alternative, FMCalc. The application is now on the official Windows Phone 7 marketplace and has been downloaded by over four thousand unique users in fifteen different countries."],
			["About this site","./about.fcgi","How this site works; an explanation of how python can be used to 'program' websites dynamically and easily."] ]

def app(environ, start_response):
	start_response('200 OK', [('Content-Type', 'text/html')])
	yield display_http_header()
	yield google_analytics()

	yield display_container()
	yield """
			<div class="left">
				<div class="box col1h">Research</div>"""
	for paper in papers:
		yield display_paper(paper[0],paper[1],paper[2],paper[3],paper[4])
	yield """
			<div class="right">
				<div class="box col2h">Other</div>"""
	yield """
			<div class="box col2">
			<h3><a href="http://scholar.google.com/citations?user=CyuQ1RUAAAAJ&hl=en">Google Scholar metrics</a></h3>"""
	yield "<p>Total citations:" + pull_indices(0) + "</p>"
	yield "<p>H-index:" + pull_indices(2) + "</p></div>"
	for other in others:
		yield display_other(other[0],other[1],other[2])
	yield """
	yield display_footer()
def display_http_header():
	return """
	<!DOCTYPE html>
		<title>Dr James P Howard</title>
		<link rel="stylesheet" type="text/css" href="./jph.css">
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
		<meta name="robots" content="index,follow"/>
		<meta name="description" content="jamesphoward.com - a junior doctor in London"/>

def display_container():
	return """
	<div class="container">
		<div class="header">
			<h1>James P Howard</h1>
			<h2>A junior doctor in London</h2><br />
			<p>Welcome to my website. It's actually a <a href='/about.fcgi'>Python</a> script, but that's not important.</p>
			<p>I (am/will be) an <a href="http://www.nihrtcc.nhs.uk/intetacatrain/">NIHR Academic clinical fellow</a> in cardiology at <a href="http://www3.imperial.ac.uk/">Imperial College London</a>.</p>
			<p>Some of my key publications are listed below; others are visible on my <a href="http://scholar.google.co.uk/citations?user=CyuQ1RUAAAAJ&amp;hl=en">Google Scholar profile</a>.</p>
		<div class="main">"""
def display_paper(title,journal,address,scholar,description):
	return "<div class="box col1"><h3><a href="" + escape(address) + "">" + title + "</a></h3><p><a href="" + escape(address) + "">" + journal + " (" + pull_citations("http://scholar.google.com/citations?view_op=view_citation&hl=en&citation_for_view=" + scholar) + " citations)</a></p><br /><p>" + description + "</p></div>"
def display_other(title,address,description):
	return "<div class="box col2"><h3><a href="" + escape(address) + "">" + title + "</a></h3>" + description + "</div>"
def pull_citations(address):
		website = urllib2.urlopen(address)
		website_html = website.read()
		citations = sre.findall('Cited by [0-9]*', website_html)
		try: return citations[0].rsplit(' ',1)[1]
		except IndexError, e:
			return "0"
	except urllib2.HTTPError, e:
		return "Cannot retrieve URL: HTTP Error Code", e.code
	except urllib2.URLError, e:
		return "Cannot retrieve URL: " + e.reason[1]
def pull_indices(position):
		website = urllib2.urlopen("http://scholar.google.com/citations?user=CyuQ1RUAAAAJ&hl=en")
		website_html = website.read()
		citations = sre.findall('<td class="cit-borderleft cit-data">[0-9]*</td>', website_html)
		return citations[position].split("<")[1].split(">")[1]
	except urllib2.HTTPError, e:
		return "Cannot retrieve URL: HTTP Error Code", e.code
	except urllib2.URLError, e:
		return "Cannot retrieve URL: " + e.reason[1]
def display_footer():
	return ''.join(["""
		<div class="footer">Copyright jph.am 2014 // email me at me at jphoward&#64;doctors&#46;org&#46;uk // uptime: """,uptime(),"""
def uptime():
	with open('/proc/uptime', 'r') as f:
		uptime_seconds = float(f.readline().split()[0])
		uptime_string = str(timedelta(seconds = uptime_seconds)).split(",")[0]

def google_analytics():
	return """
		(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
		ga('create', 'UA-32353852-1', 'jamesphoward.com');
		ga('send', 'pageview');