- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# C:/AngioLocalizeNoAuto/MevisLabNoAutoReg/STUMevisApp/Angiolocalize/Modules/Macros/STUDSA3D/DSA3D.py

    00001 """
    00002 * Copyright (c) 2009 Stanford University, School of Medicine All rights reserved.
    00003 *
    00004 * STANFORD ACADEMIC SOFTWARE LICENSE AGREEMENT
    00005 * FOR AngioLocalize SOURCE CODE:
    00006 *
    00007 * 1.  This is a legal agreement between you, RECIPIENT, and STANFORD UNIVERSITY.
    00008 *       By accepting, receiving, and using AngioLocalize.including any accompanying information, materials or
    00009 *       manuals (Program), you are agreeing to be bound by the terms of this Agreement.
    00010 *       If you do not agree to the terms of this Agreement, promptly return the Program to the STANFORD.
    00011
    00012 * 2.  STANFORD grants to RECIPIENT a royalty-free, nonexclusive, and nontransferable license to use the Program
    00013 *       and accompanying source code furnished hereunder, upon the terms and conditions set out below.
    00014 *       documentation and/or other materials provided with the distribution.
    00015 * 3.  RECIPIENT acknowledges that the Program is a research tool still in the development stage and that
    00016 *       it is being supplied as is, without any accompanying services, support or improvements from STANFORD.
    00017 * 4.  RECIPIENT agrees to use the Program solely for internal non-commercial purposes.
    00018 * 5.  RECIPIENT may create derivatives and further transfer the Program under the following terms and conditions:
    00019 *        A) Recipient agrees to not commercially exploit the Program and agrees all uses will be for non-commercial purposes; and,
    00020 *        B) Recipient may not mark any derivatives with the title of Program and may not to use iPad mark for any derivatives; and,
    00021 *        C) Recipient agrees to mark and acknowledge all derivatives as follows: "This is a derivative work based on AngioLocalize:
    00022 *           Frameless AVM localization with 2D Digital Subtraction Angiography (DSA) and 3D Rotational Angiography (DRA) Images developed
    00023 *           by Dimitre Hristov, Lina Liu.
    00024 *        D) Recipient agrees to make all improvements, enhancements and derivatives available under
    00025 *           similar terms and conditions to the research community.
    00026 * 6.   RECIPIENT warrants that RECIPIENT will not remove or export any part of the software or Program from the United
    00027 *       States except in full compliance with all United States and other applicable laws and regulations.
    00028 * 7.  RECIPIENT will use the Program in compliance with all applicable laws, policies and regulations including, but not
    00029 *       limited to, any approvals, informed consent and patient confidentiality principles.
    00030 * 8.   RECIPIENT will indemnify, hold harmless, and defend Stanford against any claim of any kind arising out of or
    00031 *       related to the exercise of any rights granted under this Agreement or the breach of this Agreement by RECIPIENT.
    00032 * 9.  Title and copyright to the Program and any associated documentation shall at all times remain with STANFORD,
    00033 *       and RECIPIENT agrees to preserve same.
    00034 """
    00035 #----------------------------------------------------------------------------------
    00036 #! Macro module DSA3D
    00037 #/*!
    00038 # \file    DSA3D.py
    00039 # \author  Lina Liu and Dimitre Hristov
    00040 # \date    2009-12-10
    00041 #
    00042 #
    00043 #*/
    00044 #----------------------------------------------------------------------------------
    00045
    00046 from mevis import *
    00047 from PythonQt import *
    00048 import time;
    00049
    00050
    00051 regContent = "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1";
    00052 ## initiate the main window
    00053 def initWindow():
    00054   ctx.field("PatientID").setValue(ctx.parent().field("PatientID").value);
    00055   ctx.field("PatientsName").setValue(ctx.parent().field("PatientsName").value);
    00056   ctx.field("PatientsBirthDate").setValue(ctx.parent().field("PatientsBirthDate").value);
    00057   ctx.field("PatientsSex").setValue(ctx.parent().field("PatientsSex").value);
    00058   ctx.field("OpenImage.dicomBrowser.reload").touch();
    00059   ctx.field("OpenImage.previewLoad.autoLoad").touch();
    00060   ctx.field("OpenImage.imgLoad.autoLoad").touch();
    00061
    00062 ## send a query to the Database and return the result set
    00063 def sendQuery(query):
    00064   ctx.field("DBConn.Statement").setValue(query);
    00065   dbModule = ctx.module("DBConn");
    00066   result = dbModule.call("sendQuery");
    00067   if (result == -1):
    00068     MLAB.logError("The following query to database failed. \n" + query + "\n.");
    00069   dbModule.call("close");
    00070   return result;
    00071
    00072 ## when the selected image has been changed
    00073 def newImageName():
    00074    ctx.field("DicomTagModify.tagName0").value = "PatientsName";
    00075    ctx.field("DicomTagModify.tagName1").value = "PatientsBirthDate";
    00076    ctx.field("DicomTagModify.tagName2").value = "PatientID";
    00077    ctx.field("DicomTagModify.tagName3").value = "PatientsSex";
    00078    ctx.field("DicomTagModify.tagName4").setValue("SeriesDescription");
    00079    ctx.field("DicomTagModify.tagName5").setValue("Modality");
    00080    ctx.field("DicomTagModify.getValues").touch();
    00081    PatientN = ctx.field("DicomTagModify.tagValue0").value;
    00082    PatientDOB = ctx.field("DicomTagModify.tagValue1").value;
    00083    ID = ctx.field("DicomTagModify.tagValue2").value;
    00084    Sex = ctx.field("DicomTagModify.tagValue3").value;
    00085    if PatientN != ctx.field("PatientsName").value or PatientDOB != ctx.field("PatientsBirthDate").value or ID != ctx.field("PatientID").value or Sex != ctx.field("PatientsSex").value:
    00086      details = "";
    00087      if PatientN != ctx.field("PatientsName").value:
    00088        details += "<br>PatientName in Dicom:<b>" + PatientN + "</b> versus <b>" +  ctx.field("PatientsName").value + "</b> in records.\n";
    00089      if PatientDOB != ctx.field("PatientsBirthDate").value:
    00090        details +="<br>PatientBirthDate in Dicom:<b>" + PatientDOB + "</b> versus <b>" +  ctx.field("PatientsBirthDate").value + "</b> in records.\n"
    00091      if ID != ctx.field("PatientID").value:
    00092        details += "<br>PatientID in Dicom:<b>" + ID + "</b> versus <b>" +  ctx.field("PatientID").value + "</b> in records.\n";
    00093      if Sex != ctx.field("PatientsSex").value:
    00094        details += "<br>PatientSex in Dicom:<b>" + Sex + "</b> versus <b>" +  ctx.field("PatientsSex").value + "</b> in records.\n";
    00095      answer = MLAB.showQuestion("The DICOM image info does not match patient's record. Do you want to replace the DICOM tags with patient's info in record?", details, "MeVisLab", ["OK", "Cancel"], 0);
    00096      if answer == 1:
    00097        ##if the user wants to cancel in case that the records do not match
    00098        msg = "The user canceled the operation since the patient record did not match that in database. The patient information in DICOM remains as follows:";
    00099        msg =+ "Patient Name:" + PatientN + "  DOB: " + PatientDOB + "  ID:" + ID + "  Sex:" + Sex;
    00100        MLAB.log(msg);
    00101        return;
    00102      else:
    00103      ## save the Dicom Tag data into the image
    00104        ctx.field("DicomTagModify.tagValue0").value = ctx.field("PatientsName").value;
    00105        ctx.field("DicomTagModify.tagValue1").value = ctx.field("PatientsBirthDate").value;
    00106        ctx.field("DicomTagModify.tagValue2").value = ctx.field("PatientID").value;
    00107        ctx.field("DicomTagModify.tagValue3").value = ctx.field("PatientsSex").value;
    00108        ctx.field("DicomTagModify.apply").touch();
    00109        ctx.field("DicomTagModify.tagValue0").value = ctx.field("PatientsName").value;
    00110        ctx.field("DicomTagModify.tagValue1").value = ctx.field("PatientsBirthDate").value;
    00111        ctx.field("DicomTagModify.tagValue2").value = ctx.field("PatientID").value;
    00112        ctx.field("DicomTagModify.tagValue3").value = ctx.field("PatientsSex").value;
    00113        ctx.field("DicomTagModify.apply").touch();
    00114        msg = "The user replaced the patient information in DICOM image with that in database\n";
    00115        msg += "Patient information saved into DICOM are as follows:\n";
    00116        msg += "Patient Name:" +  ctx.field("PatientsName").value;
    00117        msg += "\nPatient Birth Date:" + ctx.field("PatientsBirthDate").value;
    00118        msg += "\nPatient ID:" + ctx.field("PatientID").value;
    00119        msg += "\nPatient Sex:" + ctx.field("PatientsSex").value;
    00120        MLAB.log(msg);
    00121    if ctx.field("Info.sizeT").value < 2:
    00122      ## we have a image with one time point
    00123     ctx.connectField("SetPageExt2.input0", "DicomTagModify.output0");
    00124     wind = ctx.showWindow("SaveImageW");
    00125     title = "Patient: " + ctx.field("PatientsName").value + "   with MRO: " + ctx.field("PatientID").value + " DOB: " + ctx.field("PatientsBirthDate").value + " " + ctx.field("PatientsSex").value;
    00126     wind.setTitle(title);
    00127     wind.showMaximized();
    00128    else:
    00129     ctx.connectField("SetPageExt.input0", "DicomTagModify.output0");
    00130     ctx.connectField("SetPageExt1.input0", "DicomTagModify.output0");
    00131     ctx.field("Subimage.fullSize").touch();
    00132     ctx.field("Subimage.st").value=1;
    00133     ctx.field("Subimage.t").value=0;
    00134     ctx.field("Subimage1.fullSize").touch();
    00135     ctx.field("Subimage1.t").value=1;
    00136     ctx.field("Subimage1.st").value=1;
    00137     ctx.field("Subimage1.apply").touch();
    00138     ctx.field("Subimage.apply").touch();
    00139
    00140     ctx.field("AngioRegManual.reset").touch();
    00141     ctx.field("AngioRegManual.interactive").setBoolValue(False);
    00142     wind = ctx.showWindow("RegistrationManualW");
    00143     title = "Patient: " + ctx.field("PatientsName").value + "   with MRO: " + ctx.field("PatientID").value + " DOB: " + ctx.field("PatientsBirthDate").value + " " + ctx.field("PatientsSex").value;
    00144     wind.setTitle(title);
    00145     wind.showMaximized();
    00146
    00147 ## save the image data to a file
    00148 def saveToFile(type):
    00149   imageName = saveImageToFile(ctx.parent().field("PatientID").value, getFileName(),type);
    00150   ## we use the format: "patientID(time).dcm" as unique name for the image
    00151   if type == "/Src":
    00152     ctx.field("ImgSave1.filename").value =   imageName;
    00153     ctx.field("MinMaxScan1.update").touch();
    00154     ctx.field("ImgSave1.save").touch();
    00155   elif type == "/Target":
    00156     ctx.field("ImgSave.filename").value =  imageName;
    00157     ctx.field("MinMaxScan.update").touch();
    00158     ctx.field("ImgSave.save").touch();
    00159   else:
    00160     ctx.field("ImgSave2.filename").value =  imageName;
    00161     ctx.field("ImgSave2.save").touch();
    00162   MLAB.log("The image:" + imageName + " has been saved to the file system.");
    00163   return  imageName;
    00164
    00165 ## Get the inverse matrix so that we can save the inverse pair of the registered images in DB
    00166 def getInversedM(regMatrix):
    00167   ctx.field("MatrixArithmetic.matrixA").setStringValue(regMatrix);
    00168   ctx.field("MatrixArithmetic.operation").setStringValue("Inverse");
    00169   return ctx.field("MatrixArithmetic.outputMatrixC").stringValue();
    00170
    00171 ## save the image data into DB and return the record ID in DB
    00172 def saveToDB(dir, imageType, patientID, seriesDescr, modality):
    00173   queryString = "insert into images(imagetype, modality, seriesDescr, imageName,patientID) values(";
    00174   queryString = queryString + str(imageType) + ", '" + modality + "','" + seriesDescr + "', '" + dir + "'," + str(patientID) + ");";
    00175   result = sendQuery(queryString);
    00176   queryString = "SELECT ImageID AS ImgID FROM Images where imageName = '" + dir +"';";
    00177   result = sendQuery(queryString);
    00178   imgID = None;
    00179   for item in result:
    00180     imgID = item["imgid"];
    00181   MLAB.log("The image: " + dir + " has been saved to the DB as record No." + str(imgID));
    00182   return imgID;
    00183
    00184 ## save the regisration in DB
    00185 def saveReg(insertOp, srcID, targetID, status, regS):
    00186  saveRegToFile(regS, srcID, targetID, ctx.parent().field("PatientID").value);
    00187  if (insertOp == 1):
    00188    queryS = "INSERT INTO REGMATRICES(srcImage, targetImage, affineM, status, type)values(" + str(srcID) + "," + str(targetID) + ",'" + regS + "'" + "," + str(status) + ", 0" + ");";
    00189  else:
    00190    queryS = "UPDATE REGMATRICES set affineM = " + "'" + regS + "'" + " where srcImage = " + str(srcID) + " AND targetImage = " + str(targetID) + ";";
    00191  result = sendQuery(queryS);
    00192  if (result == -1):
    00193    return;
    00194  query = "select matrixID from regmatrices where srcImage = " + str(srcID) + " and targetImage = " + str(targetID) + ";";
    00195  result = sendQuery(query);
    00196  if (result == ""):
    00197    return;
    00198  imgID = None;
    00199  for item in result:
    00200     imgID = item["matrixid"];
    00201  return imgID;
    00202
    00203 ## check the DB see if the registration already exists. We only allow one registration for a unique source and target image pair
    00204 def regExist(srcID, targetID):
    00205   queryString = "SELECT matrixID as Num, affineM FROM REGMATRICES WHERE srcImage = " + str(srcID) + " AND type = 0 AND targetImage = " + str(targetID) + ";";
    00206   result = sendQuery(queryString);
    00207   if (str(result) == "()"):
    00208     return;
    00209   number = 0;
    00210   number = result[0]["Num"];
    00211   global regMatrix;
    00212   regMatrix = result[0]["affineM"];
    00213   return number;
    00214
    00215 ## propagate the registration.
    00216 def propagate(targetID, srcID):
    00217   queryString = "SELECT targetImage, affineM , approvalStatus, status FROM REGMATRICES, approvals WHERE objID = matrixID and srcImage = " + str(targetID) + " AND type = 0 " + ";";
    00218   result = sendQuery(queryString);
    00219   newTarget = 0;
    00220   for item in result:
    00221     newTarget = item["targetimage"];
    00222     oldApprovalS = item["approvalstatus"];
    00223     if (int(newTarget) == int(srcID)):
    00224       continue;
    00225     Affine = item["affinem"];
    00226     if (newTarget != 0):
    00227       insertOp = 0;
    00228       status = 1; # inferred stsatus
    00229       regS = Affine.replace("\n", " ");
    00230       if (regExist(srcID, newTarget) == 0):
    00231          insertOp = 1;
    00232       regID = saveReg(insertOp, srcID, newTarget, status, regS);
    00233       saveApprovalStatus(regID, oldApprovalS, insertOp);
    00234       saveRegToFile(regS, srcID, newTarget, ctx.parent().field("PatientID").value);
    00235        ## update the DB now, find the inverse of the reg
    00236       inverseM = getInversedM(Affine);
    00237       regS = inverseM.replace("\n", " ");
    00238       status = 1; # inferred status for inversed reg
    00239       regID = saveReg(insertOp, newTarget, srcID, status, regS);
    00240       saveApprovalStatus(regID, oldApprovalS, insertOp);
    00241       saveRegToFile(regS, newTarget, srcID, ctx.parent().field("PatientID").value);
    00242
    00243 ## save the Approval status of a registration
    00244 def saveApprovalStatus(imgID, status, insertOp):
    00245  if (insertOp == 0):
    00246    queryS = "Update APPROVALS SET approvalStatus = " + status + " where UserID = 1 AND objType = 0 AND objID = " + str(imgID) + ";";
    00247  else:
    00248    queryS = "INSERT INTO APPROVALS(userID, objID, objType, patientID, approvalStatus)VALUES(1," + str(imgID) + ", 0 , " + getPatientRecordID() + " , " + status + ");";
    00249  result = sendQuery(queryS);
    00250  MLAB.log("The data of :" + str(imgID) + " has been saved.");
    00251
    00252 ## The function is called when the user clicks OK on RegManual window
    00253 def clickOKonRegManual():
    00254   ##save the image files
    00255   global regContent;
    00256   srcDir = saveToFile("/Src");
    00257   tgtDir = saveToFile("/Target");
    00258
    00259   ##save the target and src image
    00260   ##here we need to save the image to DB
    00261   ## imagetype: 1--2D, 2--3D
    00262   patientRecID = getPatientRecordID();
    00263   imageType = 2;
    00264   seriesDescr = ctx.field("DicomTagModify.tagValue4").value;
    00265   modality = ctx.field("DicomTagModify.tagValue5").value;
    00266   filename =  getFileName();
    00267   srcDir = srcDir.replace("\\","/");
    00268   tgtDir = tgtDir.replace("\\","/");
    00269   srcID = saveToDB(srcDir,imageType, patientRecID, seriesDescr, modality);
    00270   destID = saveToDB(tgtDir,imageType, patientRecID, seriesDescr, modality);
    00271
    00272   saveRegMatrixInDB(srcID, destID);
    00273   saveRegToFile(regContent, srcID, destID, ctx.parent().field("PatientID").value);
    00274   saveRegMatrixInDB(destID, srcID);
    00275   saveRegToFile(regContent, destID, srcID, ctx.parent().field("PatientID").value);
    00276   propagate(destID, srcID);
    00277   ctx.disconnectField("SetPageExt.input0");
    00278   ctx.disconnectField("SetPageExt1.input0");
    00279   MLAB.log("The user review the image: " + filename + " and saved it into " + srcDir + " and " + tgtDir);
    00280   ctx.window().close();
    00281
    00282 ## The get the formated file Name: MRI (time)
    00283 def getFileName():
    00284   return  ctx.parent().field("PatientID").value + "(" + time.strftime("%Y%m%d-%H%M%S") + ")";
    00285
    00286 ## This function is called when user clicks cancel button in RegManual Window
    00287 ## It disconnect the image inputs from SetPageExt and SetPageExt2 and close the window
    00288 def clickCancelonRegManual():
    00289   MLAB.log("The user reviewed the image and canceled.");
    00290   ctx.disconnectField("SetPageExt.input0");
    00291   ctx.disconnectField("SetPageExt1.input0");
    00292   ctx.window().close();
    00293
    00294 ## get the PatientRecordID
    00295 def getPatientRecordID():
    00296   patientID = 0;
    00297   if (ctx.parent().field("PatientID").value == ""):
    00298     return str(patientID);
    00299   queryString = "SELECT PatientID FROM Patients WHERE MRO = " + "'" + ctx.parent().field("PatientID").value + "'";
    00300   result = sendQuery(queryString);
    00301   for item in result:
    00302     patientID = item["patientid"];
    00303   return str(patientID);
    00304
    00305 ## save the Registration matrix in a database
    00306 def saveRegMatrixInDB(srcImage, destImage):
    00307   queryString = "INSERT INTO REGMATRICES (affineM, srcImage, targetImage, status, type) VALUES (";
    00308   queryString = queryString + "'" + regContent + "'," + str (srcImage) +  "," + str(destImage) + "," + "0, 0" + ");";
    00309 #  print "regQuerystring:" + queryString
    00310   result = sendQuery(queryString);
    00311   if (result == -1):
    00312     return;
    00313   queryString = "SELECT matrixID from regmatrices where srcImage = " + str(srcImage) + " and targetImage = " + str(destImage) + ";";
    00314   result = sendQuery(queryString);
    00315   if (str(result) == "()"):
    00316     return;
    00317   matrixID = None;
    00318   for item in result:
    00319     matrixID = item["matrixid"];
    00320
    00321   queryString = "INSERT INTO Approvals(UserID, objID, patientID, objType, approvalStatus) values(1," + str(matrixID) + "," + getPatientRecordID() + ",0, 1);"
    00322   result = sendQuery(queryString);
    00323
    00324 ## The function is called when user clicks OK on save Image
    00325 def clickOKonSaveImg():
    00326   #save the image files
    00327   # we temporarily hardcode the directory c:/MLabUserData here, we need to retrive it from config file later
    00328   saveDir = saveToFile("");
    00329   patientRecID = getPatientRecordID();
    00330   seriesDescr = ctx.field("DicomTagModify.tagValue4").value;
    00331   modality = ctx.field("DicomTagModify.tagValue5").value;
    00332   filename = getFileName();
    00333   saveDir = saveDir.replace("\\","/");
    00334   srcID = saveToDB(saveDir, 2, patientRecID, seriesDescr, modality);
    00335   MLAB.log("The user review the image: " + filename + " and saved it into " + saveDir);
    00336   ctx.disconnectField("SetPageExt2.input0");
    00337   ctx.window().close();
    00338
    00339 ## The function is called when click Cencel on Save Image
    00340 def clickCancelonSaveImg():
    00341   MLAB.log("The user reviewed the image and canceled.");
    00342   ctx.disconnectField("SetPageExt2.input0");
    00343   ctx.window().close();
    00344
    00345 ## test Interactive
    00346 def testInteractive():
    00347   if (ctx.field("AngioRegManual.interactive").value == True):
    00348     ctx.disconnectField("Arithmetic2.input1");
    00349     return;
    00350   ctx.connectField("Arithmetic2.input1","AngioRegManual.outReformatImage");
    00351
    00352 ## call back function for field "no Subtraction"
    00353 def testSubtraction():
    00354   ctx.disconnectField("OrthoView2D.image");
    00355   ctx.disconnectField("MinMaxScan1.input0");
    00356   if (ctx.field("AngioRegManual.nosubtraction").value == True):
    00357     ctx.connectField("MinMaxScan1.input0", "Subimage1.output0");
    00358     ctx.connectField("OrthoView2D.image", "Subimage1.output0");
    00359   else:
    00360     ctx.connectField("MinMaxScan1.input0", "Arithmetic2.output0");
    00361     ctx.connectField("OrthoView2D.image", "Arithmetic2.output0");
    00362
    00363 ## help
    00364 def help():
    00365   ctx.showHtmlHelp();
    00366
    00367 ## clean UP the DSA3D
    00368 def cleanUp():
    00369   ctx.field("OpenImage.previewLoad.close").touch();
    00370   ctx.field("OpenImage.imgLoad.close").touch();
    00371
    00372
    00373 #//# MeVis signature v1
    00374 #//# key: MFowDQYJKoZIhvcNAQEBBQADSQAwRgJBANEfsmYse2e1dRhkQ9AQbreCq9uxwzWLoGom13MNYmyfwoJqQOEXljLFAgw2eEjaT12G4CdqKWhRxh9ANP6n7GMCARE=:VI/mB8bT4u+mRtf/ru8yUQi8BzpaS3UeL2x62YxsUYnVqCWuLrVNLiukIIjnJMKQXlc8ezmgOIcVAV7pgvgKpQ==
    00375 #//# owner: MeVis
    00376 #//# date: 2009-06-10T04:12:25
    00377 #//# hash: vHSfj+Qt8xrIkDVP4W0Rep0YH6a3+MySa0+Cs+AoqEK/IbB+f5szwmyVTENOjzz/JEgm2t31FtHmUUMFcQg5VQ==
    00378 #//# MeVis end
    00379

All Classes Namespaces Files Functions Variables Enumerator Friends