#!/usr/bin/env python # -*- coding: utf-8 -*- PATH = { "DISEASES": "diseases" } import sys, os class Disease: name = None symptoms = None def __init__( self, name, symptoms=None ): self.name = name self.symptoms = symptoms or [] # __init__() def has_symptom( self, symptom ): """ Check if the symptom happens in this disease """ return symptom in self.symptoms # has_symptom() def load( self, filename ): """ Load disease's symptoms from filename, which must have one symptom per line. """ try: f = open( filename, "r" ) c = f.read() f.close() except Exception, e: print >> sys.stderr, "ERROR: %s" % e c = c.split( '\n' ) for l in c: l = l.strip().lower() if l: self.symptoms += [ l ] # load() # Disease class Diseases: diseases = None def __init__( self, diseases=None ): self.diseases = diseases or [] # __init__() def load_diseases( self, dir ): """ Load diseases from directory. """ self.diseases = [] try: df = os.listdir( dir ) for d in df: f = os.path.join( dir, d ) if os.path.isfile( f ): disease = Disease( d ) disease.load( f ) self.diseases += [ disease ] except Exception, e: print >> sys.stderr, "ERROR: %s" % e # load_diseases() def list_symptoms( self ): """ Returns a list of every possible symptom """ symptoms = [] for d in self.diseases: for s in d.symptoms: if s not in symptoms: symptoms += [ s ] return symptoms # list_symptoms() def check_symptoms_exists( self, symptoms ): """ Check if symptoms exists in the know diseases. Return a list of list of exiting (valid) symptoms and a list of non-existant symptoms """ valid = [] invalid = [] existing_symptoms = self.list_symptoms() for s in symptoms: if s in existing_symptoms: valid += [ s ] else: invalid += [ s ] return [ valid, invalid ] # check_symptoms_exists() def analyse_count( self, symptoms ): """ Analyse symptoms against diseases based on how many symptoms match a certain disease. Returns a list of pairs ('disease',count) descendent on count. """ disease_count = {} # zero disease counters: for d in self.diseases: disease_count[ d.name ] = 0 # count symptoms: for s in symptoms: for d in self.diseases: if d.has_symptom( s ): disease_count[ d.name ] += 1 # Translate dict to list of (key,value): analyse = disease_count.items() # Sort based on count (or value, the second element in pair) # in the inverse order: analyse.sort( lambda a, b: cmp( b[ 1 ], a[ 1 ] ) ) return analyse # analyse_count() def analyse_probability( self, symptoms ): """ Analyse symptoms against diseases based on the percentual of symptoms given match. Symptoms Matching Probability = -------------------------- Total Disease Symptoms Returns a list of tuples ('disease', count, probability) descendant on probability. """ count_analyse = self.analyse_count( symptoms ) map_disease = {} # Make access faster and easier for d in self.diseases: map_disease[ d.name ] = d analyse = [] for ec in count_analyse: # ec is ('disease', count) # ep is ('disease', count, probability ) disease_total = len( map_disease[ ec[ 0 ] ].symptoms ) ep = ec + ( float( ec[ 1 ] ) / disease_total, ) analyse += [ ep ] analyse.sort( lambda a,b: cmp( b[ 2 ], a[ 2 ] ) ) return analyse # analyse_probability() # Diseases def ui_get_symptoms(): """ Get user input with symptoms to be analysed, parse it and return a list of symptoms. """ # Prompt user for symptoms symptoms = raw_input( "Sintomas do Paciente (lista " \ "separada por virgula): " ) symptoms = symptoms.split( "," ) sl = [] for s in symptoms: s = s.strip().lower() if s: sl += [ s ] return sl # ui_get_symptoms() if __name__ == "__main__": diseases = Diseases() diseases.load_diseases( PATH[ "DISEASES" ] ) # Get user input: user_symptoms = ui_get_symptoms() # Check for [in]valid symptoms user_symptoms, invalid_symptoms = \ diseases.check_symptoms_exists( user_symptoms ) # print out invalid symptoms: for s in invalid_symptoms: print >> sys.stderr, ( "AVISO: Sintoma '%s' descartado " \ "por nao existir em nenhuma doenca " \ "coberta por este software." ) % ( s ) print "Sintomas a serem analisados: `%s'" %(", ".join( user_symptoms )) print "\nResultados:" print "\n* Contagem:" analyse = diseases.analyse_count( user_symptoms ) # Summary: disease = analyse[ 0 ][ 0 ].title() # format symtom_plural = "" # format between singular and plural if analyse[ 0 ][ 1 ] > 1: symptom_plural = "sintomas" else: symptom_plural = "sintoma" print " Sumario: `%s' com %d %s." % ( disease, analyse[ 0 ][ 1 ], symptom_plural) print " Resultado completo:" print "\t.--------------------------------.-----." print "\t| Doenca | No. |" print "\t}--------------------------------+-----{" for e in analyse: print "\t| %s | % 3d |" % ( e[ 0 ][ : 30 ].ljust( 30 ), e[ 1 ] ) print "\t`--------------------------------'-----'" print "\n* Porcentagem:" analyse = diseases.analyse_probability( user_symptoms ) # Summary: disease = analyse[ 0 ][ 0 ].title() # format symtom_plural = "" # format between singular and plural if analyse[ 0 ][ 1 ] > 1: symptom_plural = "sintomas" else: symptom_plural = "sintoma" di = None for d in diseases.diseases: if d.name == analyse[ 0 ][ 0 ]: di = d print " Sumario: `%s' com %d %s de %d desta doenca, " \ "correspondente a %0.2f%% dos sintomas." % \ ( disease, analyse[ 0 ][ 1 ], symptom_plural, len( di.symptoms ), analyse[ 0 ][ 2 ] ) print " Resultado completo:" print "\t.--------------------------------.-----.-------." print "\t| Doenca | No. | % |" print "\t}--------------------------------+-----+-------{" for e in analyse: print "\t| %s | % 3d | % 02.2f |" \ % ( e[ 0 ][ : 30 ].ljust( 30 ), e[ 1 ], e[ 2 ]) print "\t`--------------------------------'-----'-------'"