<commit_before>import imp, os, inspect, sys, slicer

from XnatLoadWorkflow import *
import DICOMScalarVolumePlugin

comment = """
XnatDicomLoadWorkflow is the loader class for all DICOM input received
from XNAT.  The high-level workflow of the download is as follows:

1) Download a zip file of one scan or multiple scans in DICOM format.
2) Unpack the zip file and cache accordingly.
3) Apply these files to the slicer DICOM database.
4) Leverage the slicer 'DICOMWidget' to parse and and load the images.

NOTE: DICOMLoader makes use of Slicer's DICOM database and
Steve Pieper's DICOMPlugin for parsing.

TODO:
"""

class XnatDicomLoadWorkflow(XnatLoadWorkflow):
    """ XnatDicomLoadWorkflow conducts the necessary steps
        to load DICOM files into Slicer.
    """

    def initLoad(self, args):
        """ Starter function for loading DICOMs into Slicer from
            XNAT.  The function 'load' is its successor.  This function
            determines if the user is downloading a single folder or multiple dicom
            folders.
        """

        self.processingDicomsMessageBox = qt.QMessageBox(1, "Processing data", "Processing.  Data will load automatically.")
        self.processingDicomsMessageBox.setWindowModality(1)
        self.processingDicomsMessageBox.setStandardButtons(0)

        #--------------------
        # Make sure Slicer's DICOMdatabase is set up.
        # Show a popup informing the user if it's not.
        # The user has to restart the process if it's not.
        #--------------------
        m = slicer.util.mainWindow()
        if not slicer.dicomDatabase:
            msg =  """It doesn\'t look like your DICOM database directory is setup. Please set it up in the DICOM module and try your download again."""
            self.terminateLoad(['DICOM load', msg ])
            m.moduleSelector().selectModule('DICOM')

        #--------------------
        # Call parent class -- sets relevant public
        # variables.
        #--------------------
        super(XnatDicomLoadWorkflow, self).load(args)

        #--------------------
        # Define public vars. for XnatDicomLoadWorkflow.
        #--------------------
        self.XnatLevel = ''
        if '/scans/' in self.xnatSrc:
            self.XnatLevel = 'scans'
        elif '/experiments/' in self.xnatSrc:
            self.XnatLevel = 'experiments'
        elif '/subjects/' in self.xnatSrc:
            self.XnatLevel = 'subjects'
        self.folderName = os.path.basename(os.path.dirname(self.xnatSrc))
        self.downloadables = []
        self.DICOMWidget = None

        #---------------------
        # Is the user downloading multiple folders?
        #---------------------
        if self.xnatSrc.endswith("files"):

            #
            # If not, proceed with load at the current URI
            # (contianed in 'args' argument)
            #
            self.load()
        else:

            #
            # If so, then setup+show dialog asking user if they
            # want to proceed.
            #
            self.areYouSureDialog = qt.QMessageBox()
            self.areYouSureDialog.setIcon(4)

            self.areYouSureDialog.setText("You are about to load all of " +
                                          self.folderName + "'s "+
                                          "DICOMs.\n" +
                                          "This may take several minutes.\n" +
                                          "Are you sure you want to continue?")
            self.areYouSureDialog.addButton(qt.QMessageBox.Yes)
            self.areYouSureDialog.addButton(qt.QMessageBox.No)
            self.areYouSureDialog.connect('buttonClicked(QAbstractButton*)', self.load)
            self.areYouSureDialog.show()

    def getDownloadables(self, parentXnatUri):
        """ Called within the 'load' function. Checks if DICOM
            files exist at the 'resources' level of a given XNAT path.
        """

        #---------------------
        # Get the resources of the Xnat URI provided in the argument.
        #---------------------

        contents = self.MODULE.XnatIo.getFolderContents(parentXnatUri + '/files', metadataTags = ['URI'])

        try:
            contents['URI']
        except Exception, e:
            print "Skipping '%s' (Error: %s)"%(fileFolderUri, str(e))
            #return

        #
        # Check to see if the file extensions (contents) are valid.
        #
        for filename in contents['URI']:

            #
            # If valid, add to "downloadables" if DICOM
            #
            print "Seeing if DICOM", filename
            if self.MODULE.utils.isDICOM(filename):
                self.downloadables.append(filename)
            else:
                print  "%s Not a usable file: '%s' "%(self.MODULE.utils.lf(), (filename))

    def load(self):
        """ Main load function for downloading DICOM files
            from an XNAT server and loading them into Slicer.
            The general approach is as follows:

            1) Clear existing download path
            2) Acquire downloadables depending on the XNAT level.
               (Experiment is the minimum download level.)
            2a) Check if downloadbles are chached in the slicer.dicomDatabase.
                Track all cached files.
            3) Get the non-cached downloadables by zipped folder files.
            4) Conduct the necessary caching and file management of the download.
            5) Insert downloaded DICOMS into slicer.dicomDatabase
            6) Query the database for the recently downloaded DICOMs
            7) Acquire "Loadables" based on database query.
            8) Load loadables with highest file count to Slicer.
        """

        experimentsList = []
        scansList = []

        #--------------------
        # Remove existing files in the local download path (self.localDst)
        # if they exist.
        #--------------------
        if os.path.exists(self.localDst) and os.path.isdir(self.localDst):
            self.MODULE.utils.removeFilesInDir(self.localDst)
        if not os.path.exists(self.localDst):
            os.makedirs(self.localDst)
        print(self.MODULE.utils.lf(), "Downloading DICOMS in '%s'."%(self.xnatSrc),"Please wait.")

        #--------------------
        # EXPERIMENT - get downloadables.
        #--------------------
        if self.XnatLevel == 'experiments':
            #print(self.MODULE.utils.lf(), "Retrieving experiment-level DICOMS.")

            #
            # First, get the downloadables at the current URI.
            #
            self.getDownloadables(os.path.dirname(self.xnatSrc))

            #
            # Then, scan the folder contents of the 'scan' folders within
            # the experiment.  Get the downloadables accordingly.
            #
            scansList, sizes = self.MODULE.XnatIo.getFolderContents(self.xnatSrc, self.MODULE.utils.XnatMetadataTags_experiments)
            for scan in scansList:
                self.getDownloadables(self.xnatSrc + "/" + scan)

        #--------------------
        # SCANS - get downloadables.
        #--------------------
        elif self.XnatLevel == 'scans':
            selector = self.xnatSrc.split("/files")[0] if self.xnatSrc.endswith('/files') else self.xnatSrc
            self.getDownloadables(selector)

        #--------------------
        # RESOURCES - get downloadables.
        #--------------------
        elif self.XnatLevel == 'resources':
            self.getDownloadables(self.xnatSrc.split("/resources")[0])

        #--------------------
        # Exit out if there are no downloadables.
        #--------------------
        if len(self.downloadables) == 0:
            downloadFail = "No scans in '%s' found to download."%(self.xnatSrc)
            if self.MODULE.XnatLoadWorkflow.currentDownloadState == 'single':
                self.MODULE.XnatDownloadPopup.hide()
                self.MODULE.XnatIo.downloadFailed('Download failed', downloadFail)
            else:
                print downloadFail
            return

        #--------------------
        # Set the local download path.
        #--------------------
        if self.localDst.endswith("/"):
            self.localDst = self.localDst[:-2]
        if not os.path.exists(self.localDst):
            os.mkdir(self.localDst)

        #--------------------
        # Construct a dictionary that maps remote
        # src files to local dst files.
        #--------------------
        downloadDictionary = dict(zip(self.downloadables, [(self.localDst + "/" + os.path.basename(dcm)) for dcm in self.downloadables]))

        print downloadDictionary
        #return

        #--------------------
        # CACHING: Check the slicer.dicomDatabase to see if
        # the files already exist.
        #--------------------
        dicomFilenames = [(os.path.basename(dcm)) for dcm in self.downloadables]
        foundDicoms = {}
        for dbFile in slicer.dicomDatabase.allFiles():
            dbBasename = os.path.basename(dbFile)
            if dbBasename in dicomFilenames:
                foundDicoms[dbBasename] = dbFile
        if len(foundDicoms) > 0:
            print self.MODULE.utils.lf(), "Several of the DICOMs to download are already in the cache!"

        #--------------------
        # Establish the downloadedDicoms array.
        #--------------------
        downloadedDicoms = []

        #--------------------
        # Cull any of the cached DICOMSs from the downloadDictionary,
        # adding them to the 'downloadedDicoms' array.
        #--------------------
        newDownloadDictionary = {}
        for key, value in downloadDictionary.iteritems():
            keyBasename = os.path.basename(key)
            if not keyBasename in foundDicoms:
                newDownloadDictionary[key] = value
            else:

                #
                # Add cached files to the 'downloadedDicoms'
                # array.
                #
                downloadedDicoms.append(foundDicoms[keyBasename])
        downloadDictionary =  newDownloadDictionary

        #--------------------
        # DOWNLOAD: Download all un-cached DICOMS as part of a zipped file.
        #--------------------
        zipFolders = self.MODULE.XnatIo.getFiles(downloadDictionary)

        #
        # Close the download popup, in case it's visible.
        #
        self.MODULE.XnatDownloadPopup.window.hide()

        #--------------------
        # Reenable the XnatView so the user
        # can interact with it.
        #--------------------
        self.MODULE.XnatView.setEnabled(True)
        slicer.app.processEvents()

        #--------------------
        # Inventory downloaded zipfile
        #--------------------

        for zipFile in zipFolders:

            extractPath = zipFile.split(".")[0]

            #
            # Remove existing zipfile extract path if it exists
            #
            if os.path.exists(extractPath):
                self.MODULE.utils.removeDirsAndFiles(extractPath)

            #
            # If the zipfile does not exist, then exit.
            # (This is the result of the Cancel button in
            # the download modal being clicked.)
            #
            if not os.path.exists(zipFile):
                print "%s exiting workflow..."%(self.MODULE.utils.lf())
                return False

            #
            # Show the 'Processing DICOMs' QMessageBox if it's not open
            #
            if not self.processingDicomsMessageBox.visible:
                #print "\n\n\t\tHiding processing DICOMS"
                self.MODULE.utils.repositionToMainSlicerWindow(self.processingDicomsMessageBox)
                self.processingDicomsMessageBox.show()

            #
            # Decompress zips.
            #
            print zipFile, extractPath
            self.MODULE.utils.decompressFile(zipFile, extractPath)

            #
            # Add to files in the decompressed destination
            # to downloadedDicoms list.
            #
            print "%s Inventorying downloaded files..."%(self.MODULE.utils.lf())
            for root, dirs, files in os.walk(extractPath):
                for relFileName in files:
                    downloadedDicoms.append(self.MODULE.utils.adjustPathSlashes(os.path.join(root, relFileName)))

        #--------------------
        # Add DICOM files to slicer.dicomDataase
        #--------------------
        i = ctk.ctkDICOMIndexer()
        try:
            i.addListOfFiles(slicer.dicomDatabase, downloadedDicoms)
        except Exception, e:

            #
            # If the database is uninitialized, then initialize it.
            #
            errorString = str(e)
            if 'uninitialized ctkDICOMItem' in errorString:
                print (self.MODULE.utils.lf(), "The slicer.dicomDabase is unitialized (%s).  Initializing it."%(errorString))
                slicer.dicomDatabase.initialize()
                i.addListOfFiles(slicer.dicomDatabase, downloadedDicoms)

        #--------------------
        # Load the 'downloaded' DICOMS from Slicer's database.
        #--------------------
        return self.loadDicomsFromDatabase(downloadedDicoms)

    def loadDicomsFromDatabase(self, dicomFiles):
        """  Loads a set of dicom database files from the slicer.dicomDatabase
             into Slicer without prompting the user to input anything.
             The 'loadable' with the hightest priority has the highest
             file count.
        """

        #--------------------
        # Create dictionary of downloaded DICOMS
        # for quick retrieval when comparing with files
        # in the slicer.dicomDatabase.  Speed preferred over
        # memory consumption here.
        #--------------------
        dlDicomObj = {}
        for dlFile in dicomFiles:
            dlDicomObj[os.path.basename(dlFile)] = dlFile

        #--------------------
        # Parse through the slicer.dicomDatabase
        # to get all of the files, as determined by series.
        #--------------------
        matchedDatabaseFiles = []
        for patient in slicer.dicomDatabase.patients():
            for study in slicer.dicomDatabase.studiesForPatient(patient):
                for series in slicer.dicomDatabase.seriesForStudy(study):
                    seriesFiles = slicer.dicomDatabase.filesForSeries(series)
                    #
                    # Compare files in series with what was just downloaded.
                    # If there's a match, append to 'matchedDatabaseFiles'.
                    #
                    for sFile in seriesFiles:
                       if os.path.basename(sFile) in dlDicomObj:
                           matchedDatabaseFiles.append(sFile)

        #--------------------
        # Acquire loadabes as determined by
        # the 'DICOMScalarVolumePlugin' class, by feeding in
        # 'matchedDatabaseFiles' as a nested array.
        #--------------------
        dicomScalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']()
        loadables = dicomScalarVolumePlugin.examine([matchedDatabaseFiles])

        #--------------------
        # Determine loadable with the highest file count.
        # This is usually all DICOM files collated as one volume.
        #--------------------
        highestFileCount = 0
        highestFileCountIndex = 0
        for i in range(0, len(loadables)):
            if len(loadables[i].files) > highestFileCount:
                highestFileCount = len(loadables[i].files)
                highestFileCountIndex = i

        #--------------------
        # Load loadable with the highest file count.
        # This is assumed to be the volume file that contains
        # the majority of the downloaded DICOMS.
        #--------------------
        dicomScalarVolumePlugin.load(loadables[highestFileCountIndex])

        #--------------------
        # Hide the 'processing Dicoms' notification window.
        #--------------------
        self.processingDicomsMessageBox.hide()

        #--------------------
        # Return true if login successful.
        #--------------------
        return True

    def beginDICOMSession(self):
        """ DEECATED: Once a DICOM folder has been downloaded,
            track the origins of the files for Save/upload
            routines.

            NOTE:
        """
        #print(self.MODULE.utils.lf(), "DICOMS successfully loaded.")
        sessionArgs = XnatSessionArgs(MODULE = self.MODULE, srcPath = self.xnatSrc)
        sessionArgs['sessionType'] = "dicom download"
        self.MODULE.XnatView.startNewSession(sessionArgs)

<commit_msg>TOOLS-79 (Bugs - Fixed): Download failures: multiple folders, IMAs, etc. (and related UI issues)<commit_after>import imp, os, inspect, sys, slicer

from XnatLoadWorkflow import *
import DICOMScalarVolumePlugin

comment = """
XnatDicomLoadWorkflow is the loader class for all DICOM input received
from XNAT.  The high-level workflow of the download is as follows:

1) Download a zip file of one scan or multiple scans in DICOM format.
2) Unpack the zip file and cache accordingly.
3) Apply these files to the slicer DICOM database.
4) Leverage the slicer 'DICOMWidget' to parse and and load the images.

NOTE: DICOMLoader makes use of Slicer's DICOM database and
Steve Pieper's DICOMPlugin for parsing.

TODO:
"""

class XnatDicomLoadWorkflow(XnatLoadWorkflow):
    """ XnatDicomLoadWorkflow conducts the necessary steps
        to load DICOM files into Slicer.
    """

    def initLoad(self, args):
        """ Starter function for loading DICOMs into Slicer from
            XNAT.  The function 'load' is its successor.  This function
            determines if the user is downloading a single folder or multiple dicom
            folders.
        """

        self.processingDicomsMessageBox = qt.QMessageBox(1, "Processing data", "Processing.  Data will load automatically.")
        self.processingDicomsMessageBox.setWindowModality(1)
        self.processingDicomsMessageBox.setStandardButtons(0)

        #--------------------
        # Make sure Slicer's DICOMdatabase is set up.
        # Show a popup informing the user if it's not.
        # The user has to restart the process if it's not.
        #--------------------
        m = slicer.util.mainWindow()
        if not slicer.dicomDatabase:
            msg =  """It doesn\'t look like your DICOM database directory is setup. Please set it up in the DICOM module and try your download again."""
            self.terminateLoad(['DICOM load', msg ])
            m.moduleSelector().selectModule('DICOM')

        #--------------------
        # Call parent class -- sets relevant public
        # variables.
        #--------------------
        super(XnatDicomLoadWorkflow, self).load(args)

        #--------------------
        # Define public vars. for XnatDicomLoadWorkflow.
        #--------------------
        self.XnatLevel = ''
        if '/scans/' in self.xnatSrc:
            self.XnatLevel = 'scans'
        elif '/experiments/' in self.xnatSrc:
            self.XnatLevel = 'experiments'
        elif '/subjects/' in self.xnatSrc:
            self.XnatLevel = 'subjects'
        self.folderName = os.path.basename(os.path.dirname(self.xnatSrc))
        self.downloadables = []
        self.DICOMWidget = None

        #---------------------
        # Is the user downloading multiple folders?
        #---------------------
        if self.xnatSrc.endswith("files"):

            #
            # If not, proceed with load at the current URI
            # (contianed in 'args' argument)
            #
            self.load()
        else:

            #
            # If so, then setup+show dialog asking user if they
            # want to proceed.
            #
            self.areYouSureDialog = qt.QMessageBox()
            self.areYouSureDialog.setIcon(4)

            self.areYouSureDialog.setText("You are about to load all of " +
                                          self.folderName + "'s "+
                                          "DICOMs.\n" +
                                          "This may take several minutes.\n" +
                                          "Are you sure you want to continue?")
            self.areYouSureDialog.addButton(qt.QMessageBox.Yes)
            self.areYouSureDialog.addButton(qt.QMessageBox.No)
            self.areYouSureDialog.connect('buttonClicked(QAbstractButton*)', self.load)
            self.areYouSureDialog.show()

    def getDownloadables(self, parentXnatUri):
        """ Called within the 'load' function. Checks if DICOM
            files exist at the 'resources' level of a given XNAT path.
        """

        #---------------------
        # Get the resources of the Xnat URI provided in the argument.
        #---------------------

        contents = self.MODULE.XnatIo.getFolderContents(parentXnatUri + '/files', metadataTags = ['URI'])

        try:
            contents['URI']
        except Exception, e:
            print "Skipping '%s' (Error: %s)"%(fileFolderUri, str(e))
            #return

        #
        # Check to see if the file extensions (contents) are valid.
        #
        for filename in contents['URI']:

            #
            # If valid, add to "downloadables" if DICOM
            #
            print "Seeing if DICOM", filename
            if self.MODULE.utils.isDICOM(filename):
                self.downloadables.append(filename)
            else:
                print  "%s Not a usable file: '%s' "%(self.MODULE.utils.lf(), (filename))

    def load(self):
        """ Main load function for downloading DICOM files
            from an XNAT server and loading them into Slicer.
            The general approach is as follows:

            1) Clear existing download path
            2) Acquire downloadables depending on the XNAT level.
               (Experiment is the minimum download level.)
            2a) Check if downloadbles are chached in the slicer.dicomDatabase.
                Track all cached files.
            3) Get the non-cached downloadables by zipped folder files.
            4) Conduct the necessary caching and file management of the download.
            5) Insert downloaded DICOMS into slicer.dicomDatabase
            6) Query the database for the recently downloaded DICOMs
            7) Acquire "Loadables" based on database query.
            8) Load loadables with highest file count to Slicer.
        """

        experimentsList = []
        scansList = []

        #--------------------
        # Remove existing files in the local download path (self.localDst)
        # if they exist.
        #--------------------
        if os.path.exists(self.localDst) and os.path.isdir(self.localDst):
            self.MODULE.utils.removeFilesInDir(self.localDst)
        if not os.path.exists(self.localDst):
            os.makedirs(self.localDst)
        print(self.MODULE.utils.lf(), "Downloading DICOMS in '%s'."%(self.xnatSrc),"Please wait.")

        #--------------------
        # EXPERIMENT - get downloadables.
        #--------------------
        if self.XnatLevel == 'experiments':
            #print(self.MODULE.utils.lf(), "Retrieving experiment-level DICOMS.")

            #
            # First, get the downloadables at the current URI.
            #
            self.getDownloadables(os.path.dirname(self.xnatSrc))

            #
            # Then, scan the folder contents of the 'scan' folders within
            # the experiment.  Get the downloadables accordingly.
            #
            scansList, sizes = self.MODULE.XnatIo.getFolderContents(self.xnatSrc, self.MODULE.utils.XnatMetadataTags_experiments)
            for scan in scansList:
                self.getDownloadables(self.xnatSrc + "/" + scan)

        #--------------------
        # SCANS - get downloadables.
        #--------------------
        elif self.XnatLevel == 'scans':
            selector = self.xnatSrc.split("/files")[0] if self.xnatSrc.endswith('/files') else self.xnatSrc
            self.getDownloadables(selector)

        #--------------------
        # RESOURCES - get downloadables.
        #--------------------
        elif self.XnatLevel == 'resources':
            self.getDownloadables(self.xnatSrc.split("/resources")[0])

        #--------------------
        # Exit out if there are no downloadables.
        #--------------------
        if len(self.downloadables) == 0:
            downloadFail = "No scans in '%s' found to download."%(self.xnatSrc)
            if self.MODULE.XnatLoadWorkflow.currentDownloadState == 'single':
                self.MODULE.XnatDownloadPopup.hide()
                self.MODULE.XnatIo.downloadFailed('Download failed', downloadFail)
            else:
                print downloadFail
            return

        #--------------------
        # Set the local download path.
        #--------------------
        if self.localDst.endswith("/"):
            self.localDst = self.localDst[:-2]
        if not os.path.exists(self.localDst):
            os.mkdir(self.localDst)

        #--------------------
        # Construct a dictionary that maps remote
        # src files to local dst files.
        #--------------------
        downloadDictionary = dict(zip(self.downloadables, [(self.localDst + "/" + os.path.basename(dcm)) for dcm in self.downloadables]))

        print downloadDictionary
        #return

        #--------------------
        # CACHING: Check the slicer.dicomDatabase to see if
        # the files already exist.
        #--------------------
        dicomFilenames = [(os.path.basename(dcm)) for dcm in self.downloadables]
        foundDicoms = {}
        for dbFile in slicer.dicomDatabase.allFiles():
            dbBasename = os.path.basename(dbFile)
            if dbBasename in dicomFilenames:
                foundDicoms[dbBasename] = dbFile
        if len(foundDicoms) > 0:
            print self.MODULE.utils.lf(), "Several of the DICOMs to download are already in the cache!"

        #--------------------
        # Establish the downloadedDicoms array.
        #--------------------
        downloadedDicoms = []

        #--------------------
        # Cull any of the cached DICOMSs from the downloadDictionary,
        # adding them to the 'downloadedDicoms' array.
        #--------------------
        newDownloadDictionary = {}
        for key, value in downloadDictionary.iteritems():
            keyBasename = os.path.basename(key)
            if not keyBasename in foundDicoms:
                newDownloadDictionary[key] = value
            else:

                #
                # Add cached files to the 'downloadedDicoms'
                # array.
                #
                downloadedDicoms.append(foundDicoms[keyBasename])
        downloadDictionary =  newDownloadDictionary

        #--------------------
        # DOWNLOAD: Download all un-cached DICOMS as part of a zipped file.
        #--------------------
        zipFolders = self.MODULE.XnatIo.getFiles(downloadDictionary)

        #
        # Close the download popup, in case it's visible.
        #
        self.MODULE.XnatDownloadPopup.window.hide()

        #--------------------
        # Reenable the XnatView so the user
        # can interact with it.
        #--------------------
        self.MODULE.XnatView.setEnabled(True)
        slicer.app.processEvents()

        #--------------------
        # Inventory downloaded zipfile
        #--------------------

        for zipFile in zipFolders:

            extractPath = zipFile.split(".")[0]

            #
            # Remove existing zipfile extract path if it exists
            #
            if os.path.exists(extractPath):
                self.MODULE.utils.removeDirsAndFiles(extractPath)

            #
            # If the zipfile does not exist, then exit.
            # (This is the result of the Cancel button in
            # the download modal being clicked.)
            #
            if not os.path.exists(zipFile):
                print "%s exiting workflow..."%(self.MODULE.utils.lf())
                return False

            #
            # Show the 'Processing DICOMs' QMessageBox if it's not open
            #
            if not self.processingDicomsMessageBox.visible:
                ##print "\n\n\t\tHiding processing DICOMS"
                self.MODULE.utils.repositionToMainSlicerWindow(self.processingDicomsMessageBox)
                self.processingDicomsMessageBox.show()

            #
            # Decompress zips.
            #
            print zipFile, extractPath
            self.MODULE.utils.decompressFile(zipFile, extractPath)

            #
            # Add to files in the decompressed destination
            # to downloadedDicoms list.
            #
            print "%s Inventorying downloaded files..."%(self.MODULE.utils.lf())
            for root, dirs, files in os.walk(extractPath):
                for relFileName in files:
                    downloadedDicoms.append(self.MODULE.utils.adjustPathSlashes(os.path.join(root, relFileName)))

        #--------------------
        # Add DICOM files to slicer.dicomDataase
        #--------------------
        i = ctk.ctkDICOMIndexer()
        try:
            i.addListOfFiles(slicer.dicomDatabase, downloadedDicoms)
        except Exception, e:

            #
            # If the database is uninitialized, then initialize it.
            #
            errorString = str(e)
            if 'uninitialized ctkDICOMItem' in errorString:
                print (self.MODULE.utils.lf(), "The slicer.dicomDabase is unitialized (%s).  Initializing it."%(errorString))
                slicer.dicomDatabase.initialize()
                i.addListOfFiles(slicer.dicomDatabase, downloadedDicoms)

        #--------------------
        # Load the 'downloaded' DICOMS from Slicer's database.
        #--------------------
        return self.loadDicomsFromDatabase(downloadedDicoms)

    def loadDicomsFromDatabase(self, dicomFiles):
        """  Loads a set of dicom database files from the slicer.dicomDatabase
             into Slicer without prompting the user to input anything.
             The 'loadable' with the hightest priority has the highest
             file count.
        """

        #--------------------
        # Create dictionary of downloaded DICOMS
        # for quick retrieval when comparing with files
        # in the slicer.dicomDatabase.  Speed preferred over
        # memory consumption here.
        #--------------------
        dlDicomObj = {}
        for dlFile in dicomFiles:
            dlDicomObj[os.path.basename(dlFile)] = dlFile

        #--------------------
        # Parse through the slicer.dicomDatabase
        # to get all of the files, as determined by series.
        #--------------------
        matchedDatabaseFiles = []
        for patient in slicer.dicomDatabase.patients():
            for study in slicer.dicomDatabase.studiesForPatient(patient):
                for series in slicer.dicomDatabase.seriesForStudy(study):
                    seriesFiles = slicer.dicomDatabase.filesForSeries(series)
                    #
                    # Compare files in series with what was just downloaded.
                    # If there's a match, append to 'matchedDatabaseFiles'.
                    #
                    for sFile in seriesFiles:
                       if os.path.basename(sFile) in dlDicomObj:
                           matchedDatabaseFiles.append(sFile)

        #--------------------
        # Acquire loadabes as determined by
        # the 'DICOMScalarVolumePlugin' class, by feeding in
        # 'matchedDatabaseFiles' as a nested array.
        #--------------------
        dicomScalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']()
        loadables = dicomScalarVolumePlugin.examine([matchedDatabaseFiles])

        #--------------------
        # Determine loadable with the highest file count.
        # This is usually all DICOM files collated as one volume.
        #--------------------
        highestFileCount = 0
        highestFileCountIndex = 0
        for i in range(0, len(loadables)):
            if len(loadables[i].files) > highestFileCount:
                highestFileCount = len(loadables[i].files)
                highestFileCountIndex = i

        #--------------------
        # Load loadable with the highest file count.
        # This is assumed to be the volume file that contains
        # the majority of the downloaded DICOMS.
        #--------------------
        dicomScalarVolumePlugin.load(loadables[highestFileCountIndex])

        #--------------------
        # Hide the 'processing Dicoms' notification window.
        #--------------------
        self.processingDicomsMessageBox.hide()

        #--------------------
        # Return true if login successful.
        #--------------------
        return True

    def beginDICOMSession(self):
        """ DEECATED: Once a DICOM folder has been downloaded,
            track the origins of the files for Save/upload
            routines.

            NOTE:
        """
        #print(self.MODULE.utils.lf(), "DICOMS successfully loaded.")
        sessionArgs = XnatSessionArgs(MODULE = self.MODULE, srcPath = self.xnatSrc)
        sessionArgs['sessionType'] = "dicom download"
        self.MODULE.XnatView.startNewSession(sessionArgs)

<|endoftext|>


<commit_before>"""This file contains all the classes you must complete for this project.

You can use the test cases in agent_test.py to help during development, and
augment the test suite with your own test cases to further test your code.

You must test your agent's strength against a set of agents with known
relative strength using tournament.py and include the results in your report.
"""
import random

class Timeout(Exception):
    """Subclass base exception for code clarity."""
    pass

def custom_score(game, player):
    """Calculate the heuristic value of a game state from the point of view
    of the given player.

    Note: this function should be called from within a Player instance as
    `self.score()` -- you should not need to call this function directly.

    Parameters
    ----------
    game : `isolation.Board`
        An instance of `isolation.Board` encoding the current state of the
        game (e.g., player locations and blocked cells).

    player : object
        A player instance in the current game (i.e., an object corresponding to
        one of the player objects `game.__player_1__` or `game.__player_2__`.)

    Returns
    -------
    float
        The heuristic value of the current game state to the specified player.
    """

    if game.is_loser(player):
        return float("-inf")

    if game.is_winner(player):
        return float("inf")

    player_moves = float(len(game.get_legal_moves(player)))
    opponent_moves = float(len(game.get_legal_moves(game.get_opponent(player))))

    return player_moves / opponent_moves

class CustomPlayer:
    """Game-playing agent that chooses a move using your evaluation function
    and a depth-limited minimax algorithm with alpha-beta pruning. You must
    finish and test this player to make sure it properly uses minimax and
    alpha-beta to return a good move before the search time limit expires.

    Parameters
    ----------
    search_depth : int (optional)
        A strictly positive integer (i.e., 1, 2, 3,...) for the number of
        layers in the game tree to explore for fixed-depth search. (i.e., a
        depth of one (1) would only explore the immediate sucessors of the
        current state.)

    score_fn : callable (optional)
        A function to use for heuristic evaluation of game states.

    iterative : boolean (optional)
        Flag indicating whether to perform fixed-depth search (False) or
        iterative deepening search (True).

    method : {'minimax', 'alphabeta'} (optional)
        The name of the search method to use in get_move().

    timeout : float (optional)
        Time remaining (in milliseconds) when search is aborted. Should be a
        positive value large enough to allow the function to return before the
        timer expires.
    """

    def __init__(self, search_depth=3, score_fn=custom_score,
                 iterative=True, method='minimax', timeout=10.):
        self.search_depth = search_depth
        self.iterative = iterative
        self.score = score_fn
        self.method = method
        self.time_left = None
        self.TIMER_THRESHOLD = timeout

    def get_move(self, game, legal_moves, time_left):
        """Search for the best move from the available legal moves and return a
        result before the time limit expires.

        This function must perform iterative deepening if self.iterative=True,
        and it must use the search method (minimax or alphabeta) corresponding
        to the self.method value.

        **********************************************************************
        NOTE: If time_left < 0 when this function returns, the agent will
              forfeit the game due to timeout. You must return _before_ the
              timer reaches 0.
        **********************************************************************

        Parameters
        ----------
        game : `isolation.Board`
            An instance of `isolation.Board` encoding the current state of the
            game (e.g., player locations and blocked cells).

        legal_moves : list<(int, int)>
            A list containing legal moves. Moves are encoded as tuples of pairs
            of ints defining the next (row, col) for the agent to occupy.

        time_left : callable
            A function that returns the number of milliseconds left in the
            current turn. Returning with any less than 0 ms remaining forfeits
            the game.

        Returns
        -------
        (int, int)
            Board coordinates corresponding to a legal move; may return
            (-1, -1) if there are no available legal moves.
        """
        if not legal_moves:
            return (-1, -1)

        self.time_left = time_left

        # TODO: finish this function!

        # Perform any required initializations, including selecting an initial
        # move from the game board (i.e., an opening book), or returning
        # immediately if there are no legal moves

        try:
            # The search method call (alpha beta or minimax) should happen in
            # here in order to avoid timeout. The try/except block will
            # automatically catch the exception raised by the search method
            # when the timer gets close to expiring
            move = (-1, -1)
            maximizing_player = True

            if self.method == 'minimax':
                if self.iterative:
                    depth = 0
                    while True:
                        move = self.minimax(game, depth, maximizing_player)
                        depth += 1
                else:
                    move = self.minimax(game, self.search_depth, maximizing_player)

            elif self.method == 'alphabeta':
                if self.iterative:
                    depth = 0
                    while True:
                        move = self.alphabeta(game, depth, alpha=float("-inf"), beta=float("inf"), maximizing_player=True)
                        depth += 1
                else:
                    move = self.alphabeta(game, self.search_depth, alpha=float("-inf"), beta=float("inf"), maximizing_player=True)
            else:
                raise 'ERROR: Uknown search method: {0}'.format(self.method)

            return move

        except Timeout:
            return move

    def minimax(self, game, depth, maximizing_player=True):
        """Implement the minimax search algorithm as described in the lectures.

        Parameters
        ----------
        game : isolation.Board
            An instance of the Isolation game `Board` class representing the
            current game state

        depth : int
            Depth is an integer representing the maximum number of plies to
            search in the game tree before aborting

        maximizing_player : bool
            Flag indicating whether the current search depth corresponds to a
            maximizing layer (True) or a minimizing layer (False)

        Returns
        -------
        float
            The score for the current search branch

        tuple(int, int)
            The best move for the current branch; (-1, -1) for no legal moves

        Notes
        -----
            (1) You MUST use the `self.score()` method for board evaluation
                to pass the project unit tests; you cannot call any other
                evaluation function directly.
        """
        if self.time_left() < self.TIMER_THRESHOLD:
            raise Timeout()

        if len(game.get_legal_moves()) == 0 or depth == 0:
            return self.score(game, self), (-1.0, -1.0)

        if maximizing_player:
            return max([
                (self.minimax(game.forecast_move(move), depth - 1, not maximizing_player)[0], move) for move in game.get_legal_moves()
            ])
        else:
            return min([
                (self.minimax(game.forecast_move(move), depth - 1, not maximizing_player)[0], move) for move in game.get_legal_moves()
            ])

    def alphabeta(self, game, depth, alpha=float("-inf"), beta=float("inf"), maximizing_player=True):
        """Implement minimax search with alpha-beta pruning as described in the
        lectures.

        Parameters
        ----------
        game : isolation.Board
            An instance of the Isolation game `Board` class representing the
            current game state

        depth : int
            Depth is an integer representing the maximum number of plies to
            search in the game tree before aborting

        alpha : float
            Alpha limits the lower bound of search on minimizing layers

        beta : float
            Beta limits the upper bound of search on maximizing layers

        maximizing_player : bool
            Flag indicating whether the current search depth corresponds to a
            maximizing layer (True) or a minimizing layer (False)

        Returns
        -------
        float
            The score for the current search branch

        tuple(int, int)
            The best move for the current branch; (-1, -1) for no legal moves

        Notes
        -----
            (1) You MUST use the `self.score()` method for board evaluation
                to pass the project unit tests; you cannot call any other
                evaluation function directly.
        """
        if self.time_left() < self.TIMER_THRESHOLD:
            raise Timeout()

        if len(game.get_legal_moves()) == 0 or depth == 0:
            return (self.score(game, self), (-1.0, -1.0))

        if maximizing_player:
            v = float('-inf')
            best_move = (-1.0, -1.0)
            for move in game.get_legal_moves():

                result = self.alphabeta(game.forecast_move(move), depth - 1, alpha, beta, not maximizing_player)

                if result[0] > v:
                    v = result[0]
                    best_move = move
                if result[0] >= beta:
                    return v, best_move
                alpha = max(alpha, result[0])
            return v, best_move
        else:
            v = float('inf')
            best_move = (-1.0, -1.0)
            for move in game.get_legal_moves():
                result = self.alphabeta(game.forecast_move(move), depth - 1, alpha, beta, not maximizing_player)

                if result[0] < v:
                    v = result[0]
                    best_move = move

                if result[0] <= alpha:
                    return v, best_move
                beta = min(beta, result[0])
            return v, best_move
<commit_msg>Apparently finished Iterative Deepening<commit_after>"""This file contains all the classes you must complete for this project.

You can use the test cases in agent_test.py to help during development, and
augment the test suite with your own test cases to further test your code.

You must test your agent's strength against a set of agents with known
relative strength using tournament.py and include the results in your report.
"""
import random

class Timeout(Exception):
    """Subclass base exception for code clarity."""
    pass

def custom_score(game, player):
    """Calculate the heuristic value of a game state from the point of view
    of the given player.

    Note: this function should be called from within a Player instance as
    `self.score()` -- you should not need to call this function directly.

    Parameters
    ----------
    game : `isolation.Board`
        An instance of `isolation.Board` encoding the current state of the
        game (e.g., player locations and blocked cells).

    player : object
        A player instance in the current game (i.e., an object corresponding to
        one of the player objects `game.__player_1__` or `game.__player_2__`.)

    Returns
    -------
    float
        The heuristic value of the current game state to the specified player.
    """

    if game.is_loser(player):
        return float("-inf")

    if game.is_winner(player):
        return float("inf")

    player_moves = float(len(game.get_legal_moves(player)))
    opponent_moves = float(len(game.get_legal_moves(game.get_opponent(player))))

    return player_moves / opponent_moves

class CustomPlayer:
    """Game-playing agent that chooses a move using your evaluation function
    and a depth-limited minimax algorithm with alpha-beta pruning. You must
    finish and test this player to make sure it properly uses minimax and
    alpha-beta to return a good move before the search time limit expires.

    Parameters
    ----------
    search_depth : int (optional)
        A strictly positive integer (i.e., 1, 2, 3,...) for the number of
        layers in the game tree to explore for fixed-depth search. (i.e., a
        depth of one (1) would only explore the immediate sucessors of the
        current state.)

    score_fn : callable (optional)
        A function to use for heuristic evaluation of game states.

    iterative : boolean (optional)
        Flag indicating whether to perform fixed-depth search (False) or
        iterative deepening search (True).

    method : {'minimax', 'alphabeta'} (optional)
        The name of the search method to use in get_move().

    timeout : float (optional)
        Time remaining (in milliseconds) when search is aborted. Should be a
        positive value large enough to allow the function to return before the
        timer expires.
    """

    def __init__(self, search_depth=3, score_fn=custom_score,
                 iterative=True, method='minimax', timeout=10.):
        self.search_depth = search_depth
        self.iterative = iterative
        self.score = score_fn
        self.method = method
        self.time_left = None
        self.TIMER_THRESHOLD = timeout

    def get_move(self, game, legal_moves, time_left):
        """Search for the best move from the available legal moves and return a
        result before the time limit expires.

        This function must perform iterative deepening if self.iterative=True,
        and it must use the search method (minimax or alphabeta) corresponding
        to the self.method value.

        **********************************************************************
        NOTE: If time_left < 0 when this function returns, the agent will
              forfeit the game due to timeout. You must return _before_ the
              timer reaches 0.
        **********************************************************************

        Parameters
        ----------
        game : `isolation.Board`
            An instance of `isolation.Board` encoding the current state of the
            game (e.g., player locations and blocked cells).

        legal_moves : list<(int, int)>
            A list containing legal moves. Moves are encoded as tuples of pairs
            of ints defining the next (row, col) for the agent to occupy.

        time_left : callable
            A function that returns the number of milliseconds left in the
            current turn. Returning with any less than 0 ms remaining forfeits
            the game.

        Returns
        -------
        (int, int)
            Board coordinates corresponding to a legal move; may return
            (-1, -1) if there are no available legal moves.
        """
        if not legal_moves:
            return (-1, -1)

        self.time_left = time_left

        # TODO: finish this function!

        # Perform any required initializations, including selecting an initial
        # move from the game board (i.e., an opening book), or returning
        # immediately if there are no legal moves

        try:
            # The search method call (alpha beta or minimax) should happen in
            # here in order to avoid timeout. The try/except block will
            # automatically catch the exception raised by the search method
            # when the timer gets close to expiring
            move = (-1, -1)
            maximizing_player = True

            if self.method == 'minimax':
                if self.iterative:
                    depth = 0
                    while True:
                        move = self.minimax(game, depth, maximizing_player)[1]
                        depth += 1
                else:
                    move = self.minimax(game, self.search_depth, maximizing_player)[1]

            elif self.method == 'alphabeta':
                if self.iterative:
                    depth = 0
                    while True:
                        move = self.alphabeta(game, depth, alpha=float("-inf"), beta=float("inf"), maximizing_player=True)[1]
                        depth += 1
                else:
                    move = self.alphabeta(game, self.search_depth, alpha=float("-inf"), beta=float("inf"), maximizing_player=True)[1]
            else:
                raise 'ERROR: Uknown search method: {0}'.format(self.method)

            return move

        except Timeout:
            return move

    def minimax(self, game, depth, maximizing_player=True):
        """Implement the minimax search algorithm as described in the lectures.

        Parameters
        ----------
        game : isolation.Board
            An instance of the Isolation game `Board` class representing the
            current game state

        depth : int
            Depth is an integer representing the maximum number of plies to
            search in the game tree before aborting

        maximizing_player : bool
            Flag indicating whether the current search depth corresponds to a
            maximizing layer (True) or a minimizing layer (False)

        Returns
        -------
        float
            The score for the current search branch

        tuple(int, int)
            The best move for the current branch; (-1, -1) for no legal moves

        Notes
        -----
            (1) You MUST use the `self.score()` method for board evaluation
                to pass the project unit tests; you cannot call any other
                evaluation function directly.
        """
        if self.time_left() < self.TIMER_THRESHOLD:
            raise Timeout()

        if len(game.get_legal_moves()) == 0 or depth == 0:
            return self.score(game, self), (-1.0, -1.0)

        if maximizing_player:
            return max([
                (self.minimax(game.forecast_move(move), depth - 1, not maximizing_player)[0], move) for move in game.get_legal_moves()
            ])
        else:
            return min([
                (self.minimax(game.forecast_move(move), depth - 1, not maximizing_player)[0], move) for move in game.get_legal_moves()
            ])

    def alphabeta(self, game, depth, alpha=float("-inf"), beta=float("inf"), maximizing_player=True):
        """Implement minimax search with alpha-beta pruning as described in the
        lectures.

        Parameters
        ----------
        game : isolation.Board
            An instance of the Isolation game `Board` class representing the
            current game state

        depth : int
            Depth is an integer representing the maximum number of plies to
            search in the game tree before aborting

        alpha : float
            Alpha limits the lower bound of search on minimizing layers

        beta : float
            Beta limits the upper bound of search on maximizing layers

        maximizing_player : bool
            Flag indicating whether the current search depth corresponds to a
            maximizing layer (True) or a minimizing layer (False)

        Returns
        -------
        float
            The score for the current search branch

        tuple(int, int)
            The best move for the current branch; (-1, -1) for no legal moves

        Notes
        -----
            (1) You MUST use the `self.score()` method for board evaluation
                to pass the project unit tests; you cannot call any other
                evaluation function directly.
        """
        if self.time_left() < self.TIMER_THRESHOLD:
            raise Timeout()

        if len(game.get_legal_moves()) == 0 or depth == 0:
            return (self.score(game, self), (-1.0, -1.0))

        if maximizing_player:
            v = float('-inf')
            best_move = (-1.0, -1.0)
            for move in game.get_legal_moves():

                result = self.alphabeta(game.forecast_move(move), depth - 1, alpha, beta, not maximizing_player)

                if result[0] > v:
                    v = result[0]
                    best_move = move
                if result[0] >= beta:
                    return v, best_move
                alpha = max(alpha, result[0])
            return v, best_move
        else:
            v = float('inf')
            best_move = (-1.0, -1.0)
            for move in game.get_legal_moves():
                result = self.alphabeta(game.forecast_move(move), depth - 1, alpha, beta, not maximizing_player)

                if result[0] < v:
                    v = result[0]
                    best_move = move

                if result[0] <= alpha:
                    return v, best_move
                beta = min(beta, result[0])
            return v, best_move
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from __future__ import print_function, absolute_import, division
import boto.s3
import boto.exception
import boto.sns
import json
import logging

import boto3

BUCKET_REGION = "eu-west-1"

class S3Uploader(object):
    def __init__(self, bucket_name, allowed_ips=None, allowed_aws_account_ids=None):
        self.bucket_name = bucket_name
        self.allowed_ips = allowed_ips or []
        self.allowed_aws_account_ids = allowed_aws_account_ids or []
        self.s3_conn = boto.s3.connect_to_region(BUCKET_REGION)
        self.boto3_s3_client = boto3.client('s3')
        self.sns_conn = boto.sns.connect_to_region(BUCKET_REGION)

    def setup_infrastructure(self):
        topic_arn = self.create_sns_topic()
        self.set_sns_topic_policy(topic_arn)
        self.create_S3_bucket()
        self.set_S3_permissions()
        self.setup_S3_webserver()
        self.enable_bucket_notifications(topic_arn)

    def create_S3_bucket(self):
        """ Create a new S3 bucket if bucket not exists else nothing """
        try:
            self.s3_conn.create_bucket(self.bucket_name, location=BUCKET_REGION)
            logging.debug("Created new AWS S3 bucket with name '%s'", self.bucket_name)
        except boto.exception.S3CreateError as e:
            logging.debug("Could not create S3 bucket '%s': %s", self.bucket_name, e)

    def set_S3_permissions(self):
        policy = {
            "Version": "2012-10-17",
            "Statement": [{
                "Action": [
                    "s3:GetBucketWebsite",
                    "s3:GetObject",
                    "s3:ListBucket"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::{0}/*".format(self.bucket_name),
                    "arn:aws:s3:::{0}".format(self.bucket_name)
                ],
                "Principal": {
                    "AWS": self.allowed_aws_account_ids
                }
            }, {
                "Action": [
                    "s3:GetBucketWebsite",
                    "s3:GetObject",
                    "s3:ListBucket"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::{0}/*".format(self.bucket_name),
                    "arn:aws:s3:::{0}".format(self.bucket_name)
                ],
                "Condition": {
                    "IpAddress": {
                        "aws:SourceIp": self.allowed_ips
                    }
                },
                "Principal": {
                    "AWS": "*"
                }
            }
            ]
        }

        bucket = self.s3_conn.get_bucket(self.bucket_name)
        bucket.set_policy(json.dumps(policy))
        logging.debug("AWS S3 bucket '%s' now has policy: '%s'", self.bucket_name, policy)

    def create_sns_topic(self):
        response = self.sns_conn.create_topic(self.bucket_name)
        topic_arn = response['CreateTopicResponse']['CreateTopicResult']['TopicArn']
        logging.info("Using SNS topic with arn '%s'", topic_arn)

        return topic_arn

    def set_sns_topic_policy(self, topic_arn):
        allow_s3_events = {
            "Sid": "allow_s3_events",
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Principal": {
                "AWS": "*"
            },
            "Resource": topic_arn,
            "Condition": {
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:s3:*:*:{0}".format(self.bucket_name)
                }
            }
        }
        allow_subscribe_to_all_acconts = {
            "Sid": "allow_subscribe_to_all_acconts",
            "Effect": "Allow",
            "Action": [
                "sns:Subscribe"
            ],
            "Principal": {
                "AWS": self.allowed_aws_account_ids
            },
            "Resource": topic_arn
        }
        policy = {
            "Version": "2012-10-17",
            "Statement": [
                allow_s3_events,
                allow_subscribe_to_all_acconts
            ]
        }

        dumps = json.dumps(policy)
        print(dumps)
        self.sns_conn.set_topic_attributes(topic_arn, 'Policy', dumps)

    def enable_bucket_notifications(self, topic_arn):
        notification_configuration = {
            'TopicConfigurations': [
                {
                    'TopicArn': topic_arn,
                    'Events': ['s3:ObjectCreated:*']
                }
            ]
        }
        self.boto3_s3_client.put_bucket_notification_configuration(Bucket=self.bucket_name,
                                                                   NotificationConfiguration=notification_configuration)

    def get_routing_rules(self):
        routing_rules = boto.s3.website.RoutingRules()
        for suffix in ['json', 'yaml']:
            condition = boto.s3.website.Condition(key_prefix=suffix)
            redirect = boto.s3.website.Redirect(replace_key_prefix='accounts.{0}'.format(suffix))
            routing_rules.add_rule(boto.s3.website.RoutingRule(condition, redirect))
        return routing_rules

    def setup_S3_webserver(self):
        bucket = self.s3_conn.get_bucket(self.bucket_name)

        index_key = bucket.new_key('accounts.json')
        index_key.content_type = 'application/json'

        # now set the website configuration for our bucket
        bucket.configure_website(suffix='accounts.json', routing_rules=self.get_routing_rules())
        logging.debug("Website configuration was setup for AWS S3 bucket '%s'", self.bucket_name)

    def upload_to_S3(self, upload_data):
        bucket = self.s3_conn.get_bucket(self.bucket_name)
        key = boto.s3.key.Key(bucket)

        for key_name, content in upload_data.items():
            key.key = key_name
            key.set_contents_from_string(content)
            logging.debug("Uploaded to AWS S3 bucket '%s': "
                          "key '%s' and content '%s'", self.bucket_name, key_name, content)
<commit_msg>remove debugging statement<commit_after># -*- coding: utf-8 -*-

from __future__ import print_function, absolute_import, division
import boto.s3
import boto.exception
import boto.sns
import json
import logging

import boto3

BUCKET_REGION = "eu-west-1"

class S3Uploader(object):
    def __init__(self, bucket_name, allowed_ips=None, allowed_aws_account_ids=None):
        self.bucket_name = bucket_name
        self.allowed_ips = allowed_ips or []
        self.allowed_aws_account_ids = allowed_aws_account_ids or []
        self.s3_conn = boto.s3.connect_to_region(BUCKET_REGION)
        self.boto3_s3_client = boto3.client('s3')
        self.sns_conn = boto.sns.connect_to_region(BUCKET_REGION)

    def setup_infrastructure(self):
        topic_arn = self.create_sns_topic()
        self.set_sns_topic_policy(topic_arn)
        self.create_S3_bucket()
        self.set_S3_permissions()
        self.setup_S3_webserver()
        self.enable_bucket_notifications(topic_arn)

    def create_S3_bucket(self):
        """ Create a new S3 bucket if bucket not exists else nothing """
        try:
            self.s3_conn.create_bucket(self.bucket_name, location=BUCKET_REGION)
            logging.debug("Created new AWS S3 bucket with name '%s'", self.bucket_name)
        except boto.exception.S3CreateError as e:
            logging.debug("Could not create S3 bucket '%s': %s", self.bucket_name, e)

    def set_S3_permissions(self):
        policy = {
            "Version": "2012-10-17",
            "Statement": [{
                "Action": [
                    "s3:GetBucketWebsite",
                    "s3:GetObject",
                    "s3:ListBucket"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::{0}/*".format(self.bucket_name),
                    "arn:aws:s3:::{0}".format(self.bucket_name)
                ],
                "Principal": {
                    "AWS": self.allowed_aws_account_ids
                }
            }, {
                "Action": [
                    "s3:GetBucketWebsite",
                    "s3:GetObject",
                    "s3:ListBucket"
                ],
                "Effect": "Allow",
                "Resource": [
                    "arn:aws:s3:::{0}/*".format(self.bucket_name),
                    "arn:aws:s3:::{0}".format(self.bucket_name)
                ],
                "Condition": {
                    "IpAddress": {
                        "aws:SourceIp": self.allowed_ips
                    }
                },
                "Principal": {
                    "AWS": "*"
                }
            }
            ]
        }

        bucket = self.s3_conn.get_bucket(self.bucket_name)
        bucket.set_policy(json.dumps(policy))
        logging.debug("AWS S3 bucket '%s' now has policy: '%s'", self.bucket_name, policy)

    def create_sns_topic(self):
        response = self.sns_conn.create_topic(self.bucket_name)
        topic_arn = response['CreateTopicResponse']['CreateTopicResult']['TopicArn']
        logging.info("Using SNS topic with arn '%s'", topic_arn)

        return topic_arn

    def set_sns_topic_policy(self, topic_arn):
        allow_s3_events = {
            "Sid": "allow_s3_events",
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Principal": {
                "AWS": "*"
            },
            "Resource": topic_arn,
            "Condition": {
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:s3:*:*:{0}".format(self.bucket_name)
                }
            }
        }
        allow_subscribe_to_all_acconts = {
            "Sid": "allow_subscribe_to_all_acconts",
            "Effect": "Allow",
            "Action": [
                "sns:Subscribe"
            ],
            "Principal": {
                "AWS": self.allowed_aws_account_ids
            },
            "Resource": topic_arn
        }
        policy = {
            "Version": "2012-10-17",
            "Statement": [
                allow_s3_events,
                allow_subscribe_to_all_acconts
            ]
        }

        self.sns_conn.set_topic_attributes(topic_arn, 'Policy', json.dumps(policy))

    def enable_bucket_notifications(self, topic_arn):
        notification_configuration = {
            'TopicConfigurations': [
                {
                    'TopicArn': topic_arn,
                    'Events': ['s3:ObjectCreated:*']
                }
            ]
        }
        self.boto3_s3_client.put_bucket_notification_configuration(Bucket=self.bucket_name,
                                                                   NotificationConfiguration=notification_configuration)

    def get_routing_rules(self):
        routing_rules = boto.s3.website.RoutingRules()
        for suffix in ['json', 'yaml']:
            condition = boto.s3.website.Condition(key_prefix=suffix)
            redirect = boto.s3.website.Redirect(replace_key_prefix='accounts.{0}'.format(suffix))
            routing_rules.add_rule(boto.s3.website.RoutingRule(condition, redirect))
        return routing_rules

    def setup_S3_webserver(self):
        bucket = self.s3_conn.get_bucket(self.bucket_name)

        index_key = bucket.new_key('accounts.json')
        index_key.content_type = 'application/json'

        # now set the website configuration for our bucket
        bucket.configure_website(suffix='accounts.json', routing_rules=self.get_routing_rules())
        logging.debug("Website configuration was setup for AWS S3 bucket '%s'", self.bucket_name)

    def upload_to_S3(self, upload_data):
        bucket = self.s3_conn.get_bucket(self.bucket_name)
        key = boto.s3.key.Key(bucket)

        for key_name, content in upload_data.items():
            key.key = key_name
            key.set_contents_from_string(content)
            logging.debug("Uploaded to AWS S3 bucket '%s': "
                          "key '%s' and content '%s'", self.bucket_name, key_name, content)
<|endoftext|>


<commit_before>import sys
myNode = r'''
$[nodeName]
'''.strip()

# This will be one of three: ALL_RUNNING, ALL_STOPPED, NODEAGENT_RUNNING
successCriteria = r'''
$[successCriteria]
'''.strip()

def showServerStatus(serverName, nodeName):
    serverObj = AdminControl.completeObjectName('WebSphere:type=Server,node=' + nodeName + ',name=' + serverName + ',*')
    if len(serverObj) > 0:
        serverStatus = AdminControl.getAttribute(serverObj, 'state')
    else:
        serverStatus = 'STOPPED'

    return serverStatus

def checkServerByCriteria(serverName, serverStatus, successCriteria):
    if successCriteria == 'ALL_RUNNING':
        if serverStatus != 'STARTED':
            return 0
    elif successCriteria == 'ALL_STOPPED':
        if serverStatus == 'STARTED':
            return 0
    else:
        if serverName == 'nodeagent' and serverStatus != 'STARTED':
            return 0
    # end of conditions
    return 1

nodeFound = 0
errorsCount = 0

for node in AdminConfig.list( 'Node' ).splitlines() :
    nodeName = AdminConfig.showAttribute( node, 'name' )
    if myNode != nodeName :
        continue
    nodeFound = 1
    print '\n\n\n'
    for server in AdminConfig.list( 'Server', node ).splitlines() :
        serverName = AdminConfig.showAttribute( server, 'name' )
        serverStatus = showServerStatus(serverName, nodeName)
        # if serverStatus != 'STARTED':
        if not checkServerByCriteria(serverName, serverStatus, successCriteria):
            errorsCount += 1
        print '  Node: %s\nServer: %s\nStatus: %s\n' % ( nodeName, serverName, serverStatus )
        print '==========\n'

if not nodeFound:
    print 'Node with name %s wasn\'t found' % myNode
    sys.exit(1)

if errorsCount > 0:
    print "Success Criteria wasn't met."
    sys.exit(1)

print "Success Criteria was met."
<commit_msg>indentation update<commit_after>import sys
myNode = r'''
$[nodeName]
'''.strip()

# This will be one of three: ALL_RUNNING, ALL_STOPPED, NODEAGENT_RUNNING
successCriteria = r'''
$[successCriteria]
'''.strip()

def showServerStatus(serverName, nodeName):
    serverObj = AdminControl.completeObjectName('WebSphere:type=Server,node=' + nodeName + ',name=' + serverName + ',*')
    if len(serverObj) > 0:
        serverStatus = AdminControl.getAttribute(serverObj, 'state')
    else:
        serverStatus = 'STOPPED'

    return serverStatus

def checkServerByCriteria(serverName, serverStatus, successCriteria):
    if successCriteria == 'ALL_RUNNING':
        if serverStatus != 'STARTED':
            return 0
    elif successCriteria == 'ALL_STOPPED':
        if serverStatus == 'STARTED':
            return 0
    else:
        if serverName == 'nodeagent' and serverStatus != 'STARTED':
            return 0
    # end of conditions
    return 1

nodeFound = 0
errorsCount = 0

for node in AdminConfig.list('Node').splitlines() :
    nodeName = AdminConfig.showAttribute(node, 'name')
    if myNode != nodeName :
        continue
    nodeFound = 1
    print '\n\n\n'
    for server in AdminConfig.list('Server', node).splitlines() :
        serverName = AdminConfig.showAttribute(server, 'name')
        serverStatus = showServerStatus(serverName, nodeName)
        # if serverStatus != 'STARTED':
        if not checkServerByCriteria(serverName, serverStatus, successCriteria):
            errorsCount += 1
        print '  Node: %s\nServer: %s\nStatus: %s\n' % (nodeName, serverName, serverStatus)
        print '==========\n'

if not nodeFound:
    print 'Node with name %s wasn\'t found' % myNode
    sys.exit(1)

if errorsCount > 0:
    print "Success Criteria wasn't met."
    sys.exit(1)

print "Success Criteria was met."
<|endoftext|>


<commit_before>import sys
import os
import cv2 as opencv

class ImageFileWriter:
	def __init__(self):
		pass

	def write_images(self, *args):
		image_directory = '/root/ghisallo_venv/src/opencv_direction_indicator_detection/oop/test_images/'
		if len(args) % 2 != 0:
			print('argument error: got not enough names for files to write.')
		else:
			# save all images with their given names
			index = 0
			while index < len(args):
				file_name = args[index+0]
				image_data = args[index+1]
				file_path = os.path.join(image_directory, file_name)
				print('writing image file to', file_path)
				opencv.imwrite(file_path, image_data, (opencv.IMWRITE_PNG_COMPRESSION, 0))
				index += 2
<commit_msg>added image color space conversion before writting image using opencv<commit_after>import sys
import os
import cv2 as opencv

class ImageFileWriter:
	def __init__(self):
		pass

	def write_images(self, *args):
		image_directory = '/root/ghisallo_venv/src/opencv_direction_indicator_detection/oop/test_images/'
		if len(args) % 2 != 0:
			print('argument error: got not enough names for files to write.')
		else:
			# save all images with their given names
			index = 0
			while index < len(args):
				file_name = args[index+0]
				image_data = args[index+1]
				file_path = os.path.join(image_directory, file_name)
				print('writing image file to', file_path)

				image = opencv.cvtColor(image_data, cv2.COLOR_RGB2BGR)  # images might need to be converted to be correctly written by opencv
				opencv.imwrite(file_path, image_data, (opencv.IMWRITE_PNG_COMPRESSION, 0))
				index += 2
<|endoftext|>


<commit_before>from accelerator_abstract.models import (
    FORM_ELEM_FEEDBACK_TO_MC,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_OVERALL_RECOMMENDATION,
)

from accelerator.models import (
    ASSIGNED_PANEL_ASSIGNMENT_STATUS,
    COMPLETE_PANEL_ASSIGNMENT_STATUS,
    FEEDBACK_DISPLAY_DISABLED as DISABLED,
    FEEDBACK_DISPLAY_ENABLED as ENABLED,
    PREVIEW_PANEL_STATUS,
    SUBMITTED_APP_STATUS,
    UserRole,
)
from accelerator.tests.factories import (
    ApplicationAnswerFactory,
    ApplicationFactory,
    ApplicationPanelAssignmentFactory,
    JudgeApplicationFeedbackFactory,
    JudgeFeedbackComponentFactory,
    JudgePanelAssignmentFactory,
    JudgingFormElementFactory,
    JudgingRoundFactory,
    PanelFactory,
    ProgramCycleFactory,
    ProgramRoleGrantFactory,
    ScenarioFactory,
    StartupCycleInterestFactory,
    StartupProgramInterestFactory,
)

ELEMENT_NAMES = [
    FORM_ELEM_OVERALL_RECOMMENDATION,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_FEEDBACK_TO_MC,
]

class JudgeFeedbackContext:
    def __init__(self,
                 application=None,
                 num_components=1,
                 complete=True,
                 panel_status=PREVIEW_PANEL_STATUS,
                 display_feedback=False,
                 merge_feedback_with=None,
                 cycle_based_round=False):
        if application:
            self.application = application
            self.cycle = application.cycle
        else:
            self.cycle = ProgramCycleFactory()
            self.application = ApplicationFactory(
                application_status=SUBMITTED_APP_STATUS,
                application_type=self.cycle.default_application_type,
                cycle=self.cycle)
        self.application_type = self.application.application_type
        self.applications = [self.application]
        self.startup = self.application.startup
        self.industry = self.startup.primary_industry
        feedback_display = ENABLED if display_feedback else DISABLED
        jr_kwargs = {
            'program__cycle': self.cycle,
            'round_type': "Online",
            'feedback_display': feedback_display,
            'cycle_based_round': cycle_based_round,
            'application_type': self.application_type,
        }
        if merge_feedback_with:
            jr_kwargs['feedback_merge_with'] = merge_feedback_with
        self.judging_round = JudgingRoundFactory(**jr_kwargs)
        self.program = self.judging_round.program
        self.feedback = JudgeApplicationFeedbackFactory(
            judge__profile__primary_industry=self.industry,
            judge__profile__home_program_family=self.program.program_family,
            application=self.application,
            panel__status=panel_status,
            panel__panel_time__judging_round=self.judging_round,
            form_type=self.judging_round.judging_form)
        self.judge = self.feedback.judge

        ProgramRoleGrantFactory(
            person=self.judge,
            program_role__user_role__name=UserRole.JUDGE)
        self.judging_round.confirmed_judge_label.users.add(self.judge)
        self.judging_form = self.feedback.form_type
        self.panel = self.feedback.panel
        self.scenario = ScenarioFactory(judging_round=self.judging_round)
        self.application_assignment = ApplicationPanelAssignmentFactory(
            application=self.application,
            panel=self.panel,
            scenario=self.scenario)
        cycle_interest = StartupCycleInterestFactory(cycle=self.program.cycle,
                                                     startup=self.startup)
        StartupProgramInterestFactory(program=self.program,
                                      startup=self.startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True)
        if complete:
            assignment_status = COMPLETE_PANEL_ASSIGNMENT_STATUS
        else:
            assignment_status = ASSIGNED_PANEL_ASSIGNMENT_STATUS
        self.judge_assignment = JudgePanelAssignmentFactory(
            assignment_status=assignment_status,
            judge=self.judge,
            panel=self.panel,
            scenario=self.scenario)
        self.components = []
        self.elements = []
        self.application_questions = []
        self.application_answers = []
        for element_name in ELEMENT_NAMES:
            self.add_component(element_name=element_name)

        if complete:
            self.feedback.save()
            for _ in range(num_components):
                self.add_component()
        else:
            for _ in range(num_components):
                self.add_element()

    def add_application_answer(self, question=None, answer_text=None):
        question = question or self.application_questions[0]
        kwargs = {"application_question": question,
                  "application": self.application}
        if answer_text:
            kwargs["answer_text"] = answer_text
        app_answer = ApplicationAnswerFactory(**kwargs)
        self.application_answers.append(app_answer)
        return app_answer

    def add_component(self, element_name=None,
                      feedback_element=None,
                      add_answer=True,
                      answer_text=None):

        factory_params = {
            "judge_feedback": self.feedback, }

        if feedback_element is None:
            app_type_key = "__".join(["feedback_element",
                                      "application_question",
                                      "application_type"])
            factory_params.update(
                {
                    "feedback_element__form_type": self.judging_form,
                    "feedback_element__element_type": "feedback",
                    "feedback_element__mandatory": True,
                    "feedback_element__sharing": "share-with-startup",
                    app_type_key: self.application_type}
            )
            if element_name:
                factory_params['feedback_element__element_name'] = element_name
        else:
            factory_params.update({"feedback_element": feedback_element})

        if answer_text:
            factory_params["answer_text"] = answer_text

        component = JudgeFeedbackComponentFactory(
            **factory_params)
        self.components.append(component)
        question = component.feedback_element.application_question
        self.application_questions.append(question)
        if add_answer:
            app_answer = ApplicationAnswerFactory(
                application_question=question,
                application=self.application)
            self.application_answers.append(app_answer)
        if feedback_element is None:
            self.elements.append(component.feedback_element)
        self.feedback.save()
        return component

    def add_element(self, feedback_type="",
                    choice_layout="",
                    mandatory=True,
                    text_minimum=0,
                    text_minimum_units="",
                    answer_text=None):
        element = JudgingFormElementFactory(
            form_type=self.judging_form,
            mandatory=mandatory,
            element_type="feedback",
            feedback_type=feedback_type,
            choice_layout=choice_layout,
            sharing="share-with-startup",
            application_question__application_type=self.application_type,
            text_minimum=text_minimum,
            text_minimum_units=text_minimum_units
        )
        application_question = element.application_question
        self.application_questions.append(application_question)
        answer_kwargs = {"application_question": application_question,
                         "application": self.application}
        if answer_text:
            answer_kwargs["answer_text"] = answer_text
        application_answer = ApplicationAnswerFactory(**answer_kwargs)
        self.application_answers.append(application_answer)
        self.elements.append(element)
        self.feedback.save()
        return element

    def add_extra_scenario(self):
        return ScenarioFactory(judging_round=self.judging_round)

    def add_panel(self):
        return PanelFactory(
            panel_time__judging_round=self.judging_round,
            panel_type__judging_round=self.judging_round,
            location__judging_round=self.judging_round)

    def add_assignment(self,
                       judge=None,
                       panel=None,
                       scenario=None):
        scenario = scenario or self.scenario
        judge = judge or self.judge
        panel = panel or self.panel
        return JudgePanelAssignmentFactory(
            judge=judge,
            panel=panel,
            scenario=scenario)

    def add_feedback(self,
                     application=None,
                     judge=None,
                     panel=None):
        return JudgeApplicationFeedbackFactory(
            judge=judge or self.judge,
            application=application or self.application,
            panel=panel or PanelFactory(
                panel_time__judging_round=self.judging_round),
            form_type=self.judging_round.judging_form)

    def add_application(self, application=None):
        if application is None:
            application = ApplicationFactory(
                application_status=SUBMITTED_APP_STATUS,
                application_type=self.application_type)
        self.applications.append(application)
        startup = application.startup
        cycle_interest = StartupCycleInterestFactory(cycle=self.program.cycle,
                                                     startup=startup)
        StartupProgramInterestFactory(program=self.program,
                                      startup=startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True)

    @classmethod
    def create_batch(cls, qty, *args, **kwargs):
        if 'merge_feedback' in kwargs:
            merge_feedback = kwargs.pop('merge_feedback')
        else:
            merge_feedback = False
        contexts = [cls(*args, **kwargs)]
        if merge_feedback:
            kwargs['merge_feedback_with'] = contexts[0].judging_round
        for _ in range(1, qty):
            contexts.append(cls(*args, **kwargs))
        return contexts
<commit_msg>Add is_active flag to JudgeFeedbackContext<commit_after>from accelerator_abstract.models import (
    FORM_ELEM_FEEDBACK_TO_MC,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_OVERALL_RECOMMENDATION,
)

from accelerator.models import (
    ASSIGNED_PANEL_ASSIGNMENT_STATUS,
    COMPLETE_PANEL_ASSIGNMENT_STATUS,
    FEEDBACK_DISPLAY_DISABLED as DISABLED,
    FEEDBACK_DISPLAY_ENABLED as ENABLED,
    PREVIEW_PANEL_STATUS,
    SUBMITTED_APP_STATUS,
    UserRole,
)
from accelerator.tests.factories import (
    ApplicationAnswerFactory,
    ApplicationFactory,
    ApplicationPanelAssignmentFactory,
    JudgeApplicationFeedbackFactory,
    JudgeFeedbackComponentFactory,
    JudgePanelAssignmentFactory,
    JudgingFormElementFactory,
    JudgingRoundFactory,
    PanelFactory,
    ProgramCycleFactory,
    ProgramRoleGrantFactory,
    ScenarioFactory,
    StartupCycleInterestFactory,
    StartupProgramInterestFactory,
)

ELEMENT_NAMES = [
    FORM_ELEM_OVERALL_RECOMMENDATION,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_FEEDBACK_TO_MC,
]

class JudgeFeedbackContext:
    def __init__(self,
                 application=None,
                 num_components=1,
                 complete=True,
                 panel_status=PREVIEW_PANEL_STATUS,
                 display_feedback=False,
                 merge_feedback_with=None,
                 cycle_based_round=False,
                 is_active=True):
        if application:
            self.application = application
            self.cycle = application.cycle
        else:
            self.cycle = ProgramCycleFactory()
            self.application = ApplicationFactory(
                application_status=SUBMITTED_APP_STATUS,
                application_type=self.cycle.default_application_type,
                cycle=self.cycle)
        self.application_type = self.application.application_type
        self.applications = [self.application]
        self.startup = self.application.startup
        self.industry = self.startup.primary_industry
        feedback_display = ENABLED if display_feedback else DISABLED
        jr_kwargs = {
            'program__cycle': self.cycle,
            'round_type': "Online",
            'feedback_display': feedback_display,
            'cycle_based_round': cycle_based_round,
            'application_type': self.application_type,
            'is_active': is_active,
        }
        if merge_feedback_with:
            jr_kwargs['feedback_merge_with'] = merge_feedback_with
        self.judging_round = JudgingRoundFactory(**jr_kwargs)
        self.program = self.judging_round.program
        self.feedback = JudgeApplicationFeedbackFactory(
            judge__profile__primary_industry=self.industry,
            judge__profile__home_program_family=self.program.program_family,
            application=self.application,
            panel__status=panel_status,
            panel__panel_time__judging_round=self.judging_round,
            form_type=self.judging_round.judging_form)
        self.judge = self.feedback.judge

        ProgramRoleGrantFactory(
            person=self.judge,
            program_role__user_role__name=UserRole.JUDGE)
        self.judging_round.confirmed_judge_label.users.add(self.judge)
        self.judging_form = self.feedback.form_type
        self.panel = self.feedback.panel
        self.scenario = ScenarioFactory(judging_round=self.judging_round)
        self.application_assignment = ApplicationPanelAssignmentFactory(
            application=self.application,
            panel=self.panel,
            scenario=self.scenario)
        cycle_interest = StartupCycleInterestFactory(cycle=self.program.cycle,
                                                     startup=self.startup)
        StartupProgramInterestFactory(program=self.program,
                                      startup=self.startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True)
        if complete:
            assignment_status = COMPLETE_PANEL_ASSIGNMENT_STATUS
        else:
            assignment_status = ASSIGNED_PANEL_ASSIGNMENT_STATUS
        self.judge_assignment = JudgePanelAssignmentFactory(
            assignment_status=assignment_status,
            judge=self.judge,
            panel=self.panel,
            scenario=self.scenario)
        self.components = []
        self.elements = []
        self.application_questions = []
        self.application_answers = []
        for element_name in ELEMENT_NAMES:
            self.add_component(element_name=element_name)

        if complete:
            self.feedback.save()
            for _ in range(num_components):
                self.add_component()
        else:
            for _ in range(num_components):
                self.add_element()

    def add_application_answer(self, question=None, answer_text=None):
        question = question or self.application_questions[0]
        kwargs = {"application_question": question,
                  "application": self.application}
        if answer_text:
            kwargs["answer_text"] = answer_text
        app_answer = ApplicationAnswerFactory(**kwargs)
        self.application_answers.append(app_answer)
        return app_answer

    def add_component(self, element_name=None,
                      feedback_element=None,
                      add_answer=True,
                      answer_text=None):

        factory_params = {
            "judge_feedback": self.feedback, }

        if feedback_element is None:
            app_type_key = "__".join(["feedback_element",
                                      "application_question",
                                      "application_type"])
            factory_params.update(
                {
                    "feedback_element__form_type": self.judging_form,
                    "feedback_element__element_type": "feedback",
                    "feedback_element__mandatory": True,
                    "feedback_element__sharing": "share-with-startup",
                    app_type_key: self.application_type}
            )
            if element_name:
                factory_params['feedback_element__element_name'] = element_name
        else:
            factory_params.update({"feedback_element": feedback_element})

        if answer_text:
            factory_params["answer_text"] = answer_text

        component = JudgeFeedbackComponentFactory(
            **factory_params)
        self.components.append(component)
        question = component.feedback_element.application_question
        self.application_questions.append(question)
        if add_answer:
            app_answer = ApplicationAnswerFactory(
                application_question=question,
                application=self.application)
            self.application_answers.append(app_answer)
        if feedback_element is None:
            self.elements.append(component.feedback_element)
        self.feedback.save()
        return component

    def add_element(self, feedback_type="",
                    choice_layout="",
                    mandatory=True,
                    text_minimum=0,
                    text_minimum_units="",
                    answer_text=None):
        element = JudgingFormElementFactory(
            form_type=self.judging_form,
            mandatory=mandatory,
            element_type="feedback",
            feedback_type=feedback_type,
            choice_layout=choice_layout,
            sharing="share-with-startup",
            application_question__application_type=self.application_type,
            text_minimum=text_minimum,
            text_minimum_units=text_minimum_units
        )
        application_question = element.application_question
        self.application_questions.append(application_question)
        answer_kwargs = {"application_question": application_question,
                         "application": self.application}
        if answer_text:
            answer_kwargs["answer_text"] = answer_text
        application_answer = ApplicationAnswerFactory(**answer_kwargs)
        self.application_answers.append(application_answer)
        self.elements.append(element)
        self.feedback.save()
        return element

    def add_extra_scenario(self):
        return ScenarioFactory(judging_round=self.judging_round)

    def add_panel(self):
        return PanelFactory(
            panel_time__judging_round=self.judging_round,
            panel_type__judging_round=self.judging_round,
            location__judging_round=self.judging_round)

    def add_assignment(self,
                       judge=None,
                       panel=None,
                       scenario=None):
        scenario = scenario or self.scenario
        judge = judge or self.judge
        panel = panel or self.panel
        return JudgePanelAssignmentFactory(
            judge=judge,
            panel=panel,
            scenario=scenario)

    def add_feedback(self,
                     application=None,
                     judge=None,
                     panel=None):
        return JudgeApplicationFeedbackFactory(
            judge=judge or self.judge,
            application=application or self.application,
            panel=panel or PanelFactory(
                panel_time__judging_round=self.judging_round),
            form_type=self.judging_round.judging_form)

    def add_application(self, application=None):
        if application is None:
            application = ApplicationFactory(
                application_status=SUBMITTED_APP_STATUS,
                application_type=self.application_type)
        self.applications.append(application)
        startup = application.startup
        cycle_interest = StartupCycleInterestFactory(cycle=self.program.cycle,
                                                     startup=startup)
        StartupProgramInterestFactory(program=self.program,
                                      startup=startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True)

    @classmethod
    def create_batch(cls, qty, *args, **kwargs):
        if 'merge_feedback' in kwargs:
            merge_feedback = kwargs.pop('merge_feedback')
        else:
            merge_feedback = False
        contexts = [cls(*args, **kwargs)]
        if merge_feedback:
            kwargs['merge_feedback_with'] = contexts[0].judging_round
        for _ in range(1, qty):
            contexts.append(cls(*args, **kwargs))
        return contexts
<|endoftext|>