예제 #1
0
def anonymize_and_upload(R: DicomRegistry, D: DicomDirectory, O: Orthanc):

    for d in R.instances.values():

        ser_mhash = Dixel.from_child(d).mhash
        # Find the real ser
        ser = R.get(ser_mhash, dlvl=DLv.SERIES)

        stu_mhash = Dixel.from_child(d, DLv.STUDY).mhash
        # Find the real stu
        stu = R.get(stu_mhash, dlvl=DLv.STUDY)

        m = orthanc_sham_map(
            stu.mhash,
            stu.dhash,
            # Try patient id first, fall back to patient name, or use "UNKNOWN"
            patient_id=stu.tags.get("PatientID",
                                    stu.tags.get("PatientName", "UNKNOWN")),
            stu_dt=stu.timestamp,
            ser_mhash=ser.mhash,
            ser_dhash=ser.dhash,
            ser_dt=ser.timestamp,
            inst_mhash=d.mhash,
            inst_dhash=d.dhash,
            inst_dt=d.timestamp)

        dd = D.get(d.meta["fp"], binary=True)
        r = O.put(dd)  # If no Patient ID, need to use returned value
        oid = r['ID']
        print(f"Putting {dd.main_tags()} in {oid}")
        O.anonymize(oid,
                    replacement_map=m)  # Anon inst no longer returns image?
        O.delete(oid, dlvl=DLv.INSTANCE)
예제 #2
0
def anon_and_push_all(queue: Orthanc,
                      reg: HashRegistry,
                      archive: Orthanc = None,
                      clear_source: bool = False):

    for oid in queue.inventory():
        anonymize_and_send_w_registry(oid, queue, reg, archive, clear_source)
예제 #3
0
def review_patient_ids(queue: Orthanc):

    for study_oid in queue.inventory():
        study_dx = O.get(study_oid)
        pt_id = best_pt_id(study_dx)
        print("------------------------")
        print(f"Patient ID: {study_dx.tags.get('PatientID')}")
        print(f"Patient Name: {study_dx.tags.get('PatientName')}")
        print(f"Best Patient ID: {pt_id}")
예제 #4
0
def register_path(D: DicomDirectory,
                  H: HashRegistry,
                  O: Orthanc = None,
                  upload: bool = False):

    print(f"Registering path {D.root}")
    tic = time.time()
    m, n, o = 0, 0, 0

    for fn in D.inventory():
        m += 1
        if m % ANNOUNCEMENT_INTERVAL == 0:
            print(f"Checked {m} files")
            H.shelve()
        dx = D.get(fn,
                   binary=True,
                   bhash_validator=lambda h: not H.exists(h),
                   ignore_errors=True)
        if dx is not None:
            if not H.exists(dx.mhash):
                n += 1
                if n % ANNOUNCEMENT_INTERVAL == 0:
                    print(f"Registered {n} files")
                H.put(dx)
                if upload and O is not None:
                    o += 1
                    if o % ANNOUNCEMENT_INTERVAL == 0:
                        print(f"Uploaded {o} files")
                    O.put(dx)

    toc = time.time()
    print(f"----------------------------")
    print(f"Checked {m} files")
    print(f"Registered new {n} instances")
    print(f"Uploaded {o} instances")
    print(f"Elapsed time: {toc-tic:.2f} ({max([n,1])/(toc-tic):.2f}dx/s)")
    print(f"----------------------------")

    H.shelve()

    pprint(H.find(q={"dlvl": DLv.STUDY}))
예제 #5
0
def test_orthanc_upload():

    O = Orthanc()
    O.clear()

    ROOTP = "~/data/dcm/ibis2"
    D = DicomDirectory(ROOTP)

    d = D.get("IM1", binary=True)
    print(d.summary())
    O.put(d)
    g = O.get(d.oid(), dlvl=DLv.INSTANCE)
    Dixel.comparator = CTy.METADATA
    assert d == g

    e = Dixel.from_child(d)
    h = O.get(e.oid(), dlvl=DLv.SERIES)
    assert e == h

    f = Dixel.from_child(e)
    i = O.get(f.oid(), dlvl=DLv.STUDY)
    assert f == i
예제 #6
0
def test_orthanc_status():
    O = Orthanc()
    assert (O.status())
예제 #7
0
def anonymize_and_send_w_registry(study_oid: str,
                                  O: Orthanc,
                                  H: HashRegistry,
                                  P: Orthanc = None,
                                  clear_source: bool = False):

    tic = time.time()
    n = 0

    if P is None:
        P = O  # Stash result in-place

    study_dx = O.get(study_oid)
    print(f"Processing study {study_oid}")

    try:
        study_dx.dhash = H.get(study_dx.mhash)["dhash"]
    except KeyError as e:
        print(e)
        print("Failed to anonymize study, this is a serious error")
        print(study_dx)
        return

    study_info = O.get(study_oid, view="raw")
    # new_inst_info = None
    for ser_oid in study_info["Series"]:
        ser_dx = O.get(ser_oid, dlvl=DLv.SERIES)
        print(f"Processing series {ser_oid}")

        try:
            ser_dx.dhash = H.get(ser_dx.mhash)["dhash"]
        except KeyError as e:
            print(e)
            print("Failed to anonymize series, possibly no pixel data?")
            print(ser_dx)
            continue

        ser_info = O.get(ser_oid, dlvl=DLv.SERIES, view="raw")
        for inst_oid in ser_info["Instances"]:
            n += 1
            if n % ANNOUNCEMENT_INTERVAL == 0:
                print(f"Processed {n} instances")
                H.shelve()

            inst_dx = O.get(inst_oid, dlvl=DLv.INSTANCE)
            inst_dx.dhash = H.get(inst_dx.mhash)["dhash"]

            m = orthanc_sham_map(stu_mhash=study_dx.mhash,
                                 stu_dhash=study_dx.dhash,
                                 patient_id=best_pt_id(study_dx),
                                 stu_dt=study_dx.timestamp,
                                 ser_mhash=ser_dx.mhash,
                                 ser_dhash=ser_dx.dhash,
                                 ser_dt=ser_dx.timestamp,
                                 inst_mhash=inst_dx.mhash,
                                 inst_dhash=inst_dx.dhash,
                                 inst_dt=inst_dx.timestamp)

            s = [
                m["Replace"]["PatientID"], m["Replace"]["StudyInstanceUID"],
                m["Replace"]["SeriesInstanceUID"],
                m["Replace"]["SOPInstanceUID"]
            ]
            expected_oid = oid_from(s)

            # TODO: Prefer to check this in put??
            # if H.exists(expected_oid):
            #     # print("Skipping existing")
            #     continue

            bin = O.anonymize(
                inst_oid, dlvl=DLv.INSTANCE,
                replacement_map=m)  # Anon inst no longer returns image?
            new_bhash = hashlib.sha224(bin).hexdigest()
            new_inst_info = P.put(raw=bin)
            new_inst = P.get(new_inst_info["ID"], dlvl=DLv.INSTANCE)
            new_inst.bhash = new_bhash
            new_inst.dhash = inst_dx.dhash
            # P.put_metadata(new_inst.oid(), DLv.INSTANCE, "diana-hash", new_inst.dhash)
            # if new_inst is not None:
            #     H.get(inst_dx.mhash)["ShamAccNum"] = m["Replace"]["AccessionNumber"]
            # H.put(new_inst, link_duplicates=True)
            # H.set(new_inst.oid(), new_inst.mhash)
            if clear_source:
                O.delete(inst_oid, dlvl=DLv.INSTANCE)
        # if new_inst_info is not None:
        # new_ser = P.get(new_inst_info["ParentSeries"])
        # H.set(new_ser.oid(), new_ser.mhash)
        # H.get(ser_dx.mhash)["ShamAccNum"] = m["Replace"]["AccessionNumber"]
        # P.put_metadata(new_ser.oid(), DLv.SERIES, "diana-hash", ser_dx.dhash)
        # H.link(new_ser.mhash, ser_dx.mhash)
    # if new_inst_info is not None:
    #     H.get(study_dx.mhash)["ShamAccNum"] = m["Replace"]["AccessionNumber"]

    # new_stu = P.get(new_inst_info["ParentStudy"])
    # H.set(new_stu.oid(), new_stu.mhash)
    # # P.put_metadata(new_stu.oid(), DLv.STUDY, "diana-hash", study_dx.dhash)
    # H.link(new_stu.mhash, study_dx.mhash)

    toc = time.time()
    print(f"----------------------------")
    print(f"Uploaded {n} files")
    print(f"Elapsed time: {toc-tic:.2f} ({max([n,1])/(toc-tic):.2f}dx/s)")
    print(f"----------------------------")

    H.shelve()
예제 #8
0
                      archive: Orthanc = None,
                      clear_source: bool = False):

    for oid in queue.inventory():
        anonymize_and_send_w_registry(oid, queue, reg, archive, clear_source)


def review_patient_ids(queue: Orthanc):

    for study_oid in queue.inventory():
        study_dx = O.get(study_oid)
        pt_id = best_pt_id(study_dx)
        print("------------------------")
        print(f"Patient ID: {study_dx.tags.get('PatientID')}")
        print(f"Patient Name: {study_dx.tags.get('PatientName')}")
        print(f"Best Patient ID: {pt_id}")


if __name__ == "__main__":

    O = Orthanc(url=ORTHANC_QUEUE_URL)
    P = Orthanc(url=ORTHANC_PEER_URL)
    if CLEAR_TARGET:
        input("Are you sure that you want to clear the target archive?")
        P.clear()
    H = HashRegistry(cache_file=CACHE_FILE)
    # anonymize_and_send_w_registry(STUDY_OID, O, H, P, clear_source=CLEAR_SOURCE)

    anon_and_push_all(O, H, P, clear_source=CLEAR_SOURCE)
    # review_patient_ids(O)
예제 #9
0
                    print(f"Registered {n} files")
                H.put(dx)
                if upload and O is not None:
                    o += 1
                    if o % ANNOUNCEMENT_INTERVAL == 0:
                        print(f"Uploaded {o} files")
                    O.put(dx)

    toc = time.time()
    print(f"----------------------------")
    print(f"Checked {m} files")
    print(f"Registered new {n} instances")
    print(f"Uploaded {o} instances")
    print(f"Elapsed time: {toc-tic:.2f} ({max([n,1])/(toc-tic):.2f}dx/s)")
    print(f"----------------------------")

    H.shelve()

    pprint(H.find(q={"dlvl": DLv.STUDY}))


if __name__ == "__main__":

    D = DicomDirectory(root=ROOT_PATH)
    H = HashRegistry(clear_cache=CLEAR_HASHES, cache_file=CACHE_FILE)
    O = Orthanc(url=ORTHANC_URL)
    if CLEAR_DICOM:
        input("Are you sure that you want to clear the queue?")
        O.clear()
    register_path(D, H, O, upload=UPLOAD_DICOM)
예제 #10
0
        r = O.put(dd)  # If no Patient ID, need to use returned value
        oid = r['ID']
        print(f"Putting {dd.main_tags()} in {oid}")
        O.anonymize(oid,
                    replacement_map=m)  # Anon inst no longer returns image?
        O.delete(oid, dlvl=DLv.INSTANCE)


if __name__ == "__main__":

    ROOT_PATH = "~/data/incoming"
    R = DicomRegistry(shelf_reset=False)
    if UPDATE_CACHE:
        R.index_directory(rootp=ROOT_PATH)  # This gets cached

    # print("\nSERIES")
    # print("-----------------")
    # pprint(R.find({"dlvl": DLv.SERIES}))
    #
    # print("\nSTUDIES")
    # print("-----------------")
    # pprint(R.find({"dlvl": DLv.STUDY}))

    O = Orthanc(url="http://siren:8042")
    print(O.statistics())
    O.clear()
    print(O.statistics())

    D = DicomDirectory(root=ROOT_PATH)
    anonymize_and_upload(R, D, O)
예제 #11
0
    ORTHANC_URL  = "http://queue:8042"
    CACHE_FILE   = "/data/tmp/hashes.pkl"
else:
    # siren-staging
    ROOT_PATH    = "/data/incoming"
    ORTHANC_URL  = "http://queue-s:8042"
    CACHE_FILE   = "/data/tmp/hashes-s.pkl"


if __name__ == "__main__":

    logging.basicConfig(level=logging.DEBUG)

    D = ObservableDicomDir(root=ROOT_PATH)
    H = HashRegistry(cache_file=CACHE_FILE)
    Q = Orthanc(url=ORTHANC_URL)

    def handle_file(event: Event, source: ObservableDicomDir):
        logging.debug(event)
        fp = event.data.get("fp")
        dx = source.get(fp,
                   # bhash_validator=lambda x: not H.exists,
                   binary=True,
                   ignore_errors=True)
        if dx is not None:
            logging.debug(f"putting {dx}")
            H.put(dx)
            H.shelve()
            if UPLOAD_DICOM and Q is not None:
                Q.put(dx)