def __init__(self, config): """ class initializer :param config: configuration file for WorklistManager :return: """ cfg_defaults = { 'pdb_hostname': 'localhost', 'pdb_username': '******', 'pdb_password': '******', 'pdb_dbname': 'fcdctest', 'mr_scanner_regex': '.*(SKYRA|PRASMA(FIT)).*', 'dcmtk_setup_cmd': '', 'dcmtk_wlbroker_store': '/scratch/OrthancData/DicomWorklist/WLBROKER' } cfg = ConfigParser.ConfigParser(defaults=cfg_defaults) cfg.read(config) self.mr_scanner_regex = re.compile( cfg.get('WLBROKER', 'mr_scanner_regex')) self.dcmtk_setup = cfg.get('WLBROKER', 'dcmtk_setup_cmd') self.dcmtk_wlbroker_dir = cfg.get('WLBROKER', 'dcmtk_wlbroker_store') self.logger = getLogger(name=self.__class__.__name__, lvl=int(cfg.get('LOGGING', 'level'))) self.__getDBConnectInfo__(cfg) self.pdb = IMySQL(db_host=self.pdb_host, db_username=self.pdb_uid, db_password=self.pdb_pass, db_name=self.pdb_name)
def __init__(self, config): """ class initializer :param config: configuration file for WorklistManager :return: """ cfg_defaults = {'pdb_hostname': 'localhost', 'pdb_username': '******', 'pdb_password': '******', 'pdb_dbname': 'fcdctest', 'mr_scanner_regex': '.*(SKYRA|PRASMA(FIT)).*', 'dcmtk_setup_cmd': '', 'dcmtk_wlbroker_store': '/scratch/OrthancData/DicomWorklist/WLBROKER'} cfg = ConfigParser.ConfigParser(defaults=cfg_defaults) cfg.read(config) self.mr_scanner_regex = re.compile(cfg.get('WLBROKER','mr_scanner_regex')) self.dcmtk_setup = cfg.get('WLBROKER','dcmtk_setup_cmd') self.dcmtk_wlbroker_dir = cfg.get('WLBROKER','dcmtk_wlbroker_store') self.logger = getLogger(name=self.__class__.__name__, lvl=int(cfg.get('LOGGING', 'level'))) self.__getDBConnectInfo__(cfg) self.pdb = IMySQL(db_host = self.pdb_host, db_username = self.pdb_uid, db_password = self.pdb_pass, db_name = self.pdb_name)
class WorklistManager: def __init__(self, config): """ class initializer :param config: configuration file for WorklistManager :return: """ cfg_defaults = { 'pdb_hostname': 'localhost', 'pdb_username': '******', 'pdb_password': '******', 'pdb_dbname': 'fcdctest', 'mr_scanner_regex': '.*(SKYRA|PRASMA(FIT)).*', 'dcmtk_setup_cmd': '', 'dcmtk_wlbroker_store': '/scratch/OrthancData/DicomWorklist/WLBROKER' } cfg = ConfigParser.ConfigParser(defaults=cfg_defaults) cfg.read(config) self.mr_scanner_regex = re.compile( cfg.get('WLBROKER', 'mr_scanner_regex')) self.dcmtk_setup = cfg.get('WLBROKER', 'dcmtk_setup_cmd') self.dcmtk_wlbroker_dir = cfg.get('WLBROKER', 'dcmtk_wlbroker_store') self.logger = getLogger(name=self.__class__.__name__, lvl=int(cfg.get('LOGGING', 'level'))) self.__getDBConnectInfo__(cfg) self.pdb = IMySQL(db_host=self.pdb_host, db_username=self.pdb_uid, db_password=self.pdb_pass, db_name=self.pdb_name) def __del__(self): self.pdb.closeConnector() def __getDBConnectInfo__(self, cfg): '''common function to get database connection information ''' ## project database connection information self.pdb_host = cfg.get('PDB', 'pdb_hostname') self.pdb_uid = cfg.get('PDB', 'pdb_username') self.pdb_pass = cfg.get('PDB', 'pdb_password') self.pdb_name = cfg.get('PDB', 'pdb_dbname') if not self.pdb_pass: ## try ask for password from the interactive shell if sys.stdin.isatty(): ## for interactive password typing self.pdb_pass = getpass.getpass('Project DB password: '******'Project DB password: '******''): """ make worklist items for DICOM worklist broker :param eDate: the date in which the MR scan is planned :param worklistStore: (optional) the filesystem path in which the DICOM worklist items will be stored. If it's specified, it replaces the path specified by 'dcmtk_wlbroker_store' in the config file. :return: a list of filesystem paths to the successfully created worklist items """ worklistFiles = [] s = Shell() dump2dcm_cmd = 'dump2dcm' if self.dcmtk_setup: dump2dcm_cmd = '%s; %s' % (self.dcmtk_setup, dump2dcm_cmd) if not worklistStore: worklistStore = self.dcmtk_wlbroker_dir for wl in self.getWorklistItems(eDate): # save worklist as human-readable (DICOM dump) dump_fpath = os.path.join( worklistStore, '%s_%s.dump' % (wl.modalityAE, wl.eventId)) f = open(dump_fpath, 'w') f.write(str(wl)) f.close() # convert DICOM dump to DICOM format dcm_fpath = os.path.join(worklistStore, '%s_%s.wl' % (wl.modalityAE, wl.eventId)) s_cmd = '%s %s %s' % (dump2dcm_cmd, dump_fpath, dcm_fpath) self.logger.debug('dump2dcm command: %s' % s_cmd) rc, output, m = s.cmd1(s_cmd) if rc != 0: self.logger.error('DICOM worklist item creation failed: ' % wl.studyId) else: worklistFiles.append(dcm_fpath) return worklistFiles def getWorklistItems(self, eDate=date.today()): '''compose worklist items based on booking events retrieved from calendar table in PDB ''' conn = self.pdb.getConnector() crs = None worklist = [] try: qry = 'SELECT a.id,a.project_id,a.subj_ses,a.start_date,a.start_time,a.user_id,b.projectName,c.description AS lab_desc FROM calendar_items_new AS a, projects AS b, calendars AS c WHERE a.status IN (\'CONFIRMED\',\'TENTATIVE\') AND a.subj_ses NOT IN (\'Cancellation\',\'0\') AND a.start_date = DATE(\'%s\') AND a.project_id = b.id AND a.calendar_id = c.id ORDER BY a.start_time' % eDate.strftime( '%Y-%m-%d') self.logger.debug(qry) crs = conn.cursor() crs.execute(qry) for (eId, projectId, subj_ses, startDate, startTime, userId, projectName, labDesc) in crs.fetchall(): # only events for MR scanners are considered m = self.mr_scanner_regex.match(labDesc.upper()) if not m: continue scannerAE = m.group(1) d = re.compile('\s*(-)\s*').split(subj_ses) subjectId = d[0] # always set session id to '1' if it's not part of subj_ses string sessionId = d[-1] if len(d) > 1 else '1' # in some MySQL library, the startTime is returned as timedelta object eStartTime = None if type(startTime) is timedelta: eStartTime = datetime(startDate.year, startDate.month, startDate.day) eStartTime += startTime else: eStartTime = startTime # make another SQL query to get user name try: crs1 = conn.cursor() crs1.execute( 'SELECT firstName,lastName FROM users WHERE id = \'%s\'' % userId) (firstName, lastName) = crs1.fetchone() userId = '%s %s' % (firstName, lastName) except Exception, e: self.logger.exception('User name select failed: %s' % userId) else: pass finally: try: crs1.close() except Exception, e: pass # construct worklist item wl = WorklistItem(projectId, projectName, subjectId, sessionId, startDate.strftime('%Y%m%d'), eStartTime.strftime('%H%M%S'), scannerAE, userId) worklist.append(wl)
class WorklistManager: def __init__(self, config): """ class initializer :param config: configuration file for WorklistManager :return: """ cfg_defaults = {'pdb_hostname': 'localhost', 'pdb_username': '******', 'pdb_password': '******', 'pdb_dbname': 'fcdctest', 'mr_scanner_regex': '.*(SKYRA|PRASMA(FIT)).*', 'dcmtk_setup_cmd': '', 'dcmtk_wlbroker_store': '/scratch/OrthancData/DicomWorklist/WLBROKER'} cfg = ConfigParser.ConfigParser(defaults=cfg_defaults) cfg.read(config) self.mr_scanner_regex = re.compile(cfg.get('WLBROKER','mr_scanner_regex')) self.dcmtk_setup = cfg.get('WLBROKER','dcmtk_setup_cmd') self.dcmtk_wlbroker_dir = cfg.get('WLBROKER','dcmtk_wlbroker_store') self.logger = getLogger(name=self.__class__.__name__, lvl=int(cfg.get('LOGGING', 'level'))) self.__getDBConnectInfo__(cfg) self.pdb = IMySQL(db_host = self.pdb_host, db_username = self.pdb_uid, db_password = self.pdb_pass, db_name = self.pdb_name) def __del__(self): self.pdb.closeConnector() def __getDBConnectInfo__(self, cfg): '''common function to get database connection information ''' ## project database connection information self.pdb_host = cfg.get('PDB','pdb_hostname') self.pdb_uid = cfg.get('PDB','pdb_username') self.pdb_pass = cfg.get('PDB','pdb_password') self.pdb_name = cfg.get('PDB','pdb_dbname') if not self.pdb_pass: ## try ask for password from the interactive shell if sys.stdin.isatty(): ## for interactive password typing self.pdb_pass = getpass.getpass('Project DB password: '******'Project DB password: '******''): """ make worklist items for DICOM worklist broker :param eDate: the date in which the MR scan is planned :param worklistStore: (optional) the filesystem path in which the DICOM worklist items will be stored. If it's specified, it replaces the path specified by 'dcmtk_wlbroker_store' in the config file. :return: a list of filesystem paths to the successfully created worklist items """ worklistFiles = [] s = Shell() dump2dcm_cmd = 'dump2dcm' if self.dcmtk_setup: dump2dcm_cmd = '%s; %s' % (self.dcmtk_setup, dump2dcm_cmd) if not worklistStore: worklistStore = self.dcmtk_wlbroker_dir for wl in self.getWorklistItems(eDate): # save worklist as human-readable (DICOM dump) dump_fpath = os.path.join(worklistStore, '%s_%s.dump' % (wl.modalityAE, wl.eventId)) f = open( dump_fpath,'w') f.write( str(wl) ) f.close() # convert DICOM dump to DICOM format dcm_fpath = os.path.join(worklistStore, '%s_%s.wl' % (wl.modalityAE, wl.eventId)) s_cmd = '%s %s %s' % (dump2dcm_cmd, dump_fpath, dcm_fpath) self.logger.debug('dump2dcm command: %s' % s_cmd) rc,output,m = s.cmd1(s_cmd) if rc != 0: self.logger.error('DICOM worklist item creation failed: ' % wl.studyId) else: worklistFiles.append(dcm_fpath) return worklistFiles def getWorklistItems(self, eDate=date.today()): '''compose worklist items based on booking events retrieved from calendar table in PDB ''' conn = self.pdb.getConnector() crs = None worklist = [] try: qry = 'SELECT a.id,a.project_id,a.subj_ses,a.start_date,a.start_time,a.user_id,b.projectName,c.description AS lab_desc FROM calendar_items_new AS a, projects AS b, calendars AS c WHERE a.status IN (\'CONFIRMED\',\'TENTATIVE\') AND a.subj_ses NOT IN (\'Cancellation\',\'0\') AND a.start_date = DATE(\'%s\') AND a.project_id = b.id AND a.calendar_id = c.id ORDER BY a.start_time' % eDate.strftime('%Y-%m-%d') self.logger.debug(qry) crs = conn.cursor() crs.execute(qry) for (eId, projectId, subj_ses, startDate, startTime, userId, projectName, labDesc) in crs.fetchall(): # only events for MR scanners are considered m = self.mr_scanner_regex.match(labDesc.upper()) if not m: continue scannerAE = m.group(1) d = re.compile('\s*(-)\s*').split(subj_ses) subjectId = d[0] # always set session id to '1' if it's not part of subj_ses string sessionId = d[-1] if len(d) > 1 else '1' # in some MySQL library, the startTime is returned as timedelta object eStartTime = None if type(startTime) is timedelta: eStartTime = datetime(startDate.year, startDate.month, startDate.day) eStartTime += startTime else: eStartTime = startTime # make another SQL query to get user name try: crs1 = conn.cursor() crs1.execute('SELECT firstName,lastName FROM users WHERE id = \'%s\'' % userId) (firstName, lastName) = crs1.fetchone() userId = '%s %s' % (firstName, lastName) except Exception, e: self.logger.exception('User name select failed: %s' % userId) else: pass finally: try: crs1.close() except Exception, e: pass # construct worklist item wl = WorklistItem(projectId, projectName, subjectId, sessionId, startDate.strftime('%Y%m%d'), eStartTime.strftime('%H%M%S'), scannerAE, userId) worklist.append(wl)