<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>medicalnerds.com</title>
	<atom:link href="http://www.medicalnerds.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.medicalnerds.com</link>
	<description>technology, stats and IT for medics</description>
	<pubDate>Sat, 12 Jun 2010 19:40:20 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.5</generator>
	<language>en</language>
			<item>
		<title>Batch converting images using imagemagick</title>
		<link>http://www.medicalnerds.com/batch-converting-images-using-imagemagick/</link>
		<comments>http://www.medicalnerds.com/batch-converting-images-using-imagemagick/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 19:37:42 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=152</guid>
		<description><![CDATA[A quick update to my previous post Batch converting PDF to JPG/JPEG using free software about converting multiple files.
Instead of using convert, one can use the command mogrify:


mogrify -format jpg *.gif


These commands are from the fantastic suite of software known as ImageMagick.
I&#8217;m using this to convert the fantastic icons from famfamfam to gif as IE6 [...]]]></description>
			<content:encoded><![CDATA[<p>A quick update to my previous post <a href="http://www.medicalnerds.com/batch-converting-pdf-to-jpgjpeg-using-free-software/">Batch converting PDF to JPG/JPEG using free software</a> about converting multiple files.<span id="more-152"></span></p>
<p>Instead of using <code>convert</code>, one can use the command <code>mogrify</code>:</p>
<pre>
<code>
mogrify -format jpg *.gif
</code>
</pre>
<p>These commands are from the fantastic suite of software known as <a href="http://www.imagemagick.org/script/index.php">ImageMagick</a>.</p>
<p>I&#8217;m using this to convert the fantastic icons from <a href="http://www.famfamfam.com/lab/icons/">famfamfam</a> to gif as IE6 (running as the browser of choice on NHS computers - my target browser sadly) has problems with PNG format graphics. This is for my all singing all dancing WebObjects based medical research / patient record online system that is being deployed this month for the first time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/batch-converting-images-using-imagemagick/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Apache Lucene</title>
		<link>http://www.medicalnerds.com/apache-lucene/</link>
		<comments>http://www.medicalnerds.com/apache-lucene/#comments</comments>
		<pubDate>Tue, 25 May 2010 22:39:02 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Medical]]></category>

		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=149</guid>
		<description><![CDATA[A short post. Apache Lucene is amazing - I was faced with slow full text searches searching >1.6 million SNOMED CT descriptions using PostgreSQL&#8217;s built in full-text search. Apache Lucene performs these searches in microseconds - I rapidly turn the list of concept Ids into full enterprise objects and my work is done!
Please check out [...]]]></description>
			<content:encoded><![CDATA[<p>A short post. <a href="http://lucene.apache.org/java/docs/">Apache Lucene</a> is amazing - I was faced with slow full text searches searching >1.6 million SNOMED CT descriptions using PostgreSQL&#8217;s built in full-text search. Apache Lucene performs these searches in microseconds - I rapidly turn the list of concept Ids into full enterprise objects and my work is done!</p>
<p>Please check out Apache Lucene&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/apache-lucene/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Invaders Internet explorer 6 must die</title>
		<link>http://www.medicalnerds.com/invadersinternet-explorer-6-must-die/</link>
		<comments>http://www.medicalnerds.com/invadersinternet-explorer-6-must-die/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 22:13:15 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=145</guid>
		<description><![CDATA[
Repeat after me:


while (1) {
   System.out.println("Internet explorer 6 must die");
}


Why is internet explorer so ubiquitous across all NHS organisations?


I&#8217;m currently fighting CSS, javascript and graphics transparency problems&#8230;. ARRRRGHHHHHHH!
]]></description>
			<content:encoded><![CDATA[<p>
Repeat after me:
</p>
<p><code><br />
while (1) {<br />
   System.out.println("Internet explorer 6 must die");<br />
}<br />
</code></p>
<p>
Why is internet explorer so ubiquitous across all NHS organisations?
</p>
<p>
I&#8217;m currently fighting CSS, javascript and graphics transparency problems&#8230;. ARRRRGHHHHHHH!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/invadersinternet-explorer-6-must-die/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Finding rows in one table not present in another table with PostgreSQL</title>
		<link>http://www.medicalnerds.com/finding-rows-in-one-table-not-present-in-another-table-with-postgresql/</link>
		<comments>http://www.medicalnerds.com/finding-rows-in-one-table-not-present-in-another-table-with-postgresql/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 21:32:57 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=139</guid>
		<description><![CDATA[In implementing a comprehensive SNOMED CT browser as part of a research clinical information system, I cache the results of several processor and disk-intensive queries to speed up lookup and SNOMED CT navigation. I was finding some odd results and found that my caching was missing for several items. I needed a way of comparing [...]]]></description>
			<content:encoded><![CDATA[<p>In implementing a comprehensive SNOMED CT browser as part of a research clinical information system, I cache the results of several processor and disk-intensive queries to speed up lookup and SNOMED CT navigation. I was finding some odd results and found that my caching was missing for several items. I needed a way of comparing the contents of one table with another in PostgreSQL and finding out which rows were not present. <span id="more-139"></span></p>
<p>To do this, PostgreSQL supports set operations. For instance, I have two tables:</p>
<pre><code>
rsdb=# \d t_concept
                                      Table "public.t_concept"
        Column        |          Type          |                      Modifiers
----------------------+------------------------+-----------------------------------------------------
 concept_id           | bigint                 | not null default nextval('t_concept_seq'::regclass)
 concept_status_code  | integer                | not null
 ctv_id               | character varying(10)  | not null
 fully_specified_name | character varying(255) | not null
 is_primitive         | integer                | not null
 snomed_id            | character varying(10)  | not null

</code></pre>
<pre><code>
rsdb=# \d t_cached_parent_concepts
Table "public.t_cached_parent_concepts"
      Column       |  Type  | Modifiers
-------------------+--------+-----------
 child_concept_id  | bigint | not null
 parent_concept_id | bigint | not null
</code></pre>
<p>I want to identify rows in <code>t_concept</code> without a corresponding row in <code>t_cached_parent_concepts</code> using SQL:</p>
<p>Try this!</p>
<pre><code>
select concept_id from t_concept except select child_concept_id from t_cached_parent_concepts;
</code></pre>
<p>Now this doesn&#8217;t explain why my sophisticated caching system is not so sophisticated&#8230;..</p>
<pre><code>
rsdb=# select count(*) from t_concept;
 count
--------
 388289
(1 row)

rsdb=# select count(*) from (select concept_id from t_concept except select child_concept_id from t_cached_parent_concepts) as tmp;
 count
--------
 142960
(1 row)

</code></pre>
<p>Hmm.. that&#8217;s a lot of concepts without a cache&#8230;.</p>
<p> </p>
<h2>Update 8th March 2010</h2>
<pre><code>
rsdb=# select count(*) from t_concept;
 count
--------
 2
(1 row)

</code></pre>
<p>Now that&#8217;s better. But why isn&#8217;t there only a single root node with no parent concepts? Further investigation identifies a UK-only SNOMED term that hasn&#8217;t been classified correctly. A bug report will be filed with Connecting for Health!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/finding-rows-in-one-table-not-present-in-another-table-with-postgresql/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Executing raw SQL with WebObjects and Project Wonder</title>
		<link>http://www.medicalnerds.com/executing-raw-sql-with-webobjects-and-project-wonder/</link>
		<comments>http://www.medicalnerds.com/executing-raw-sql-with-webobjects-and-project-wonder/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 13:07:20 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=136</guid>
		<description><![CDATA[WebObjects is an extraordinarily powerful java based web-application server. On occasions, I need to execute arbitrary SQL against the underlying database. This is not necessary for most uses, but for certain batch operations it is useful.
I&#8217;m currently writing an introduction to WebObjects and I hope to post these introductory documents both here and to the [...]]]></description>
			<content:encoded><![CDATA[<p>WebObjects is an extraordinarily powerful java based web-application server. On occasions, I need to execute arbitrary SQL against the underlying database. This is not necessary for most uses, but for certain batch operations it is useful.<span id="more-136"></span></p>
<p>I&#8217;m currently writing an introduction to WebObjects and I hope to post these introductory documents both here and to the <a href="http://wiki.objectstyle.org/confluence/display/WO/Home">WebObjects wiki</a></p>
<p>To execute arbitrary SQL without getting any results back (e.g. executing non-Select SQL statements) use <a href="http://webobjects.mdimension.com/hudson/job/Wonder53/javadoc/er/extensions/eof/ERXEOAccessUtilities.html#evaluateSQLWithEntity(com.webobjects.eocontrol.EOEditingContext,%20com.webobjects.eoaccess.EOEntity,%20java.lang.String)">ERXEOAccessUtilities.evaluateRawSqlForEntity()</a></p>
<p>For example:</p>
<pre>
<code>
	protected static void deleteCache() {
		ERXEOAccessUtilities.evaluateSQLWithEntityNamed(ERXEC.newEditingContext(), "CachedParentConcepts", "truncate t_cached_parent_concepts;");
	}
</code>
</pre>
<p>Deletes all the rows in the table <code>t_cached_parent_concepts</code></p>
<p>If you wish to get the results back from a custom SQL query and convert the raw rows into enterprise objects, use EOUtilities.rawRowsForSQL</p>
<p>For example:</p>
<pre>
<code>
	/**
	 * Helper function to execute raw SQL and convert the results to enterprise objects
	 * @param ec
	 * @param entityName
	 * @param sql
	 * @param columns
	 * @return
	 */
	public static NSArray<? extends EOEnterpriseObject> executeRawSqlToEO(EOEditingContext ec, String entityName, String sql, NSArray<String> columns) {
		NSArray<EOGlobalID> gids = executeRawSql(ec, entityName, sql, columns);
		return ERXEOGlobalIDUtilities.fetchObjectsWithGlobalIDs(ec, gids);
	}

	/**
	 * Executes a raw SQL statement returning an array of EOGlobalIDs.
	 * The raw SQL should return sufficient columns to allow the raw row to be converted into an
	 * enterprise object.
	 * You will usually need to convert column names to attribute names to allow the raw rows
	 * to be converted properly.
	 *
	 * @param ec - editing context
	 * @param entityName - name of the entity that the raw rows will be converted to
	 * @param sql - the raw SQL statement to be executed
	 * @param columns - array of attribute names to replace the column names that will arrive from the database
	 * @return
	 */
	public static NSArray<EOGlobalID> executeRawSql(EOEditingContext ec, String entityName, String sql, NSArray<String> columns) {
		NSMutableArray<EOGlobalID> gids = new NSMutableArray<EOGlobalID>();
		EOModelGroup modelGroup = ERXEOAccessUtilities.modelGroup(ec);
		EOEntity entity = modelGroup.entityNamed(entityName);
		String modelName = entity.model().name();
		NSArray<NSDictionary<?,?>> rawRows = EOUtilities.rawRowsForSQL(ec, modelName, sql, columns);
		for(NSDictionary<?,?> row : rawRows) {
			EOGlobalID gid = entity.globalIDForRow(row);
			if (gid==null) throw new NullPointerException("Could not fetch global ID for raw row: " + row);
			gids.add(gid);
		}
		return gids;
	}

</code>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/executing-raw-sql-with-webobjects-and-project-wonder/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Recursive SQL with PostgreSQL 8.4</title>
		<link>http://www.medicalnerds.com/recursive-sql-with-postgresql-84/</link>
		<comments>http://www.medicalnerds.com/recursive-sql-with-postgresql-84/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 21:02:32 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Medical]]></category>

		<category><![CDATA[PostgreSQL]]></category>

		<category><![CDATA[SNOMED CT]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=103</guid>
		<description><![CDATA[Representing hierarchical data in a relational database is easy. For instance, modelling the contents of a filesystem with directories and subdirectories is straightforward using self-joins on a parent key. The root node(s) are represented as those without a parent. Such a model is useful for modelling other types of data - in particular, hierarchies in [...]]]></description>
			<content:encoded><![CDATA[<p>Representing hierarchical data in a relational database is easy. For instance, modelling the contents of a filesystem with directories and subdirectories is straightforward using self-joins on a parent key. The root node(s) are represented as those without a parent. Such a model is useful for modelling other types of data - in particular, hierarchies in which nodes can have multiple parents - for example, SNOMED CT is a hierarchical clinical terminology - the &#8220;Systematised Nomenclature of Medicine Clinical Terms&#8221;. The <a href="http://www.connectingforhealth.nhs.uk/systemsandservices/data/snomed">Connecting for Health</a> website suggests this terminology is in widespread use by &#8220;all computers&#8221; in the NHS (website accessed 4th March 2010) but as those of us who work in the NHS will testify, this is not the case. <span id="more-103"></span></p>
<p>Those who work in the NHS will be more familiar with <a href="http://www.connectingforhealth.nhs.uk/systemsandservices/data/readcodes/faqs">Read</a> codes. These are primarily used in primary care information systems. The origins of terminology systems worldwide is a subject for another article, but Read codes are limited to a fixed hierarchy. Such a hierarchy results in duplicate terms as semantically some terms may be logically related to different terms in the hierarchy.</p>
<p>The structure of SNOMED CT is complex and again, beyond the scope of this article. Those who download the distribution will find a large number of explanatory technical and implementation guidelines. There are essentially three tables representing a Concept, a Description and a Relationship. There is a one to many relationship between Concept and Description - as such, one concept can have multiple descriptions. There is also a more complex relationship between Concept and Relationship with a relationship defined as a join table between related concepts. Each relationship links a &#8220;source concept&#8221; to a &#8220;target concept&#8221; and as such has an implicit direction - from parent to child. A relationship can have different types - themselves represented as a concept - the most commonly used concept reflects a &#8220;IS A&#8221; type of relationship. Thus, each Relationship has three Concept foreign keys - &#8220;source Concept&#8221;, &#8220;target Concept&#8221; and &#8220;type Concept&#8221;.</p>
<p>The greatest difficulty in implementing SNOMED CT in an application is its sheer size. I debated using only a small (manually managed) subset but instead decided to include all SNOMED CT terms available - including those in designated UK-specific subpacks such as that provided to document pharmaceutical products available in the UK. As such, careful optimisation of full-text searches and other queries is essential, with applications decided which subsets to use.</p>
<p>My web-based application supports automatic updating from multiple SNOMED CT distributions and as such grows very large. Even with only the core SNOMED CT distribution there are 388,289 concepts, 1,149,406 descriptions and 1,387,930 relationships.</p>
<p>How does this relate to the use of recursive SQL in PostgreSQL? My naive approach to implementing SNOMED CT was to iterate manually through an object graph of SNOMED CT as provided by a sophisticated object-relational mapping (ORM) - in this case the <a href="http://wiki.objectstyle.org/confluence/display/WO/EOF-Overview">Enterprise Object Framework (EOF)</a> from <a href="http://wiki.objectstyle.org/confluence/display/WO/Home">WebObjects</a>. This works well for many use cases, but iterating recursively to find all child or parent concepts uses memory and processor time. There are not many use cases when you need to do this - certainly fetching all child concepts of a high-level SNOMED CT concept even as raw SQL is inappropriate. However, there <em>is</em> a need to find all parent concepts of a particular concept to understand its position in a semantic sense. For instance, understanding algorithmically than &#8220;Friedreich&#8217;s ataxia&#8221; is a &#8220;Degenerative disease&#8221;.</p>
<p>It certainly is possible to generate a cache of all parent concepts and keep this up to date which can sometimes be required if you clearly demonstrate that this is the rate-limiting step using profiling. However, I try to avoid early optimisation and as such, use recursive SQL to rapidly identify all parent concepts.</p>
<p><a href="http://www.storytotell.org/blog/2009/08/11/postgresql84-recursive-queries.html">Recursive queries</a> appeared in PostgreSQL only with the release of version 8.4. The documentation is <a href="http://www.postgresql.org/docs/8.4/static/queries-with.html">here</a>.</p>
<p>Here is my table structure:</p>
<pre>
<code>
rsdb=# \d t_concept
Table "public.t_concept"
Column        |          Type          |                      Modifiers
----------------------+------------------------+-----------------------------------------------------
concept_id           | bigint                 | not null default nextval('t_concept_seq'::regclass)
concept_status_code  | integer                | not null
ctv_id               | character varying(10)  | not null
fully_specified_name | character varying(255) | not null
is_primitive         | integer                | not null
snomed_id            | character varying(10)  | not null
</code>
</pre>
<pre>
<code>
rsdb=# \d t_description
Table "public.t_description"
Column          |          Type          |                        Modifiers
-------------------------+------------------------+---------------------------------------------------------
concept_id              | bigint                 | not null
description_id          | bigint                 | not null default nextval('t_description_seq'::regclass)
description_status_code | integer                | not null
description_type_code   | integer                | not null
initial_capital_status  | character varying(10)  | not null
language_code           | character varying(10)  | not null
term                    | character varying(255) | not null
</code>
</pre>
<pre>
<code>
rsdb=# \d t_relationship
Table "public.t_relationship"
Column            |         Type          |                        Modifiers
------------------------------+-----------------------+----------------------------------------------------------
characteristic_type          | integer               | not null
refinability                 | integer               | not null
relationship_group           | character varying(10) | not null
relationship_id              | bigint                | not null default nextval('t_relationship_seq'::regclass)
relationship_type_concept_id | bigint                | not null
source_concept_id            | bigint                | not null
target_concept_id            | bigint                | not null
</code>
</pre>
<p>And this is the SQL to fetch the concept_id of all parent concepts of the concept Friedreich&#8217;s ataxia (concept ID 10394003).</p>
<pre>
<code>
-- SHOW ALL PARENT CONCEPTS FOR FRIEDREICH'S ATAXIA (10394003)
with recursive parent_concepts(concept_id) as (
select t0.concept_id from t_concept t0 inner join t_relationship t1 on t0.concept_id = t1.target_concept_id
where (t1.relationship_type_concept_id = 116680003 and t1.source_concept_id = 10394003)
union all
select t0.concept_id from t_concept t0,t_relationship t1, parent_concepts pc where t0.concept_id = t1.target_concept_id and
t1.source_concept_id = pc.concept_id and t1.relationship_type_concept_id = 116680003
)
select distinct(concept_id) from parent_concepts;
</code>
</pre>
<p>You might ask, why am I limiting the parent concepts to those linked by relationships with the concept type &#8220;116680003&#8243;? This is because that reflects the <code>IS A</code> relationship type concept.</p>
<p>A quick hack to get the fully specified names of the concepts&#8230;</p>
<pre>
<code>
rsdb=# select fully_specified_name from t_concept, (with recursive parent_concepts(concept_id) as (
rsdb(# select t0.concept_id from t_concept t0 inner join t_relationship t1 on t0.concept_id = t1.target_concept_id
rsdb(# where (t1.relationship_type_concept_id = 116680003 and t1.source_concept_id = 10394003)
rsdb(# union all
rsdb(# select t0.concept_id from t_concept t0,t_relationship t1, parent_concepts pc where t0.concept_id = t1.target_concept_id and
rsdb(# t1.source_concept_id = pc.concept_id and t1.relationship_type_concept_id = 116680003
rsdb(# )
rsdb(# select distinct(concept_id) from parent_concepts) as temp where t_concept.concept_id = temp.concept_id;
</code>
</pre>
<p>gives these results:</p>
<pre>
<code>
                    fully_specified_name
---------------------------------------------------------------
 Disorder of head (disorder)
 Clinical finding (finding)
 Cerebellar disorder (disorder)
 Disorder of body system (disorder)
 SNOMED CT Concept (SNOMED RT+CTV3)
 Spinal cord disorder (disorder)
 Disorder of nervous system (disorder)
 Disorder of back (disorder)
 Encephalomyelopathy (disorder)
 Head finding (finding)
 Degenerative disorder (disorder)
 Disorder of body cavity (disorder)
 Disease (disorder)
 Disorder of spine (disorder)
 Finding of back (finding)
 Finding of head and neck region (finding)
 Finding by site (finding)
 Disorder of spinal region (disorder)
 Disorder of the central nervous system (disorder)
 Degenerative disease of the central nervous system (disorder)
 Spinocerebellar disease (disorder)
 Finding of body region (finding)
 Degenerative brain disorder (disorder)
 Disorder by body site (disorder)
 Finding of spinal region (finding)
 Disorder of brain (disorder)
</code>
</pre>
<p>Note: I am not limiting concepts by whether they are &#8220;active&#8221; or not, as this is something I switch on and off at the application level.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/recursive-sql-with-postgresql-84/feed/</wfw:commentRss>
		</item>
		<item>
		<title>More posts</title>
		<link>http://www.medicalnerds.com/more-posts/</link>
		<comments>http://www.medicalnerds.com/more-posts/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 21:01:21 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Medical]]></category>

		<category><![CDATA[Research]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=114</guid>
		<description><![CDATA[After a long hiatus while we both finish our theses (one of us [1] more successfully than the other) and obtain substantive posts (one of us [2] more successfully than the other), we are keen to restart regular nerdy medical technology posts.
Welcome back!
(1) Completed his MD in 2008
(2) This is not necessarily the same person
]]></description>
			<content:encoded><![CDATA[<p>After a long hiatus while we both finish our theses (one of us [1] more successfully than the other) and obtain substantive posts (one of us [2] more successfully than the other), we are keen to restart regular nerdy medical technology posts.</p>
<p>Welcome back!</p>
<hr />(1) Completed his MD in 2008<br />
(2) This is not necessarily the same person</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/more-posts/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Encrypting a USB Key using TrueCrypt</title>
		<link>http://www.medicalnerds.com/encrypting-a-usb-key-using-truecrypt/</link>
		<comments>http://www.medicalnerds.com/encrypting-a-usb-key-using-truecrypt/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 16:04:13 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[Free]]></category>

		<category><![CDATA[Medical]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Software]]></category>

		<category><![CDATA[Encryption]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=86</guid>
		<description><![CDATA[If you are a healthcare professional you have a duty to maintain the security of patient identifiable data. Within your job you sometimes need to use a USB key to transfer lists or letters between computers. If you lose your un-encrypted USB key with patient identifiable data then it may deemed negligent and you may [...]]]></description>
			<content:encoded><![CDATA[<p><img title="TrueCrypt Logo" src="/wp-content/images/tclogo.png" alt="" width="65" height="80" align="right" />If you are a healthcare professional you have a duty to maintain the security of patient identifiable data. Within your job you sometimes need to use a USB key to transfer lists or letters between computers. If you lose your un-encrypted USB key with patient identifiable data then it may deemed negligent and you may face disciplinary action. In this how-to I will talk through how to setup an easy to use secure software encryption scheme for a USB stick/key for use with Windows.<span id="more-86"></span></p>
<p><strong>The Problem</strong></p>
<p>You need to take care of PID (patient identifiable data) but you don&#8217;t have the time to learn the ins and outs of encryption schemata. Even if you use your USB key to transfer the data and then delete it, if you were to lose the key and it fell into unscrupulous hands it possible that someone could read even the <em>deleted </em>files.</p>
<p><strong>The Solution</strong></p>
<p>TrueCrypt is an open source, free application that allows you to use tried-and-tested <a href="http://www.connectingforhealth.nhs.uk/systemsandservices/infogov/security/encryption.pdf" target="_blank">NHS approved</a> encryption methods. It can be set up to automatically load when you plug the USB key into the PC.</p>
<p><strong>How Does it work?</strong></p>
<p><img title="TrueCrypt Diagram" src="/wp-content/images/tcdiagram.png" alt="" width="265" height="199" align="right" />When you plug a USB stick into a PC it usually <em>mounts</em> the drive as a drive letter (F in this example).  When TrueCrypt is running and you have entered your password you will be greeted by a second drive letter, this is the encrypted one. The files on this new drive will only be decrypted and visible to you once you have typed in your password. Existing files on your USB key will <strong>not</strong> encrypted, only ones added to the new drive letter. You have to store the encrypted files in a container I have called &#8217;secretfile&#8217;, but you could call it anything you wish. If someone found your USB key the encrypted data will all be enclosed safely within your file container &#8217;secretfile&#8217;  which someone could see exists but they would not be able to view the actual contents of the file without obtaining your password.</p>
<p><strong>The How-to</strong></p>
<p>1. Download the newest version of TrueCrypt from <a href="http://www.truecrypt.org/downloads.php" target="_blank">here</a>.</p>
<p>3. Double-click on the downloaded file and it will run. You will be warned that the file has come from the internet, this is OK.</p>
<p>4. Accept the default terms and conditions and then select <strong>extract </strong>rather than install. You do not want to install the program on your computer as this would probably be in breach of your local IT guidelines.</p>
<p>5. Extract the files to your desktop, leave the box ticked that allows you to open the folder once extracted.</p>
<p>6. This new folder will pop-up. Plug your USB key in and note what drive it comes up as. (eg F:)</p>
<p>6. Run the program called &#8220;TrueCryptFormat.exe&#8221; by double-clicking on it.</p>
<p>7. Select &#8220;Create File Container&#8221;, then &#8220;Standard TrueCrypt Volume&#8221;</p>
<p>8. Where it says Volume Location, enter &#8220;F:secretfile&#8221; (substituting the drive letter of your USB key if it is not F.) This is the container in which your encrypted files will be stored.</p>
<p>9. Keep the standard options on the next screen, that of AES and RIPEMD-160.</p>
<p>10. You need to tell the program the size of the encrypted drive you want to create. The container produced will use up that amount of space, so if for instance you created a 100MB encrypted drive, this would take up 100MB of un-encrypted space on your USB key, even if<em> </em>the encrypted area was &#8216;empty&#8217;. You may wish to leave room for un-encrypted data. The amount of free space should be displayed to help guide you.</p>
<p>11. Next enter your password, the <em>strength</em> of your password is critical, see below for details on this.</p>
<p>12. Click next and your encrypted drive should now be created, this may take a few minutes depending on the size of your key and speed of your computer.</p>
<p>13. Once complete close the window.</p>
<p>14. Now open the file called &#8220;TrueCrypt.exe&#8221;, go to the &#8220;Tools&#8221; option on the menu, then &#8220;Traveller Disk Setup&#8221;.</p>
<p>15. Under file settings specify the location F:\truecrypt, (changing the drive letter F to whatever the current drive letter is for your USB key). Where it asks for autorun configuration select &#8220;Auto-mount&#8221;. In the box where it says &#8220;file to mount&#8221; enter secretfile .<img class="alignnone" title="TrueCrypt Setup How-to" src="/wp-content/images/tcTravellerDiskSetup.PNG" alt="" width="455" height="462" /></p>
<p>16. Click create, when done, close all windows that you have opened and remove the USB key.</p>
<p><strong>How to use</strong></p>
<p>1. Insert USB key. You should get the following popup, select &#8220;Mount Truecrypt Volume&#8221; and then enter your password at the next prompt. A window should pop up with a new drive letter but there will be no files, yet.</p>
<p><img class="alignnone" title="TrueCrypt Password Prompt" src="/wp-content/images/tcPassword.png" alt="" width="427" height="135" /></p>
<p>2. To copy files to the new encrypted area just drag and drop as if it was a USB key.</p>
<p>3. To remove the USB key first <em>dismount</em> the key by clicking on the TrueCrypt logo on the right hand side of the status bar and select &#8220;Dismount all devices&#8221;</p>
<p><strong>What is Encryption?</strong></p>
<p>When you use your password to get into a website it is used to compare it with a list of usernames and paswords to confirm your identity and let you in, that means if you lose your password your supervisor can look it up and remind you of it.</p>
<p>Encryption is different. Think of encryption as your data being scrambled using your password, and not even your supervisor or boss can access it. This means if you lose your password then you can&#8217;t get your data back.</p>
<p><strong>How secure is AES-256 Encryption?</strong></p>
<p>It is secure&#8230; secure enough for the US government for use with  &#8220;Top Secret&#8221; information. Your encryption, however,  is only as strong as your password.</p>
<p><strong>Password Strength</strong></p>
<p>The easiest way to &#8220;crack&#8221; or hack your encrypted USB key would be to try common passwords or run through the dictionary. The longer and more complicated your password, or <em>pass phrase</em> the safer your data. Try using a password with at least 8 letters, use upper and lower case and numbers. Use more than one word or use a combination of your favourite non-English language words. This is an example of a strong password. &#8220;Love&#8221;, &#8220;Password&#8221;, &#8220;Arsenal&#8221;  or your name are all examples of <em>weak</em> passwords.</p>
<p>eg Ouvert1971NerdBoy</p>
<p><strong>Potential Problems</strong></p>
<p>Your local IT department may not allow you to use programmes that run off the USB key because you may not be running as an &#8220;administrator&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/encrypting-a-usb-key-using-truecrypt/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How to encrypt ZIP files securely using 7Zip</title>
		<link>http://www.medicalnerds.com/how-to-encrypt-zip-files-securely-using-7zip/</link>
		<comments>http://www.medicalnerds.com/how-to-encrypt-zip-files-securely-using-7zip/#comments</comments>
		<pubDate>Sat, 18 Oct 2008 17:48:14 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[Free]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=65</guid>
		<description><![CDATA[Windows has had built in zip file support with encryption since Windows XP, unfortunately the quality of this encryption is poor as evidenced by the number of commercial programmes available to crack it. Winzip, WinRAR are trialware commercial programs that offer secure AES encryption to your compressed files but cost between 23 and 30 Euros [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/images/7ziplogo.png" border="0" alt="" width="110" height="63" align="right" />Windows has had built in zip file support with encryption since Windows XP, unfortunately the quality of this encryption is poor as evidenced by the number of commercial programmes available to crack it. Winzip, WinRAR are trialware commercial programs that offer secure AES encryption to your compressed files but cost between 23 and 30 Euros per user. 7-Zip is an open-source, free utility that offers AES-256bit encryption. In this how-to I will show you how to install and produce 256-bit encryption of your compressed files.<span id="more-65"></span></p>
<p><strong>A short introduction to Encryption</strong></p>
<p style="text-align: left;">Encryption is a way of scrambling the data within your files to prevent a third party eavesdropping. Encryption can be <em>symmetric</em>, where the same password is used for encrypting and decrypting the data. <em>Asymmetric</em> encryption is the method using the concept of <a rel="nofollow" href="http://en.wikipedia.org/wiki/Public-key_cryptography" target="_blank">public and private keys</a> eliminating the need to transfer a password between the 2 parties.</p>
<p><strong>Encryption within Windows</strong></p>
<p>Windows supports the use of ZIP or <a rel="nofollow" href="http://support.microsoft.com/kb/306531" target="_blank">compressed folders</a>, however it is hampered by the use of <a href="http://archive.cert.uni-stuttgart.de/vuln-dev/2003/02/msg00019.html" target="_blank">weak encryption,</a> that can be brute-forced using a myriad of programs in minutes to hours with a modern PC. <a href="http://www.winzip.com/index.htm">Winzip</a>, <a rel="nofollow" href="http://www.rarlab.com/" target="_blank">WinRAR</a>, 7-Zip and others offer the more secure <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank">AES</a> standard. AES, like any encryption scheme, can be broken given time, but this is likely to run into hundreds if not thousands of years.</p>
<p><strong>Installing 7-Zip</strong></p>
<p>1. Download the most modern non-beta version from <a href="http://www.7-zip.org/" target="_blank">here</a>.</p>
<p>2. Install using default options.</p>
<p><strong>Using Z-Zip</strong></p>
<p>As default 7-Zip installs itself to with &#8220;explorer extensions&#8221; that allow you to right click on items on the desktop or in windows explorer to compress files. Z-Zip has its own file format 7z which is more efficient at compressing files than the standard zip extension, but this will mean the person you are sending the file to will also have to use 7zip. Using the zip format will enable people using other programs to de-compress the file.</p>
<p>1. Right click on the files or folder you wish to compress and encrypt.</p>
<p><img src="/wp-content/images/private.jpg" alt="" width="395" height="190" align="middle" /></p>
<p>2.Firstly change the Archive format to Zip (or use 7z if both you and your intended recipient use 7zip), then change the encryption method to the robust AES-256, thirdly enter your password. Then click OK. The rest of the options can be left as default.</p>
<p><img src="/wp-content/images/7zsettings.jpg" alt="" width="626" height="541" /></p>
<p><strong>Decryption</strong></p>
<p>Simply right-click on the file, select extract then enter the password when requested.</p>
<p><strong>Important Notes</strong></p>
<p>Your data will still be vulnerable to a &#8220;<a href="http://en.wikipedia.org/wiki/Dictionary_attack" target="_blank">dictionary attack</a>&#8221; where an attacker cycles through common passwords such as &#8220;Love&#8221;, &#8220;Password&#8221; etc. To protect from this simply make your password a mixture of numbers and letters rather than simply a single English word. One way to protect from this would be to use a <a href="https://www.grc.com/passwords.htm" target="_blank">random generated password</a> or use asymmetric encryption.<strong> </strong></p>
<p>For a comparison of software for compressing files see <a href="http://en.wikipedia.org/wiki/Comparison_of_file_archivers" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/how-to-encrypt-zip-files-securely-using-7zip/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Filling in PDF Forms with Foxit PDF Reader</title>
		<link>http://www.medicalnerds.com/filling-in-pdf-forms-with-foxit-pdf-reader/</link>
		<comments>http://www.medicalnerds.com/filling-in-pdf-forms-with-foxit-pdf-reader/#comments</comments>
		<pubDate>Sat, 16 Aug 2008 21:49:37 +0000</pubDate>
		<dc:creator>James</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.medicalnerds.com/?p=49</guid>
		<description><![CDATA[Foxit PDF Reader is a free closed source alternative to Adobe&#8217;s PDF reader. On older machines it feels snappier than using Adobe&#8217;s bloated product. In this short how-to I will show you how to fill in forms using Foxit Reader with the 39 US$ Pro-Pack.
The technique I will describe can be used to create professional [...]]]></description>
			<content:encoded><![CDATA[<p><img class="right" style="border: 0pt none; margin: 0px;" title="Foxit Reader " src="/wp-content/images/foxitlogo.jpg" alt="" width="153" height="173" />Foxit PDF Reader is a free closed source alternative to Adobe&#8217;s PDF reader. On older machines it feels snappier than using Adobe&#8217;s bloated product. In this short how-to I will show you how to fill in forms using Foxit Reader with the 39 US$ Pro-Pack.<span id="more-49"></span></p>
<p>The technique I will describe can be used to create professional looking job application forms whether the form is printed or in PDF format.</p>
<p>Adobe Acrobat (not Acrobat-Reader) is the professional product that allows you to edit/fill in forms from Adobe, it currently retails at around 270US$.</p>
<p>Foxit Reader is free to download and use and relatively lightweight at 2.3MB download compared to 33.5MB download with Acrobat Reader. Foxit produce a PDF Editor which allows editing text and images within PDF files, but to fill in forms you only really need the &#8220;Plus pack&#8221; which is currently 39 US$. You can use all Foxit versions in evaluation mode on a trial basis but this will leave a watermark on your form.</p>
<p><strong>Create PDF from Printed Form</strong></p>
<p>1. In Windows XP the required software is PDFCreator, details of which can be found <a href="http://www.medicalnerds.com/the-killer-free-applications-for-the-medical-research-student-windows-part-1/" target="_blank">here</a>. This is only needed if you have a paper form, my technique is to scan in the pages in 300dpi format. Then select the pages in the correct order and right click to &#8220;Print using Photo Printing Wizard.&#8221; Select PDF Creator as the printer and you will have the required pages as a PDF file.</p>
<p>2. When you have Foxit Reader installed click<br />
<code><br />
Tools&gt;&gt;Typewriter&gt;&gt;Typewriter</code></p>
<p>This will allow you to type directly onto the form. The advantages of this method over using a image editor and typing over the jpeg scan is that Foxit will allow you to save the form and come back and edit the text at a later date as well as offering a spell checker.</p>
<p><img class="alignright" title="Foxit" src="/wp-content/images/foxit.png" alt="" width="480" height="336" /></p>
<p><strong></strong></p>
<p><strong>Problems with Foxit and Typewriter: Landscape Forms<br />
</strong></p>
<p>There is an annoying bug in Foxit,Â  acknowledged <a href="https://www.foxitsoftware.com/bbs/showthread.php?p=17184" target="_blank">here</a> and <a href="http://www.foxitsoftware.com/bbs/showthread.php?p=19055" target="_blank">here</a> but not fixed by the software house. When you try and use the typewriter in a landscape document the text comes out 90 degrees out.</p>
<p>This makes filling all those landscape forms impossible without resorting to Acrobat Professional.</p>
<p><strong></strong></p>
<p><strong>The Hack</strong></p>
<ol>
<li>Select Print from the File Menu in Foxit.</li>
<li>Select PDFCreator as your Printer</li>
<li>Click on Properties</li>
<li>Then Advanced</li>
<li>Select Papersize &#8220;Postscript Custom&#8221;</li>
<li>Select Edit Custom Paper Size</li>
<li>Assuming you are using A4 paper enter 297 * 210mm</li>
<li>Change paper feed to &#8220;Short Edge First&#8221;</li>
<li>Print to PDF.</li>
</ol>
<p>You should now have an identical looking PDF but the typewriter will work correctly. If the typewriter function is still 90 degrees out then change paper feed to &#8220;Long Edge first&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.medicalnerds.com/filling-in-pdf-forms-with-foxit-pdf-reader/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
