first commit
This commit is contained in:
parent
c50b0df427
commit
b55a361374
4 changed files with 355 additions and 0 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -162,3 +162,5 @@ cython_debug/
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
# xfr
|
||||||
|
*.xlsx
|
||||||
|
|
275
src/pacs.py
Normal file
275
src/pacs.py
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import glob
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import time
|
||||||
|
|
||||||
|
from pywinauto import Desktop, actionlogger, mouse, keyboard
|
||||||
|
from pywinauto.application import Application
|
||||||
|
from pywinauto.timings import Timings
|
||||||
|
|
||||||
|
from settings import *
|
||||||
|
|
||||||
|
def mouse_click(ws):
|
||||||
|
r = ws.rectangle()
|
||||||
|
coords = (r.left + r.right)//2, (r.top + r.bottom)//2
|
||||||
|
mouse.click(coords=coords)
|
||||||
|
|
||||||
|
def login(id=USER_ID, pw=PASSWORD):
|
||||||
|
# Timings.fast()
|
||||||
|
# Timings.window_find_timeout = 10
|
||||||
|
|
||||||
|
patterns = [
|
||||||
|
# '另存新檔.*'
|
||||||
|
'.* - Microsoft Edge$',
|
||||||
|
'.*日期:.*',
|
||||||
|
]
|
||||||
|
|
||||||
|
for p in patterns:
|
||||||
|
|
||||||
|
while True:
|
||||||
|
quit = False
|
||||||
|
try:
|
||||||
|
w = Desktop(backend="uia").window(title_re=p)
|
||||||
|
logging.warning(p + str(w))
|
||||||
|
w.close()
|
||||||
|
except:
|
||||||
|
quit = True
|
||||||
|
if quit:
|
||||||
|
break
|
||||||
|
|
||||||
|
app = Application(backend="uia").start(r'C:\Users\xfr\Desktop\PACS.exe')
|
||||||
|
|
||||||
|
w = Desktop(backend="uia").window(title_re='.* - Microsoft Edge$')
|
||||||
|
w.wait('ready')
|
||||||
|
|
||||||
|
# time.sleep(9)
|
||||||
|
|
||||||
|
app = Application(backend="uia").connect(title_re='.* - Microsoft Edge$')
|
||||||
|
# app.wait_cpu_usage_lower(threshold=50)
|
||||||
|
|
||||||
|
# dlg_spec = Desktop(backend="uia").window(title_re='.* - Microsoft Edge$')
|
||||||
|
window = app.window(title_re='.* - Microsoft Edge$')
|
||||||
|
# dlg_spec = app.top_window()
|
||||||
|
|
||||||
|
window['使用者帳號: \xa0Edit'].set_text(id)
|
||||||
|
window['使用者密碼: \xa0Edit'].set_text(pw)
|
||||||
|
|
||||||
|
# r = window['登入Static'].rectangle()
|
||||||
|
# coords = (r.left + r.right)//2, (r.top + r.bottom)//2
|
||||||
|
# mouse.click(coords=coords)
|
||||||
|
mouse_click(window['登入Static'])
|
||||||
|
time.sleep(9)
|
||||||
|
|
||||||
|
return app, window
|
||||||
|
|
||||||
|
def dump(pane):
|
||||||
|
print(pane)
|
||||||
|
print(dir(pane))
|
||||||
|
print(pane.element_info)
|
||||||
|
print(pane.get_properties())
|
||||||
|
print(pane.print_control_identifiers())
|
||||||
|
# print(len(pane.children()))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def save_study(chartno, outdir):
|
||||||
|
|
||||||
|
while True:
|
||||||
|
logging.warning('connecting '+chartno)
|
||||||
|
try:
|
||||||
|
app = Application(backend="uia").connect(title_re='^%s.*'%chartno)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
logging.warning(str(app))
|
||||||
|
window = app.top_window()
|
||||||
|
# window.maximize()
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
while True:
|
||||||
|
TFlowPanel = window.child_window(class_name='TFlowPanel', found_index=index)
|
||||||
|
# dump(TFlowPanel)
|
||||||
|
if TFlowPanel.control_count():
|
||||||
|
break
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
series = sorted(TFlowPanel.children(), key=lambda x: x.rectangle().left)
|
||||||
|
c = series[0]
|
||||||
|
c.set_focus()
|
||||||
|
mouse_click(c)
|
||||||
|
keyboard.send_keys('^i')
|
||||||
|
|
||||||
|
for c in series:
|
||||||
|
|
||||||
|
logging.warning(str(c.element_info))
|
||||||
|
c.set_focus()
|
||||||
|
mouse_click(c)
|
||||||
|
|
||||||
|
mouse_click(window['註釋/標籤'])
|
||||||
|
TToolBar = window.child_window(class_name='TToolBar', found_index=2)
|
||||||
|
mouse_click(TToolBar.Button5)
|
||||||
|
time.sleep(1)
|
||||||
|
export_to_file = window['輸出至檔案']
|
||||||
|
export_to_file.wait('ready')
|
||||||
|
export = export_to_file.wrapper_object()
|
||||||
|
export.click()
|
||||||
|
|
||||||
|
TDicomTagListForm = window['DICOM 標籤清單Dialog']
|
||||||
|
|
||||||
|
dlg_save = Desktop(backend="uia").window(title='另存新檔')
|
||||||
|
NEdit = dlg_save['檔案名稱(N):Edit']
|
||||||
|
NEdit.wait('ready')
|
||||||
|
edit = NEdit.wrapper_object()
|
||||||
|
pahtname = os.path.join(outdir, edit.get_value())
|
||||||
|
for p in glob.glob(pahtname + '*'):
|
||||||
|
os.remove(p)
|
||||||
|
edit.set_text(pahtname)
|
||||||
|
dlg_save['存檔(S)Button'].wrapper_object().click()
|
||||||
|
|
||||||
|
TDicomTagListForm.close()
|
||||||
|
# break
|
||||||
|
|
||||||
|
|
||||||
|
keyboard.send_keys('^s')
|
||||||
|
keyboard.send_keys('{DOWN}')
|
||||||
|
keyboard.send_keys('{DOWN}')
|
||||||
|
|
||||||
|
# time.sleep(9)
|
||||||
|
|
||||||
|
# logging.warning(str(datetime.datetime.now()))
|
||||||
|
TFormSaveBitmap = window['選項']
|
||||||
|
# TFormSaveBitmap.dump_tree(filename='z-%s-TFormSaveBitmap.txt'%chartno)
|
||||||
|
TFormSaveBitmap.Edit5.set_text(outdir)
|
||||||
|
TFormSaveBitmap.Button2.click()
|
||||||
|
|
||||||
|
logging.warning('button clicked')
|
||||||
|
time.sleep(1)
|
||||||
|
logging.warning('saving started')
|
||||||
|
saving = window.child_window(title_re='^另存新檔.*')
|
||||||
|
logging.warning('saving exists')
|
||||||
|
saving.wait_not("exists", timeout=999)
|
||||||
|
logging.warning('saving not exists')
|
||||||
|
|
||||||
|
c.set_focus()
|
||||||
|
mouse_click(c)
|
||||||
|
keyboard.send_keys('^q')
|
||||||
|
|
||||||
|
# while True:
|
||||||
|
# try:
|
||||||
|
# if not window.exists():
|
||||||
|
# break
|
||||||
|
# except :
|
||||||
|
# break
|
||||||
|
|
||||||
|
# logging.warning(str((datetime.datetime.now())))
|
||||||
|
# c.set_focus()
|
||||||
|
# mouse_click(c)
|
||||||
|
# keyboard.send_keys('^q')
|
||||||
|
# time.sleep(9)
|
||||||
|
|
||||||
|
|
||||||
|
def save_patient(chartno, outdir, query = "CT,MR"):
|
||||||
|
|
||||||
|
app = Application(backend="uia").connect(title_re='.* - Microsoft Edge$')
|
||||||
|
logging.warning(str(app))
|
||||||
|
# window = app.window(title_re='.* - Microsoft Edge$')
|
||||||
|
window=app.top_window()
|
||||||
|
window.maximize()
|
||||||
|
|
||||||
|
if query:
|
||||||
|
|
||||||
|
window['病歷號:Edit'].set_text(chartno)
|
||||||
|
window['儀器種類:Edit'].set_text(query)
|
||||||
|
|
||||||
|
r = window['ComboBox關閉'].rectangle()
|
||||||
|
coords = (r.left + r.right)//2, (r.top + r.bottom)//2
|
||||||
|
mouse.click(coords=coords)
|
||||||
|
keyboard.send_keys('{UP}')
|
||||||
|
keyboard.send_keys('{UP}')
|
||||||
|
keyboard.send_keys('{ENTER}')
|
||||||
|
|
||||||
|
window['Button'].click()
|
||||||
|
time.sleep(9)
|
||||||
|
|
||||||
|
ListItem = window['開啟影像'].parent()
|
||||||
|
# print(ListItem.texts())
|
||||||
|
|
||||||
|
ListView = ListItem.parent()
|
||||||
|
|
||||||
|
shutil.rmtree(outdir, ignore_errors=True)
|
||||||
|
os.makedirs(outdir, exist_ok=True)
|
||||||
|
|
||||||
|
items =[]
|
||||||
|
|
||||||
|
for item in ListView.items():
|
||||||
|
if item.texts()[0] != '開啟影像':
|
||||||
|
continue
|
||||||
|
items.append(item)
|
||||||
|
logging.debug(str(item.rectangle()))
|
||||||
|
|
||||||
|
for i, item in enumerate(items):
|
||||||
|
# if i < 7:
|
||||||
|
# continue
|
||||||
|
bottom = False
|
||||||
|
logging.debug(str(items[i].rectangle()))
|
||||||
|
|
||||||
|
try:
|
||||||
|
if items[i+1].rectangle().top < 1:
|
||||||
|
bottom = True
|
||||||
|
except:
|
||||||
|
bottom = True
|
||||||
|
|
||||||
|
if bottom:
|
||||||
|
item.set_focus()
|
||||||
|
keyboard.send_keys('{DOWN}')
|
||||||
|
|
||||||
|
# r = item.rectangle()
|
||||||
|
# coords = (r.left + r.right)//2, (r.top + r.bottom)//2
|
||||||
|
# mouse.scroll(coords=coords)
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
logging.debug(str(item.rectangle()))
|
||||||
|
|
||||||
|
mouse_click(item)
|
||||||
|
|
||||||
|
save_study(chartno, outdir)
|
||||||
|
logging.warning(chartno+" completed "+query)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# exit()
|
||||||
|
|
||||||
|
|
||||||
|
actionlogger.enable()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s'
|
||||||
|
|
||||||
|
FORMAT = '%(asctime)s %(message)s'
|
||||||
|
|
||||||
|
logging.basicConfig(filename=__file__.replace('.py','.%s.log'%str(datetime.datetime.now()).replace(':','')),
|
||||||
|
format=FORMAT)
|
||||||
|
|
||||||
|
# logger = logging.getLogger('pywinauto')
|
||||||
|
# logger.handlers[0] = logging.FileHandler(__file__.replace('.py','.log'))
|
||||||
|
# logging.basicConfig(format=FORMAT)
|
||||||
|
# formatter = logging.Formatter(FORMAT)
|
||||||
|
# logger.handlers[0].setFormatter(formatter)
|
||||||
|
|
||||||
|
app, window = login()
|
||||||
|
save_patient('5344141', r'T:\0\5344141', query="CT,MR")
|
||||||
|
# save_patient('5344141', r'T:\0\5344141', query="CT")
|
||||||
|
# save_patient('2380784', r'T:\3\2380784', query=False)
|
||||||
|
# save_study('2380784', outdir=r'T:\0\2380784')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# step2()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
53
src/pituitary.py
Normal file
53
src/pituitary.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
import pacs
|
||||||
|
|
||||||
|
def get_pacs(series, outdir, max_patients=10):
|
||||||
|
app, window = pacs.login()
|
||||||
|
num_patients = 0
|
||||||
|
for index, row in series.items():
|
||||||
|
if isinstance(row, float):
|
||||||
|
row = int(row)
|
||||||
|
chartno = str(int(row)).zfill(7)
|
||||||
|
|
||||||
|
complete_file = Path(f'{outdir}\\{chartno}.complete')
|
||||||
|
if complete_file.is_file():
|
||||||
|
logging.warning('skip '+chartno)
|
||||||
|
continue
|
||||||
|
|
||||||
|
logging.warning('saving '+chartno)
|
||||||
|
pacs.save_patient(chartno, f'{outdir}\\{chartno}', query="CT,MR")
|
||||||
|
|
||||||
|
complete_file.touch()
|
||||||
|
num_patients += 1
|
||||||
|
if num_patients >= max_patients:
|
||||||
|
break
|
||||||
|
|
||||||
|
return num_patients
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
FORMAT = '%(asctime)s %(message)s'
|
||||||
|
logging.basicConfig(filename=__file__.replace('.py','.%s.log'%str(datetime.datetime.now()).replace(':','')),
|
||||||
|
format=FORMAT)
|
||||||
|
|
||||||
|
# df = pd.read_excel('pituitary-op.xlsx')
|
||||||
|
# series = df['PatChartNo'].drop_duplicates().iloc[-1000:].iloc[::-1]
|
||||||
|
# outdir = r'T:\pituitary-op'
|
||||||
|
|
||||||
|
df = pd.read_excel('pituitary-srs.xlsx', sheet_name='NFA Data (n=178)', header=1)
|
||||||
|
series = df[~df['Patient ID'].isna()]['Patient ID'].drop_duplicates()
|
||||||
|
outdir = r'T:\pituitary-srs'
|
||||||
|
|
||||||
|
get_pacs(series, outdir)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
25
src/settings.py
Normal file
25
src/settings.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import os
|
||||||
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
|
PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
PROJECT_APP = os.path.basename(PROJECT_APP_PATH)
|
||||||
|
BASE_DIR = os.path.dirname(PROJECT_APP_PATH)
|
||||||
|
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
USER_ID = '123456'
|
||||||
|
PASSWORD = '123456'
|
||||||
|
|
||||||
|
##################
|
||||||
|
# LOCAL SETTINGS #
|
||||||
|
##################
|
||||||
|
|
||||||
|
# Allow any settings to be defined in local_settings.py which should be
|
||||||
|
# ignored in your version control system allowing for settings to be
|
||||||
|
# defined per machine.
|
||||||
|
|
||||||
|
# from local_settings import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
from local_settings import *
|
||||||
|
except ImportError:
|
||||||
|
pass
|
Loading…
Reference in a new issue