labkeyBrowser.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. import os
  2. import unittest
  3. from __main__ import vtk, qt, ctk, slicer
  4. from slicer.ScriptedLoadableModule import *
  5. #import slicerNetwork
  6. import json
  7. import zipfile
  8. import pathlib
  9. import sys
  10. import urllib3
  11. import string
  12. #
  13. # labkeySlicerPythonExtension
  14. #
  15. class labkeyBrowser(ScriptedLoadableModule):
  16. """Uses ScriptedLoadableModule base class, available at:
  17. https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
  18. """
  19. def __init__(self, parent):
  20. ScriptedLoadableModule.__init__(self, parent)
  21. self.parent.title = "labkeyBrowser" # TODO make this more human readable by adding spaces
  22. self.parent.categories = ["LabKey"]
  23. self.parent.dependencies = []
  24. self.parent.contributors = ["Andrej Studen (UL/FMF)"] # replace with "Firstname Lastname (Organization)"
  25. self.parent.helpText = """
  26. Interface to files in LabKey
  27. """
  28. self.parent.acknowledgementText = """
  29. Developed within the medical physics research programme of the Slovenian research agency.
  30. """ # replace with organization, grant and thanks.
  31. #
  32. # labkeySlicerPythonExtensionWidget
  33. #
  34. class labkeyBrowserWidget(ScriptedLoadableModuleWidget):
  35. """Uses ScriptedLoadableModuleWidget base class, available at:
  36. https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
  37. """
  38. def setup(self):
  39. ScriptedLoadableModuleWidget.setup(self)
  40. # Instantiate and connect widgets ...
  41. self.logic=labkeyBrowserLogic(self)
  42. fhome=os.path.expanduser('~')
  43. fsetup=os.path.join(fhome,'.labkey','slicer','setup.json')
  44. try:
  45. with open(fsetup) as f:
  46. self.setup=json.load(f)
  47. except FileNotFoundError:
  48. self.setup={}
  49. try:
  50. pt=self.setup['paths']
  51. except KeyError:
  52. self.setup['paths']={}
  53. try:
  54. sys.path.append(self.setup['paths']['labkeyInterface'])
  55. except KeyError:
  56. self.setup['paths']['labkeyInterface']=loadLibrary('labkeyInterface')
  57. with open(fsetup,'w') as f:
  58. json.dump(self.setup,f,indent='\t')
  59. import labkeyInterface
  60. import labkeyDatabaseBrowser
  61. import labkeyFileBrowser
  62. #self.network=slicerNetwork.labkeyURIHandler()
  63. self.network=labkeyInterface.labkeyInterface()
  64. fconfig=os.path.join(fhome,'.labkey','network.json')
  65. self.network.init(fconfig)
  66. self.db=labkeyDatabaseBrowser.labkeyDB(self.network)
  67. self.fb=labkeyFileBrowser.labkeyFileBrowser(self.network)
  68. #
  69. # Parameters Area
  70. #
  71. connectionCollapsibleButton = ctk.ctkCollapsibleButton()
  72. connectionCollapsibleButton.text = "Connection"
  73. self.layout.addWidget(connectionCollapsibleButton)
  74. connectionFormLayout = qt.QFormLayout(connectionCollapsibleButton)
  75. self.configDir=os.path.join(os.path.expanduser('~'),".labkey")
  76. self.serverURL=qt.QLineEdit("https://merlin.fmf.uni-lj.si")
  77. #self.serverURL.textChanged.connect(self.updateServerURL)
  78. connectionFormLayout.addRow("Server: ", self.serverURL)
  79. #copy initial setting
  80. #self.updateServerURL(self.serverURL.text);
  81. self.startDir=os.path.join(os.path.expanduser('~'),"temp","crt")
  82. self.userCertButton=qt.QPushButton("Load")
  83. self.userCertButton.toolTip="Load user certificate (crt)"
  84. self.userCertButton.connect('clicked(bool)',self.onUserCertButtonClicked)
  85. connectionFormLayout.addRow("User certificate:",self.userCertButton)
  86. self.privateKeyButton=qt.QPushButton("Load")
  87. self.privateKeyButton.toolTip="Load private key"
  88. self.privateKeyButton.connect('clicked(bool)',\
  89. self.onPrivateKeyButtonClicked)
  90. connectionFormLayout.addRow("Private key:",self.privateKeyButton)
  91. self.caCertButton=qt.QPushButton("Load")
  92. self.caCertButton.toolTip="Load CA certificate (crt)"
  93. self.caCertButton.connect('clicked(bool)',self.onCaCertButtonClicked)
  94. connectionFormLayout.addRow("CA certificate:",self.caCertButton)
  95. self.loadConfigButton=qt.QPushButton("Load configuration")
  96. self.loadConfigButton.toolTip="Load configuration"
  97. self.loadConfigButton.connect('clicked(bool)',\
  98. self.onLoadConfigButtonClicked)
  99. connectionFormLayout.addRow("Configuration:",self.loadConfigButton)
  100. self.loadZipButton=qt.QPushButton("Load certificates (.zip)")
  101. self.loadZipButton.toolTip="Load certificates from zip file"
  102. self.loadZipButton.connect('clicked(bool)',\
  103. self.onLoadZipButtonClicked)
  104. connectionFormLayout.addRow("Load certificates (merlin):",\
  105. self.loadZipButton)
  106. self.saveConfigButton=qt.QPushButton("Save configuration")
  107. self.saveConfigButton.toolTip="Save configuration"
  108. self.saveConfigButton.clicked.connect(self.onSaveConfigButtonClicked)
  109. connectionFormLayout.addRow("Configuration:",self.saveConfigButton)
  110. self.resetConfigButton=qt.QPushButton("Reset configuration")
  111. self.resetConfigButton.toolTip="Reset configuration"
  112. self.resetConfigButton.clicked.connect(self.onResetConfigButtonClicked)
  113. connectionFormLayout.addRow("Configuration:",self.resetConfigButton)
  114. self.initButton=qt.QPushButton("Init")
  115. self.initButton.toolTip="Initialize connection to the server"
  116. self.initButton.connect('clicked(bool)',self.onInitButtonClicked)
  117. connectionFormLayout.addRow("Connection:",self.initButton)
  118. self.authName=qt.QLineEdit("email")
  119. #self.authName.textChanged.connect(self.updateAuthName)
  120. connectionFormLayout.addRow("Labkey username: ", self.authName)
  121. self.authPass=qt.QLineEdit("")
  122. self.authPass.setEchoMode(qt.QLineEdit.Password)
  123. #self.authPass.textChanged.connect(self.updateAuthPass)
  124. connectionFormLayout.addRow("Labkey password: ", self.authPass)
  125. fileDialogCollapsibleButton = ctk.ctkCollapsibleButton()
  126. fileDialogCollapsibleButton.text = "Remote files"
  127. self.layout.addWidget(fileDialogCollapsibleButton)
  128. # Layout within the dummy collapsible button
  129. fileDialogFormLayout = qt.QFormLayout(fileDialogCollapsibleButton)
  130. #add item list for each found file/directory
  131. self.fileList=qt.QListWidget()
  132. self.fileList.toolTip="Select remote file"
  133. self.fileList.itemDoubleClicked.connect(self.onFileListDoubleClicked)
  134. #remote dir is a list
  135. self.currentRemoteDir=[]
  136. #add dummy entry
  137. items=('.','..')
  138. self.populateFileList(items)
  139. fileDialogFormLayout.addWidget(self.fileList)
  140. #add selected file display
  141. self.selectedFile=qt.QLineEdit("")
  142. self.selectedFile.toolTip="Selected file"
  143. fileDialogFormLayout.addRow("Selected file :",self.selectedFile)
  144. #add possible file Content
  145. self.fileTypeSelector=qt.QComboBox()
  146. self.fileTypeSelector.toolTip="Select file type"
  147. items=('VolumeFile','SegmentationFile','TransformFile')
  148. self.populateFileTypeSelector(items)
  149. fileDialogFormLayout.addRow("File type :",self.fileTypeSelector)
  150. self.keepCachedFileCheckBox=qt.QCheckBox("keep cached file")
  151. self.keepCachedFileCheckBox.toolTip="Toggle local storage of labkey files"
  152. self.keepCachedFileCheckBox.setChecked(True)
  153. fileDialogFormLayout.addRow("Manage cache :",self.keepCachedFileCheckBox)
  154. loadFileButton=qt.QPushButton("Load file")
  155. loadFileButton.toolTip="Load file"
  156. loadFileButton.clicked.connect(self.onLoadFileButtonClicked)
  157. fileDialogFormLayout.addRow("Action :",loadFileButton)
  158. loadDirButton=qt.QPushButton("Load directory")
  159. loadDirButton.toolTip="Load directory"
  160. loadDirButton.clicked.connect(self.onLoadDirButtonClicked)
  161. fileDialogFormLayout.addRow("Action :",loadDirButton)
  162. def populateFileList(self,items):
  163. self.fileList.clear()
  164. for it_text in items:
  165. item=qt.QListWidgetItem(self.fileList)
  166. item.setText(it_text)
  167. item.setIcon(qt.QIcon(it_text))
  168. def populateFileTypeSelector(self,items):
  169. for item in items:
  170. self.fileTypeSelector.addItem(item)
  171. def cleanup(self):
  172. pass
  173. def onSelect(self):
  174. self.applyButton.enabled = self.inputSelector.currentNode() and self.outputSelector.currentNode()
  175. def onApplyButton(self):
  176. #logic = labkeySlicerPythonExtensionLogic()
  177. #enableScreenshotsFlag = self.enableScreenshotsFlagCheckBox.checked
  178. #screenshotScaleFactor = int(self.screenshotScaleFactorSliderWidget.value)
  179. print("Run the algorithm")
  180. #logic.run(self.inputSelector.currentNode(), self.outputSelector.currentNode(), enableScreenshotsFlag,screenshotScaleFactor)
  181. def onUserCertButtonClicked(self):
  182. filename=qt.QFileDialog.getOpenFileName(None,'Open user certificate',
  183. self.startDir, '*.crt')
  184. #pwd=qt.QInputDialog.getText(None,'Certificate password',
  185. # 'Enter certificate password',qt.QLineEdit.Password)
  186. if not(filename) :
  187. print("No file selected")
  188. return
  189. f=qt.QFile(filename)
  190. if not (f.open(qt.QIODevice.ReadOnly)) :
  191. print("Could not open file")
  192. return
  193. certList=qt.QSslCertificate.fromPath(filename)
  194. if len(certList) < 1:
  195. print ("Troubles parsing {0}".format(filename))
  196. return
  197. self.logic.cert=qt.QSslCertificate(f)
  198. print("cert.isNull()={0}".format(self.logic.cert.isNull()))
  199. self.userCertButton.setText(filename)
  200. self.authName.setText(self.logic.cert.subjectInfo("emailAddress"))
  201. def onPrivateKeyButtonClicked(self):
  202. filename=qt.QFileDialog.getOpenFileName(None,'Open private key',
  203. self.startDir, '*.key')
  204. if not (filename) :
  205. print ("No file selected")
  206. return
  207. f=qt.QFile(filename)
  208. if not (f.open(qt.QIODevice.ReadOnly)) :
  209. print ("Could not open file")
  210. return
  211. self.pwd=qt.QInputDialog.getText(None,'Private key password',
  212. 'Enter key password',qt.QLineEdit.Password)
  213. self.logic.key=qt.QSslKey(f,qt.QSsl.Rsa,qt.QSsl.Pem,qt.QSsl.PrivateKey,
  214. str(self.pwd))
  215. self.privateKeyButton.setText(filename)
  216. def onCaCertButtonClicked(self):
  217. filename=qt.QFileDialog.getOpenFileName(None,'Open authority certificate',
  218. self.startDir, '*.crt')
  219. if not(filename) :
  220. print("No file selected")
  221. return
  222. f=qt.QFile(filename)
  223. if not (f.open(qt.QIODevice.ReadOnly)) :
  224. print("Could not open file")
  225. return
  226. certList=qt.QSslCertificate.fromPath(filename)
  227. if len(certList) < 1:
  228. print("Troubles parsing {0}".format(filename))
  229. return
  230. self.logic.caCert=qt.QSslCertificate(f)#certList[0]
  231. self.caCertButton.setText(filename)
  232. def onLoadConfigButtonClicked(self):
  233. filename=qt.QFileDialog.getOpenFileName(None,'Open configuration file (JSON)',
  234. self.configDir, '*.json')
  235. self.network.init(filename)
  236. cfg=self.network.connectionConfig
  237. if 'SSL' in cfg:
  238. sslSetup=cfg['SSL']
  239. self.privateKeyButton.setText(sslSetup['key'])
  240. self.userCertButton.setText(sslSetup['user'])
  241. self.caCertButton.setText(sslSetup['ca'])
  242. self.serverURL.setText(cfg['host'])
  243. if 'labkey' in cfg:
  244. labkey=cfg['labkey']
  245. self.authName.setText(labkey['user'])
  246. self.authPass.setText(labkey['password'])
  247. #self.serverURL.setText(self.network.hostname)
  248. #self.authName.setText(self.network.auth_name)
  249. #self.authPass.setText(self.network.auth_pass)
  250. self.loadConfigButton.setText(os.path.basename(filename))
  251. def onLoadZipButtonClicked(self):
  252. filename=qt.QFileDialog.getOpenFileName(\
  253. None,'Open certificate file (zip)',
  254. self.configDir, '*.zip')
  255. zpath=pathlib.Path(filename)
  256. user=zpath.stem
  257. userDir=os.path.join(os.path.expanduser('~'),'.labkey',user)
  258. if not os.path.isdir(userDir):
  259. os.mkdir(userDir)
  260. caName=None
  261. with zipfile.ZipFile(filename,'r') as zipObj:
  262. zipObj.extract(user+'.crt',userDir)
  263. zipObj.extract(user+'.key',userDir)
  264. zipList=zipObj.namelist()
  265. for f in zipList:
  266. if f.find('CA')>-1:
  267. caName=f
  268. zipObj.extract(f,userDir)
  269. self.serverURL.setText('https://merlin.fmf.uni-lj.si')
  270. self.privateKeyButton.setText(os.path.join(userDir,user+'.key'))
  271. self.userCertButton.setText(os.path.join(userDir,user+'.crt'))
  272. self.pwd='notUsed'
  273. self.caCertButton.setText(os.path.join(userDir,caName))
  274. self.authName.setText("guest")
  275. self.authPass.setText("guest")
  276. def onSaveConfigButtonClicked(self):
  277. connectionConfig=self.generateConfig()
  278. fhome=os.path.expanduser('~')
  279. labkeyDir=os.path.join(fhome,".labkey")
  280. if not os.path.isdir(labkeyDir):
  281. os.mkdir(labkeyDir)
  282. fconfig=os.path.join(labkeyDir,'network.json')
  283. with open(fconfig,'w') as f:
  284. json.dump(connectionConfig,f,indent=3)
  285. print("Done")
  286. def generateConfig(self):
  287. connectionConfig={}
  288. #setup SSL
  289. if self.privateKeyButton.text=="Load" or\
  290. self.userCertButton.text=="Load" or\
  291. self.caCertButton.text=="Load":
  292. #no ssl
  293. pass
  294. else:
  295. sslSetup={}
  296. sslSetup['user']=self.userCertButton.text
  297. sslSetup['key']=self.privateKeyButton.text
  298. sslSetup['ca']=self.caCertButton.text
  299. try:
  300. sslSetup['keyPwd']=self.pwd
  301. except AttributeError:
  302. sslSetup['keyPwd']='notUsed'
  303. connectionConfig['SSL']=sslSetup
  304. connectionConfig["host"]=self.serverURL.text
  305. connectionConfig["context"]="labkey"
  306. labkeySetup={}
  307. labkeySetup['user']=self.authName.text
  308. labkeySetup['password']=self.authPass.text
  309. connectionConfig['labkey']=labkeySetup
  310. orthancSetup={}
  311. if self.serverURL.text.find('merlin')>-1:
  312. orthancSetup['server']='https://orthanc.fmf.uni-lj.si'
  313. if self.serverURL.text.find('onko-nix')>-1:
  314. orthancSetup['server']='http://onko-nix.onko-i.si:8042'
  315. orthancSetup['user']='ask'
  316. orthancSetup['password']='askPassword'
  317. connectionConfig['orthanc']=orthancSetup
  318. return connectionConfig
  319. def onResetConfigButtonClicked(self):
  320. self.serverURL.setText('URL')
  321. self.privateKeyButton.setText("Load")
  322. self.userCertButton.setText("Load")
  323. self.caCertButton.setText("Load")
  324. self.authName.setText("labkey username")
  325. self.authPass.setText("password")
  326. def onInitButtonClicked(self):
  327. self.network.connectionConfig=self.generateConfig()
  328. print(self.network.connectionConfig['labkey']['user'])
  329. self.network.initRemote()
  330. remoteId=self.network.getUserId()
  331. if remoteId==None:
  332. self.initButton.setStyleSheet("background-color: red")
  333. else:
  334. if remoteId['email']==self.network.connectionConfig['labkey']['user']:
  335. self.initButton.setStyleSheet("background-color: green")
  336. else:
  337. self.initButton.setStyleSheet("background-color: orange")
  338. #def updateAuthName(self,txt):
  339. #self.network.auth_name=txt
  340. #print("Setting username to {0}".format(self.network.auth_name))
  341. #def updateAuthPass(self,txt):
  342. #self.network.auth_pass=txt
  343. #print("Setting password.")
  344. #def updateServerURL(self,txt):
  345. #self.network.hostname=txt
  346. #print("Setting hostname to {}".format(self.network.hostname))
  347. def onFileListDoubleClicked(self,item):
  348. if item == None:
  349. print("Selected items: None")
  350. return
  351. iText=item.text()
  352. print("Selected items: {0} ".format(iText))
  353. #this is hard -> compose path string from currentRemoteDir and selection
  354. if item.text().find('..')==0:
  355. #one up
  356. try:
  357. self.currentRemoteDir.pop()
  358. except IndexError:
  359. pass
  360. elif item.text().find('.')==0:
  361. pass
  362. else:
  363. self.currentRemoteDir.append(item.text())
  364. print("Listing {}".format(self.currentRemoteDir))
  365. remoteDirString=self.fb.GetRootUrl()
  366. if len(self.currentRemoteDir):
  367. remoteDirString+='/'+'/'.join(self.currentRemoteDir)
  368. ok,lst=self.fb.listRemoteDir(remoteDirString)
  369. flist=[self.fb.baseDir(f) for f in lst]
  370. print("Got")
  371. print(flist)
  372. flist.insert(0,'..')
  373. flist.insert(0,'.')
  374. self.populateFileList(flist)
  375. self.selectedFile.setText(self.currentRemoteDir)
  376. def onLoadFileButtonClicked(self):
  377. properties={}
  378. #local path
  379. tempDir=os.path.join(os.path.expanduser('~'),'temp')
  380. if not os.path.isdir(tempDir):
  381. os.mkdir(tempDir)
  382. localPath=os.path.join(tempDir,self.currentRemoteDir[-1])
  383. print(localPath)
  384. #remote path
  385. remotePath=self.fb.GetRootUrl()+'/'+'/'.join(self.currentRemoteDir)
  386. print(remotePath)
  387. #copy over
  388. self.fb.readFileToFile(remotePath,localPath)
  389. #do slicer magic
  390. slicer.util.loadNodeFromFile(localPath,self.fileTypeSelector.currentText,
  391. properties,returnNode=False)
  392. #if not self.keepCachedFileCheckBox.isChecked():
  393. os.remove(localPath)
  394. def onLoadDirButtonClicked(self):
  395. print('Not implemented')
  396. # labkeySlicerPythonExtensionLogic
  397. #
  398. class labkeyBrowserLogic(ScriptedLoadableModuleLogic):
  399. """This class should implement all the actual
  400. computation done by your module. The interface
  401. should be such that other python code can import
  402. this class and make use of the functionality without
  403. requiring an instance of the Widget.
  404. Uses ScriptedLoadableModuleLogic base class, available at:
  405. https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
  406. """
  407. def __init__(self,parent):
  408. ScriptedLoadableModuleLogic.__init__(self, parent)
  409. self.qnam=qt.QNetworkAccessManager()
  410. def hasImageData(self,volumeNode):
  411. """This is a dummy logic method that
  412. returns true if the passed in volume
  413. node has valid image data
  414. """
  415. if not volumeNode:
  416. print('no volume node')
  417. return False
  418. if volumeNode.GetImageData() == None:
  419. print('no image data')
  420. return False
  421. return True
  422. def takeScreenshot(self,name,description,type=-1):
  423. # show the message even if not taking a screen shot
  424. self.delayDisplay(description)
  425. if self.enableScreenshots == 0:
  426. return
  427. lm = slicer.app.layoutManager()
  428. # switch on the type to get the requested window
  429. widget = 0
  430. if type == slicer.qMRMLScreenShotDialog.FullLayout:
  431. # full layout
  432. widget = lm.viewport()
  433. elif type == slicer.qMRMLScreenShotDialog.ThreeD:
  434. # just the 3D window
  435. widget = lm.threeDWidget(0).threeDView()
  436. elif type == slicer.qMRMLScreenShotDialog.Red:
  437. # red slice window
  438. widget = lm.sliceWidget("Red")
  439. elif type == slicer.qMRMLScreenShotDialog.Yellow:
  440. # yellow slice window
  441. widget = lm.sliceWidget("Yellow")
  442. elif type == slicer.qMRMLScreenShotDialog.Green:
  443. # green slice window
  444. widget = lm.sliceWidget("Green")
  445. else:
  446. # default to using the full window
  447. widget = slicer.util.mainWindow()
  448. # reset the type so that the node is set correctly
  449. type = slicer.qMRMLScreenShotDialog.FullLayout
  450. # grab and convert to vtk image data
  451. qpixMap = qt.QPixmap().grabWidget(widget)
  452. qimage = qpixMap.toImage()
  453. imageData = vtk.vtkImageData()
  454. slicer.qMRMLUtils().qImageToVtkImageData(qimage,imageData)
  455. annotationLogic = slicer.modules.annotations.logic()
  456. annotationLogic.CreateSnapShot(name, description, type, self.screenshotScaleFactor, imageData)
  457. def run(self,inputVolume,outputVolume,enableScreenshots=0,screenshotScaleFactor=1):
  458. """
  459. Run the actual algorithm
  460. """
  461. self.delayDisplay('Running the aglorithm')
  462. self.enableScreenshots = enableScreenshots
  463. self.screenshotScaleFactor = screenshotScaleFactor
  464. self.takeScreenshot('labkeySlicerPythonExtension-Start','Start',-1)
  465. return True
  466. class labkeyBrowserTest(ScriptedLoadableModuleTest):
  467. """
  468. This is the test case for your scripted module.
  469. Uses ScriptedLoadableModuleTest base class, available at:
  470. https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
  471. """
  472. def setUp(self):
  473. """ Do whatever is needed to reset the state - typically a scene clear will be enough.
  474. """
  475. slicer.mrmlScene.Clear(0)
  476. def runTest(self):
  477. """Run as few or as many tests as needed here.
  478. """
  479. self.setUp()
  480. self.test_labkeySlicerPythonExtension1()
  481. def test_labkeyBrowser(self):
  482. """ Ideally you should have several levels of tests. At the lowest level
  483. tests sould exercise the functionality of the logic with different inputs
  484. (both valid and invalid). At higher levels your tests should emulate the
  485. way the user would interact with your code and confirm that it still works
  486. the way you intended.
  487. One of the most important features of the tests is that it should alert other
  488. developers when their changes will have an impact on the behavior of your
  489. module. For example, if a developer removes a feature that you depend on,
  490. your test should break so they know that the feature is needed.
  491. """
  492. self.delayDisplay("Starting the test")
  493. #
  494. # first, get some data
  495. #
  496. import urllib
  497. downloads = (
  498. ('http://slicer.kitware.com/midas3/download?items=5767', 'FA.nrrd', slicer.util.loadVolume),
  499. )
  500. for url,name,loader in downloads:
  501. filePath = slicer.app.temporaryPath + '/' + name
  502. if not os.path.exists(filePath) or os.stat(filePath).st_size == 0:
  503. print('Requesting download %s from %s...\n' % (name, url))
  504. urllib.urlretrieve(url, filePath)
  505. if loader:
  506. print('Loading %s...\n' % (name,))
  507. loader(filePath)
  508. self.delayDisplay('Finished with download and loading\n')
  509. volumeNode = slicer.util.getNode(pattern="FA")
  510. logic = labkeySlicerPythonExtensionLogic()
  511. self.assertTrue( logic.hasImageData(volumeNode) )
  512. self.delayDisplay('Test passed!')
  513. def getHomeDir():
  514. try:
  515. return os.environ['HOME']
  516. except:
  517. fhome=os.environ['HOMEDRIVE']+os.environ['HOMEPATH']
  518. return fhome
  519. def loadLibrary(name):
  520. #load library from git, store it at a default location and return path to the stored location
  521. remoteSources={
  522. "labkeyInterface":\
  523. "http://wiscigt.powertheword.com/labkey/labkeyinterface/-/archive/master/labkeyinterface-master.zip"
  524. }
  525. #two steps:
  526. #1 Download
  527. tempDir=os.path.join(os.path.expanduser('~'),'temp')
  528. if not os.path.isdir(tempDir):
  529. os.mkdir(tempDir)
  530. tempFile=os.path.join(tempDir,name+'.zip')
  531. http = urllib3.PoolManager()
  532. r = http.request('GET', remoteSources[name], preload_content=False)
  533. chunk_size=65536
  534. with open(tempFile, 'wb') as out:
  535. while True:
  536. data = r.read(chunk_size)
  537. if not data:
  538. break
  539. out.write(data)
  540. r.release_conn()
  541. #2 Unzip
  542. installDir=os.path.join(os.path.expanduser('~'),'.labkey','software','src')
  543. if not os.path.isdir(installDir):
  544. os.makedirs(installDir)
  545. with zipfile.ZipFile(tempFile,'r') as zip_ref:
  546. zip_ref.extractall(installDir)
  547. #cleanup
  548. os.remove(tempFile)
  549. zipName=name.lower()+'-master'
  550. os.rename(os.path.join(installDir,zipName),os.path.join(installDir,name))
  551. return os.path.join(installDir,name)