<commit_before># @author:  <NAME>
#           <NAME>

"""
SCU is a module that wraps the findscu and movescu commands, which are part of DCMTK.

Usage involves the instantiation of an SCU object, which maintains knowledge of the caller and callee (data requester
and data source, respectively).

Specific Query objects are constructed (e.g., SeriesQuery, if you intend to search for or move a series) and passed to
the find() or move() methods of an SCU object.
"""

import re
import shlex
import logging
import subprocess

log = logging.getLogger('reaper.dicom.scu')

RESPONSE_RE = re.compile("""
W: # Dicom-Data-Set
W: # Used TransferSyntax: (?P<transfer_syntax>.+)
(?P<dicom_cvs>(W: \(.+\) .+\n){2,})""")
DICOM_CV_RE = re.compile(""".*\((?P<idx_0>[0-9a-f]{4}),(?P<idx_1>[0-9a-f]{4})\) (?P<type>\w{2}) (?P<value>.+)#[ ]*(?P<length>\d+),[ ]*(?P<n_elems>\d+) (?P<label>\w+)\n""")
MOVE_OUTPUT_RE = re.compile('.*Completed Suboperations +: ([a-zA-Z0-9]+)', re.DOTALL)


class SCU(object):

    """
    SCU stores information required to communicate with the scanner during calls to find() and move().

    Instantiated with the host, port, and aet of the scanner, as well as the aec of the calling machine. Incoming port
    is optional (default=port).
    """

    def __init__(self, host, port, return_port, aet, aec):
        self.host = host
        self.port = port
        self.return_port = return_port
        self.aet = aet
        self.aec = aec

    def find(self, query):
        """ Construct a findscu query. Return a list of Response objects. """
        cmd = 'findscu -v %s' % self.query_string(query)
        log.debug(cmd)
        output = ''
        try:
            output = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT)
        except Exception as ex:
            log.debug(ex)
            output and self.log.debug(output)
        if output and re.search('DIMSE Status .* Success', output):
            return [Response(query.kwargs.keys(), match_obj.groupdict()) for match_obj in RESPONSE_RE.finditer(output)]
        else:
            return []

    def move(self, query, dest_path='.'):
        """Construct a movescu query. Return the count of images successfully transferred."""
        cmd = 'movescu -v -od %s --port %s %s' % (dest_path, self.return_port, self.query_string(query))<commit_msg>better logging on scu error<commit_after># @author:  <NAME>
#           <NAME>

"""
SCU is a module that wraps the findscu and movescu commands, which are part of DCMTK.

Usage involves the instantiation of an SCU object, which maintains knowledge of the caller and callee (data requester
and data source, respectively).

Specific Query objects are constructed (e.g., SeriesQuery, if you intend to search for or move a series) and passed to
the find() or move() methods of an SCU object.
"""

import re
import shlex
import logging
import subprocess

log = logging.getLogger('reaper.dicom.scu')

RESPONSE_RE = re.compile("""
W: # Dicom-Data-Set
W: # Used TransferSyntax: (?P<transfer_syntax>.+)
(?P<dicom_cvs>(W: \(.+\) .+\n){2,})""")
DICOM_CV_RE = re.compile(""".*\((?P<idx_0>[0-9a-f]{4}),(?P<idx_1>[0-9a-f]{4})\) (?P<type>\w{2}) (?P<value>.+)#[ ]*(?P<length>\d+),[ ]*(?P<n_elems>\d+) (?P<label>\w+)\n""")
MOVE_OUTPUT_RE = re.compile('.*Completed Suboperations +: ([a-zA-Z0-9]+)', re.DOTALL)


class SCU(object):

    """
    SCU stores information required to communicate with the scanner during calls to find() and move().

    Instantiated with the host, port, and aet of the scanner, as well as the aec of the calling machine. Incoming port
    is optional (default=port).
    """

    def __init__(self, host, port, return_port, aet, aec):
        self.host = host
        self.port = port
        self.return_port = return_port
        self.aet = aet
        self.aec = aec

    def find(self, query):
        """ Construct a findscu query. Return a list of Response objects. """
        cmd = 'findscu -v %s' % self.query_string(query)
        log.debug(cmd)
        output = ''
        try:
            output = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT)
        except Exception as ex:
            log.debug(ex)
            output and log.debug(output)
        if output and re.search('DIMSE Status .* Success', output):
            return [Response(query.kwargs.keys(), match_obj.groupdict()) for match_obj in RESPONSE_RE.finditer(output)]
        else:
            log.warning(cmd)
            log.warning(output)
            return []

    def move(self, query, dest_path='.'):
        """Construct a movescu query. Return the count of images successfully transferred."""
        cmd = 'movescu -v -od %s --port %s %s' % (dest_path, self.return_port, self.query_string(query))
{'fraction_non_alphanumeric': 0.14402859545836838, 'fraction_numerical': 0.005046257359125316, 'mean_word_length': 3.0588737201365186, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4746949', 'n_tokens_mistral': 1589, 'n_tokens_neox': 1551, 'n_words': 475}