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.


#!/usr/bin/python2.7

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>
			<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 """
			</div>"""
		
	yield display_footer()
	
def display_http_header():
	return """
	<!DOCTYPE html>
	<html>
	<head>
		<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"/>
	</head>
	<body>"""

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>
		<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):
	try:
		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):
	try:
		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>
		<div class="footer">Copyright jph.am 2014 // email me at me at jphoward&#64;doctors&#46;org&#46;uk // uptime: """,uptime(),"""
		</div>
	</div>
	</body>
	</html>
	"""])
	
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]
	return(uptime_string)

def google_analytics():
	return """
	<script>
		(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
		(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
		m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
		})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
		ga('create', 'UA-32353852-1', 'jamesphoward.com');
		ga('send', 'pageview');
	</script>"""
		
WSGIServer(app).run()