Skip to main content

A python and MongoDB-based Matchmaker Exchange server

Project description

patientMatcher - a Python and MongoDB - based MatchMaker Exchange server

Build Status codecov DOI

Table of Contents:

  1. Intro
  2. Running the app using Docker
  3. Installing the app on a virtual environment with a running instance of MongoDB
  4. Data types
  5. Command line interface
  6. Server endpoints
  7. Patient matching algorithm
  8. Enabling matching notifications
  9. Enabling log errors notifications

Intro

PatientMatcher is a Python and MongoDB - based implementation of a MatchMaker Exchange(MME) server, developed and actively maintained by Clinical Genomics, Science For Life Laboratory in Stockholm. PatientMatcher is designed as a standalone application, but can easily communicate with external applications via REST API. The MME Stockholm node is being implemented in clinical production in collaboration with the Genomic Medicine Center Karolinska at the Karolinska University Hospital.

Running the app using Docker

An example containing a demo setup for the app is included in the docker-compose file. Note that this file is not intended for use in production and is onpy provided to illustrate how the backend and frontend of the app could be connected to a mongodb instance stored on an external image. Start the docker-compose demo using this command:

docker-compose up -d

The command will create 3 containers:

  • mongodb: starting a mongodb server with support for user authentication (--auth option)
  • pmatcher-cli: the a command-line app, which will connect to the server and populates it with demo data
  • pmatcher-web: a web server running on localhost and port 9020.

The server will be running and accepting requests sent from outside the containers (another terminal or a web browser). Read further down to find out about requests and commands.

To test server responses try to invoke the metrics endpoint with the following command:

curl localhost:5000/metrics

To stop the containers (and the server), run:

docker-compose down

Make sure that there are no mongo containers running before before running the command again. Commands:

docker ps -a
docker rm <id of the eventual vepo/mongo container>

Installing the app on a virtual environment with a running instance of MongoDB

Prerequisites

To use this server you'll need to have a working instance of MongoDB. from the mongo shell you can create a database and an authenticated user to handle connections using this syntax:

use pmatcher
db.createUser(
   {
     user: "pmUser",
     pwd: "pmPassword",
     roles: [ "dbOwner" ]
   }
)

After setting up the restricted access to the server you'll just have to launch the mongo demon using authentication:

mongod --auth --dbpath path_to_database_data

Clone patientMatcher repository from github using this command:

git clone https://github.com/Clinical-Genomics/patientMatcher.git

Change directory to the cloned folder and from there install the software using the following command:

pip install -r requirements.txt
pip install -e .

To customize the server configuration you'll need to edit the config.py file under the /instance folder.   For testing purposes you can keep the default configuration values as they are, but keep in mind that you should adjust these numbers when in production.

To start the server run this command:

pmatcher run -h custom_host -p custom_port

Please note that the code is NOT guaranteed to be bug-free and it must be adapted to be used in production.

Data types

This server implements the Matchmaker Exchange APIs. It accepts and returns patient data validated against the json schema defined in the MME reference-server project.

  

Command line interface

A list of available commands can be invoked by running the following command:

pmatcher

  

Adding demo data to server

For testing purposes you can upload a list of 50 benchmarking patients.  To add these patients to the database run the following command:

pmatcher add demodata --ensembl_genes

Please note that the list of benchmarking patients all gene ids are represented as HGNC gene symbols. The command above, with the --ensembl_genes option, will convert gene symbols to Ensembl ids, in accordance to the GA4GH API: https://github.com/ga4gh/mme-apis/blob/master/search-api.md.

The above command will also load a demo client with token DEMO into the database   

Removing a patient from the database.

You can remove a patient using the command line interface by invoking this command and providing either its ID or its label (or both actually):

pmatcher remove patient [OPTIONS]

Options:
-id TEXT     ID of the patient to be removed from database
-label TEXT  label of the patient to be removed from database

  

Updating patients' contact info using the command line

Contact information is a mandatory descriptor for each patient and represents the primary contact email address or URL used when looking for additional information for a patient in case of positive matches triggered by other patients from external nodes or the same database. A patient contact is described in PatientMatcher (and in the MatchMaker Exchange API) by these key/values:

  • href: a string represented by a URL (example: http://www.ncbi.nlm.nih.gov/pubmed/23542699) or the email address of the contact user (example: mailto:someone@somesite.com). This field is mandatory.
  • name: complete name of the contact user responsible for the patient saved in the MatchMaker. This field is mandatory.
  • institution: the Institution the contact person for the patients belongs to. This information is optional.

The command to update patients' contact info is the following:

pmatcher update contact [OPTIONS]

  Update contact person for a group of patients

Options:
  -old-href TEXT     Old contact href  [required]
  -href TEXT         New contact href  [required]
  -name TEXT         New contact name  [required]
  -institution TEXT  New contact institution

Let's assume a group of patients has a contact Peter Parker with href mailto:pparker@example.com. To replace the old user contact in all patients with the new contact info, for instance Bruce Wayne, type:

pmatcher update contact -old-href maito:pparker@example.com -href mailto:bwayne@example.com -name "Bruce Wayne" -institution "Wayne Enterprises, Inc."

Adding a client to the database

In order to save patients into patientMatcher you need to create at least one authorized client.  Use the following command to insert a client object in the database:

pmatcher add client [OPTIONS]

Options:
-id TEXT       Client ID  [required]
-token TEXT    Authorization token  [required]
-url TEXT      Client URL  [required]
-contact TEXT  Client email

POST request aimed at adding or modifying a patient in patientMatcher should be using a token from a client present in the database.  Clients may be from the command line with this command:

pmatcher remove client -id client_id

  

Adding a connected node to the database

To connect to another MME node and submit requests to it you should know the authentication token to the other node.  You can add a node to the database by running the command:

pmatcher add node [OPTIONS]

Options:
  -id TEXT                Server/Client ID  [required]
  -token TEXT             Authorization token  [required]
  -matching_url TEXT      URL to send match requests to  [required]
  -accepted_content TEXT  Accepted Content-Type  [required]
  -contact TEXT           An email address

Connected nodes may be removed any time using the command: 

pmatcher remove node -id node_id

  

Server endpoints

  • /patient/add.  To add patients using a POST request. Example:
curl -X POST \
  -H 'X-Auth-Token: DEMO' \
  -H 'Content-Type: application/vnd.ga4gh.matchmaker.v1.0+json' \
  -H 'Accept: application/json' \
  -d '{"patient":{
    "id":"patient_id",
    "contact": {"name":"Contact Name", "href":"mailto:contact_name@mail.com"},
    "features":[{"id":"HP:0009623"}],
    "genomicFeatures":[{"gene":{"id":"EFTUD2"}}]
  }}' localhost:9020/patient/add

To update the data of a patient already submitted to the server you can use the same command and add a patient with the same ID. 

The action of adding or updating a patient in the server will trigger an external search of similar patients from connected nodes.  If there are no connected nodes in the database or you are uploading demo data no search will be performed on other nodes.

  

  • patient/delete/<patient_id>.  You can delete a patient from the database by sending a DELETE request with its ID to the server. Example:
curl -X DELETE \
  -H 'X-Auth-Token: DEMO' \
  localhost:9020/patient/delete/patient_id

Please note that when a patient is deleted all its match results will be also deleted from the database. This is valid for matches where the patient was used as the query patient in searches performed on other nodes or the internal patientMatcher database (internal search). Matching results where the removed patient is instead listed among the matching results will be not removed from the database.

  

  • /metrics.  Use this endpoint to get database metrics.
    Stats which could be retrieved by a MME service are described here
    Example:
curl -X GET \
  localhost:9020/metrics

  

  • /nodes.  GET the list of connected nodes. Example:
curl -X GET \
  -H 'X-Auth-Token: DEMO' \
  localhost:9020/nodes

The response will return a list like this : [ { 'id' : node_1_id, 'description' : node1_description }, .. ] or an empty list if the server is not connected to external nodes.

  

  • /match.  POST a request with a query patient to patientMatcher and get a response with the patients in the server which are most similar to your query. Example:
curl -X POST \
  -H 'X-Auth-Token: DEMO' \
  -H 'Content-Type: application/vnd.ga4gh.matchmaker.v1.0+json' \
  -H 'Accept: application/vnd.ga4gh.matchmaker.v1.0+json' \
  -d '{"patient":{
    "id":"patient_id",
    "contact": {"name":"Contact Name", "href":"mailto:contact_name@mail.com"},
    "features":[{"id":"HP:0009623"}],
    "genomicFeatures":[{"gene":{"id":"EFTUD2"}}]
  }}' localhost:9020/match

The maximum number of patients returned by the server is a parameter which can be customized by editing the "MAX_RESULTS" field in the config.py file. Default value is 5. Patient matches are returned in order or descending similarity with the query patient (The most similar patients are higher in the list of results).

Another customizable parameter is the minimum patient score threshold for returned results (SCORE_THRESHOLD in the config file). Matches with patient score lower than this number won't be returned. Default value for this parameter is 0.

  

  • /match/external/<patient_id>.  Trigger a search in external nodes for patients similar to the one specified by the ID. Example:
curl -X POST \
  -H 'X-Auth-Token: DEMO' \
  localhost:9020/match/external/patient_id

It is possible to search for matching patients on a specific node. To do so specify the node id in the request args. Example:

curl -X POST \
  -H 'X-Auth-Token: DEMO' \
  localhost:9020/match/external/patient_id?node=specific_node_id

Read here how to get a list with the ID of the connected nodes.

  

  • /matches/<patient_id>.  Return all matches (internal and external) with positive results for a patient specified by an ID. Example:
curl -X GET \
  -H 'X-Auth-Token: DEMO' \
  localhost:9020/matches/patient_id

  

Patient matching algorithm.

Each patient query submitted to the server triggers a matching algorithm which will search and return those patients on the server that are most similar to the queried one. Patient similarity is measured by the a similarity score that may span from 0 (no matching) to 1 (exact matching).

Similarity score computation is taking into account genomic similarity and phenotype similarity across patients. The weight of these two factors is numerically evaluated into a GTscore and a PhenoScore, and the sum of the 2 constitutes the similarity score of the matching patient.

The relative weight of the GTscore and the PhenoScore can be customised by the database administrator by changing the values of the parameters "MAX_GT_SCORE" and "MAX_PHENO_SCORE" in the configuration file (instance/config.py). Default values are MAX_GT_SCORE: 0.5, MAX_PHENO_SCORE : 0.5.

Genotyping matching algorithm

GTscore is computed by evaluating the list of genomic features of the queried patient and the patients available on the MME server. PatientMatcher patients are saved with gene ids described by Ensembl gene ids, but it's possible to search the database using patients with genes represented by HGNC symbols, Entrez ids and Ensembl ids.

If the queried patient has no genomic features (only phenotype features) then GTscore of all the returned matches will be 0.

Example of how the algorithm works: Let's assume that 0.5 is the MAX_GT_SCORE possible for a patient match (default parameters).

If for instance the queried patient (QUERY) has 3 variants, each variant will have a relative weight of 0.1666 (0.5/3). 0.1666 will be the maximum score for each variant. Assuming having a QUERY patient with these variants:

  • gene X variant A
  • gene Y variant B
  • gene Z variant C

Any patient in the database having variants in any of the X,Y,Z genes will constitute a match (MATCH) to the queried patient and will be compared against it. Let's assume the variants in MATCH are:

  • gene X variant D (1)
  • gene Y variant B (2)
  • gene W variant E (3)

The evaluation of the matching features is always performed on the QUERY variants, in this way:

  • gene X variant A ---> gene match with (1). No variant match. Assigned score: 0.1666/4 (gene match only will be arbitrarily assigned a fourth of the relative weight of the variant)
  • gene Y variant B ---> exact matching of variant and gene with (2). Assigned score: 0.1666 (max relative weight of the variant)
  • gene Z variant C ---> No match, assigned score: 0.

GTscore assigned to the MATCH patients will then be: 0.1666/4 + 0.1666 + 0.

Note that the algorithm will evaluate and assign a score of 0.1666 (max relative weight of the variant) also to matching variants outside genes. This way patients will be evaluated for genetic similarity even if the variants lay outside genes.

Phenotype matching algorithm

Phenotype similarity is calculated by taking into account features and disorders of a patient.

  • Patient features are specified by the eventual HPO terms provided for the query patient. Similarity between HPO features will be equal the maximum similarity score between two patients if no disorders (OMIM terms) are provided for one or both patients.
    Otherwise feature similarity score will make up 1/2 of the maximum similarity score. Feature similarity is calculated as the simgic score obtained by comparing HPO terms of a query patient with those from a matching patient. You can find more information on semantic similarity comparison algorithms in this paper

  • Disorders (OMIM diagnoses), if available, will make up 1/2 of the maximum similarity score. OMIM score is calculated by pairwise comparison of the available OMIM terms for the patients.  

Enabling match notifications

Email notification of patient matching can be enabled by editing the email notification parameters in the configuration file (config.py). If you want to test your email configuration without sending real match notifications you could use this command:

pmatcher test email -recipient your_email@email.com

It is possible to choose to send complete or partial info for matching patients in the email notification body. Set NOTIFY_COMPLETE to True (in config.py) if you want to notify complete patient data (i.e. variants and phenotypes will be shared by email) or set it to False if email body should contain ONLY contact info and patient IDs for all matching patients. This latter option is useful to better secure the access to sensitive data.

Once these parameters are set to valid values a notification email will be sent in the following cases:

  • A patient is added to the database and the add request triggers a search on external nodes. There is at least one returned result (/patient/add endpoint).
  • An external search is actively performed on connected nodes and returns at least one result (/match/external/<patient_id> endpoint).
  • The server is interrogated by an external node and returns at least one match (/match endpoint). In this case a match notification is sent to each contact of the matches (patients in results).
  • An internal search is submitted to the server using a patient from the database (/match endpoint) and this search returns at least one match. In this case contact users of all patients involved will be notified (contact from query patient and contacts from the result list of patients).

You can stop server notification any time by commenting the MAIL_SERVER parameter in config file and rebooting the server.

Enabling log errors notifications

App email notifications might be enabled by providing one or more email addresses as values for the ADMINS parameter in the configuration file. Note that the email handler will only notify app errors (LOG level = error).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

patientMatcher-2.12.tar.gz (3.5 MB view hashes)

Uploaded Source

Built Distribution

patientMatcher-2.12-py3-none-any.whl (3.6 MB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page