Exemple #1
0
def old_upload(local_path):
    """
    OBSOLETE Upload file to incoming folder.
    :param local_path:
    :return:
    """

    ProxyIP = config_get("ProxyIP")
    ProxyUsername = config_get("ProxyUsername")
    ProxyPassword = config_get("ProxyPassword")
    LORISHostIP = config_get("LORISHostIP")
    LORISHostUsername = config_get("LORISHostUsername")
    LORISHostPassword = config_get("LORISHostPassword")

    Client = LORIS_helper.getProxySSHClient(
        ProxyIP,
        ProxyUsername,
        ProxyPassword,
        LORISHostIP,
        LORISHostUsername,
        LORISHostPassword,
    )

    file_name = os.path.basename(local_path)
    LORIS_helper.uploadThroughClient(Client, "//data/incoming/" + file_name,
                                     local_path)
Exemple #2
0
def check_online_status() -> bool:
    """
    Quck to see if the online connection exist
    :return:
    """

    from DICOMTransit.LORIS.helper import LORIS_helper
    """
    # DNS check vs Google DNS
    host = "http://8.8.8.8"
    port = 53
    timeout = 3
    try:
        socket.setdefaulttimeout(timeout)
        test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
        test_socket.close()
    except:
        return False
    """

    # WWW check vs Google
    import urllib.request

    status_google = urllib.request.urlopen("https://google.com").getcode()
    if not LORIS_helper.is_response(status_google, 200):
        return False

    # WWW check vs CNBP.ca
    status_cnbp = urllib.request.urlopen("http://www.cnbp.ca").getcode()
    if not LORIS_helper.is_response(status_cnbp, 200):
        return False
    else:
        return True
Exemple #3
0
def process_upload_response(response):
    """
    Check the upload response and then try to extract the process ID and UploadID
    :param response:
    :return:
    """

    # Check if it is 403: permission error.
    if LORIS_helper.is_response(response.status_code, 403):
        warning_string = "The credential in the configuration for uploading to LORIS is incorrect, you do not have the credential to upload files!"
        logger.critical(warning_string)
        raise ValueError(warning_string)

    # Check for when the response is properly 200.
    elif LORIS_helper.is_response(response.status_code, 202):

        logger.info("Status Code: 202 received properly.")
        logger.info("Attempting to decode the JSON response:")

        # Convert to JSON.
        json_response = response.json()
        """
        The Keys Will return: 
            MRI upload ID
            Status
            Processes:
        """

        # If there is mri upload ID, return it, other wise, do not return.
        if "processes" in json_response:
            # fixme: should attempt ot extract not only MRI_upload ID but also the process ID to return
            return 0

        elif "mri_upload_id" in json_response:
            upload_id = json_response["mri_upload_id"]
            logger.debug(
                f"Successfully uploaded and server returned 202 with Upload ID of:{upload_id}"
            )
            return upload_id
        else:
            warning_string = "Successfully uploaded and server returned 202, but returned JSON does not contain 'mri_upload_id'"
            logger.error(warning_string)
            raise ValueError(warning_string)

    # other. non 200 response.
    elif not LORIS_helper.is_response(response.status_code, 202):
        warning_string = f"Upload process has returned a non-202 RESPONSE. Status code returned is {response.status_code}"
        logger.critical(warning_string)
        raise ValueError(warning_string)

    else:
        warning_string = "Unanticipated status code condition encountered."
        logger.error(warning_string)
        raise UnboundLocalError(warning_string)
Exemple #4
0
    def login():
        """
        Logs into LORIS using the stored credential. Must use PyCurl as Requests is not working.
        :return: BOOL if or not it is successful. also, the JSON token that is necessary to conduct further transactions.
        """

        from DICOMTransit.settings import config_get

        username = config_get("LORISusername")
        password = config_get("LORISpassword")

        data = json.dumps({"username": username, "password": password})

        # Login URL
        url = config_get("LORISurl")

        if type(url) is furl:
            updated_url = url.url + "login"
        else:
            updated_url = url + "login"

        # requests style login # NOT WORKING!
        r = requests.post(updated_url, data=data)

        logger.debug(str(r.status_code) + r.reason)

        response_json = r.json()

        return LORIS_helper.is_response(r.status_code, 200), response_json.get("token")
Exemple #5
0
    def checkDCCIDExist(token, proposed_DCCID):
        """
        Check if Site/Study already contain the PSCID
        :param token:
        :param proposed_DCCID:
        :return: True/False on if DCCID exist, PSCID if it exist.
        """
        from DICOMTransit.LORIS.validate import LORIS_validation

        logger.debug("Checking if DCCID exist: " + str(proposed_DCCID))

        if not LORIS_validation.validate_DCCID(proposed_DCCID):
            raise ValueError("DCCID is not valid!")

        # @todo: This area has projects/loris dependency. Refactor to enable multiple projects handling.
        response, JSON = LORIS_query.getCNBP(
            token, r"candidates/" + str(proposed_DCCID))
        response_success = LORIS_helper.is_response(response, 200)

        if not response_success:
            logger.error(f"FAILED log response: {str(response)}")
            return response_success, None

        if JSON is not None:  # only try to decode if response is not empty!
            meta = JSON.get("Meta")
            PSCID = meta.get("PSCID")
            return True, PSCID
        else:
            return False, None
Exemple #6
0
def delete_study(StudyUID: str) -> bool:
    """
    API to delete subject from the production Orthanc instance.
    :param StudyUID:
    :return: successful deletion status.
    """
    credential = get_prod_orthanc_credentials()
    reseponse_code, _ = orthanc_query.deleteOrthanc(f"studies/{StudyUID}",
                                                    credential)
    return LORIS_helper.is_response(reseponse_code, 200)
Exemple #7
0
    def test_deleteStudies(self):
        list_subjects = self.test_getStudies()

        patients_url = urllib.parse.urljoin(UT_DevOrthanc.credential.url,
                                            "studies/")

        for subject in list_subjects:
            patient_url = urllib.parse.urljoin(patients_url, f"{subject}")
            reseponse_code, _ = orthanc_query.deleteOrthanc(
                patient_url, self.credential)
            assert LORIS_helper.is_response(reseponse_code, 200)
Exemple #8
0
def get_list_of_subjects_noauth(orthanc_URL: str) -> List[str]:
    """
    Get a list of subjects from a .env predefined orthanc server.
    :return: the lsit of all subjects in the orthanc server
    """
    endpoint = urllib.parse.urljoin(orthanc_URL, "patients/")

    reseponse_code, list_subjects = orthanc_query.getOrthanc_noauth(endpoint)

    if not (LORIS_helper.is_response(reseponse_code, 200)):
        raise ConnectionError("LORIS server did not return list of subjects. ")
    return list_subjects
Exemple #9
0
    def uploadExamples(self):
        file_list = get_testdata_files("[Ss][Mm][Aa][Ll][Ll]")
        for file in file_list:
            print(file)
            upload_files = {"upload_file": open(file, "rb")}
            orthanc_instance_url = urllib.parse.urljoin(
                UT_DevOrthanc.credential.url, "instances")

            status, r = orthanc_query.postOrthanc(orthanc_instance_url,
                                                  UT_DevOrthanc.credential,
                                                  upload_files)
            assert LORIS_helper.is_response(status, 200)
            assert r.json()
Exemple #10
0
def check_prod_orthanc_status() -> bool:
    """
    Check the orthanc status to ensure that it is online.
    :return:
    """
    credential = get_prod_orthanc_credentials()
    try:
        endpoint = urllib.parse.urljoin(credential.url, "studies")
        reseponse_code, _ = orthanc_query.getOrthanc(endpoint, credential)
        success = LORIS_helper.is_response(reseponse_code, 200)
    except:
        # in case any thing goes wrong
        return False
    return success
Exemple #11
0
    def visit_number_extraction(string: str):
        """
        A wrapper for number_extraction by calling it on a string and then return the latest one.
        Used to deal with visitnumber list.
        :param string:
        :return:
        """
        number_extracted = LORIS_helper.number_extraction(string)

        # return last number from the timepoint string: usually it should be V2 or T3 things like that.
        if len(number_extracted) > 1:
            return number_extracted[len(number_extracted) - 1]
        else:
            return number_extracted[0]
Exemple #12
0
    def test_number_extraction(self):
        Prefix = "V"
        numbers = [1, 2, 3, 9, 10, 11, 12, 100, 101, 102]

        timepoints = []

        for number in numbers:
            timepoints.append(Prefix + str(number))

        DualList = zip(numbers, timepoints)

        for tupleItem in DualList:
            assert str(tupleItem[0]) == LORIS_helper.number_extraction(
                tupleItem[1])[0]
Exemple #13
0
    def deleteCandidateCNBP(DCCID, PSCID):
        # @todo: this should really be done through API. But Currently LORIS does not offer such API.
        # NOTE! If you EVER get NULL coalesce not recognized error, make sure that the PHP version being called from
        # the SSH session is 7+ or else. We had a major issue where the PHP version from SSH session being LOWER
        # than the .bashrc profile imported edition. Also keep in mind that EVEN if .bashrc import this, it MOST LIKELY
        # will not apply to the SSH session!

        LORISHostPassword = config_get("LORISHostPassword")
        LORISHostUsername = config_get("LORISHostUsername")
        LORISHostIP = config_get("LORISHostIP")
        DeletionScript = config_get("DeletionScript")

        # NOTE! If you EVER get NULL coalesce not recognized error, make sure that the PHP version being called from
        # the SSH session is 7+ or else. We had a major issue where the PHP version from SSH session being LOWER
        # than the bashrc profile imported edition. Also keep in mind that EVEN if .bashrc import this, it MOST LIKELY
        # will not apply to the SSH session!

        command_string = f"/opt/rh//rh-php70/root/usr/bin/php {DeletionScript} delete_candidate {str(DCCID)} {PSCID} confirm"

        logger.debug(command_string)

        # Establish connection to client.
        Client = LORIS_helper.getProxySSHClient(
            ProxyIP,
            ProxyUsername,
            ProxyPassword,
            LORISHostIP,
            LORISHostUsername,
            LORISHostPassword,
        )

        # Execute the command
        LORIS_helper.triggerCommand(Client, command_string)

        # Close the client.
        Client.close()
Exemple #14
0
def get_all_subject_StudyUIDs(
        credential: orthanc_credential) -> List[List[str]]:
    """
    Get a list of STUDIES from a .env predefined orthanc server.
    :return: the list of all studies in the orthanc server
    """
    endpoint = urllib.parse.urljoin(credential.url, "studies/")

    reseponse_code, list_studies = orthanc_query.getOrthanc(
        endpoint, credential)

    if not LORIS_helper.is_response(reseponse_code, 200):
        raise ConnectionError("LORIS server did not return list of subjects. ")

    return list_studies
Exemple #15
0
    def createCandidate(token, project, birth_date, gender):
        """
        Create a candidate with a provided project information. This assumes that the PSCID and DCCIDs are automaticly assigned!
        :param token
        :param birth_date: Birth date MUST Be in YYYY-MM-DD format!
        :param gender: Gender must be Male or Female!
        :param project:
        :return: DCCID
        """

        logger.debug(f"Creating CNBP Candidates belong to project: {project}")

        Candidate = {}
        from DICOMTransit.LORIS.validate import LORIS_validation

        if not LORIS_validation.validate_birth_date_loris(
                birth_date
        ) or not LORIS_validation.validate_gender(
                gender
        ):  # not LORIS_validation.validate_project(project) or #@todo fix this project validation part during creation.
            logger.error(
                "Non-compliant PSCID component detected. Aborting PSCID creation "
            )
            return False, None

        Candidate["Project"] = project
        Candidate["EDC"] = birth_date
        # Candidate['PSCID'] = proposed_PSCID Now auto sequence.
        Candidate["DoB"] = birth_date
        Candidate["Gender"] = gender
        Candidate["Site"] = config_get("institutionName")

        data = {"Candidate": Candidate}

        data_json = json.dumps(data)

        response_code, response = LORIS_query.postCNBP(token, "candidates/",
                                                       data_json)
        if not LORIS_helper.is_response(response_code, 201):
            return False, None, None
        elif response is not None:  # only try to decode if response is not empty!
            response_json = response.json()
            meta = response_json.get("Meta")
            CandID = meta.get("CandID")
            return True, CandID
        else:
            return False, None
Exemple #16
0
def get_StudyUID_zip(orthanc_URL_with_StudyUID: str,
                     credential: orthanc_credential) -> str:
    """
    Obtain the actual zip files of the subject based on the StudyUID given and unzip them to a temporary folder, and return it.
    :param orthanc_URL_with_StudyUID:
    :return: the temporary folder object which contain the reference to the folder in the .name attribute
    """

    status, local_zip_file_path = orthanc_query.getZipFromOrthanc(
        orthanc_URL_with_StudyUID, credential)
    if not (LORIS_helper.is_response(status, 200)):
        raise ConnectionError("Orthanc is not reachable!")

    if not os.path.exists(local_zip_file_path):
        raise FileNotFoundError(
            "Local zip file to be uploaded has not been found!")

    logger.info("Subject ZIP downloaded.")

    return local_zip_file_path
Exemple #17
0
def new_trigger_insertion(DCCID: int, VisitLabel: str, filename: str,
                          mri_upload_id: int) -> int:
    """
    Trigger the insertion of the subject files and then return the process_id which can be checked later on.
    :param DCCID:
    :param VisitLabel:
    :param filename:
    :param mri_upload_id:
    :return:
    """
    # POST / candidates /$CandID /$VisitLabel / dicoms /$Filename /
    endpoint = f"candidates/{DCCID}/{VisitLabel}/dicoms/{filename}"

    # Get token.
    response_success, token = LORIS_query.login()
    if not response_success:
        raise ConnectionError

    import json

    request_dictionary = {
        "process_type": "mri_upload",
        "Filename": filename,
        "mri_upload_id": mri_upload_id,
    }

    # the request in json format ready for payload.
    request_json = json.dumps(request_dictionary)

    # Post the requests.
    status_code, response = LORIS_query.postCNBP(token, endpoint, request_json)

    process_id = None

    if LORIS_helper.is_response(status_code, 202):
        response_dict = response.json()
        if ("processes" in response_dict
                and "process_id" in response_dict["processes"][0]):
            process_id = int(response_dict["processes"][0]["process_id"])

    return process_id
Exemple #18
0
    def createTimepoint(token, DCCID, time_point) -> bool:
        """
        Create a timepoint of the given DCCID subject based on the timepoint provided.
        :param token:
        :param DCCID:
        :param time_point:
        :return:
        """
        endpoint = r"/candidates/" + str(DCCID) + r"/" + time_point
        MetaData = {
            "CandID": DCCID,
            "Visit": time_point,
            "Site": config_get("institutionName"),
            "Battery": "CNBP",
        }  # default to CNBP for NOW
        Meta = {"Meta": MetaData}
        JSON = json.dumps(Meta)
        status_code, _ = LORIS_query.putCNBP(token, endpoint, JSON)
        success = LORIS_helper.is_response(
            status_code,
            201)  # 201 signify successufl subject timepoint creation!

        # response should be null!
        return success