Skip to content
Snippets Groups Projects
addExperimentCli.py 7.72 KiB
Newer Older
from dm.aps_bss.api.apsBssApi import ApsBssApi
from dm.ds_web_service.api.experimentDsApi import ExperimentDsApi
from dm.ds_web_service.api.userDsApi import UserDsApi
from dm.common.exceptions.invalidRequest import InvalidRequest
from dm.common.utility.configurationManager import ConfigurationManager
from dsWebServiceSessionCli import DsWebServiceSessionCli

class AddExperimentCli(DsWebServiceSessionCli):
    def __init__(self):
        DsWebServiceSessionCli.__init__(self)
        configManager = ConfigurationManager.getInstance()
        self.allowedExperimentTypes = configManager.getAllowedExperimentTypes()
        allowedExperimentTypesHelp = ''
        if self.allowedExperimentTypes:
            allowedExperimentTypesHelp = ' Allowed types: %s' % self.allowedExperimentTypes
            

        self.addOption('', '--experiment', dest='experimentName', help='Experiment name.')
        self.addOption('', '--station', dest='stationName', help='Experiment station name, can also be set via DM_STATION_NAME environment variable.')
        self.addOption('', '--type', dest='typeName', help='Experiment type name.%s' % allowedExperimentTypesHelp)
        self.addOption('', '--type-id', dest='typeId', help='Experiment type id (may be given instead of type name; type id is ignored if both type name and id are provided).')
        self.addOption('', '--description', dest='description', help='Experiment description.')
        self.addOption('', '--start-date', dest='startDate', help='Experiment start date in format DD-MMM-YY.')
        self.addOption('', '--end-date', dest='endDate', help='Experiment end date in format DD-MMM-YY.')
        self.addOption('', '--users', dest='users', help='Comma-separated list of DM usernames to be added to the new experiment as users.')
        self.addOption('', '--proposal-id', dest='proposalId', help='Beamline proposal id. If specified, all users listed on the proposal will be added to the new experiment.')
        self.addOption('', '--run', dest='runName', help='Run name. If not specified, current run name is assumed for beamline proposal.')
        self.addOption('', '--bss-login-file', dest='bssLoginFile', help='BSS login file. Login file may also be specified via environment variable DM_BSS_LOGIN_FILE.')
        if self.options.experimentName is None:
            raise InvalidRequest('Experiment name must be provided.')
        if self.getTypeName() is None:
            raise InvalidRequest('Experiment type name must be provided.')
        if self.getStationName() is None:
            raise InvalidRequest('Experiment station name must be provided.')
        # If allowed experiment types is not set, there are no restrictions
        if self.allowedExperimentTypes:
            if self.getTypeName() not in self.allowedExperimentTypes.split(','):
                raise InvalidRequest('Experiment type %s is not allowed on this station. Allowed types are: %s.' % (self.getTypeName(), self.allowedExperimentTypes))
    def getExperimentName(self):
        return self.options.experimentName
    def getStationName(self):
        stationName = self.options.stationName
        if not stationName:
            configManager = ConfigurationManager.getInstance()
            stationName = configManager.getStationName()
        return stationName

    def getTypeName(self):
        typeName = self.options.typeName
        if not typeName:
            if self.options.typeId:
                api = ExperimentDsApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
                experimentType = api.getExperimentTypeById(typeId)
                typeName = experimentType.get('name')
                self.options.typeName = typeName
        return typeName

    def getDescription(self):
        return self.options.description

    def getStartDate(self):
        return self.options.startDate

    def getEndDate(self):
        return self.options.endDate

    def getProposalId(self):
        proposalId = self.options.proposalId
        if proposalId:
            proposalId = int(proposalId)
        return proposalId

    def getUsers(self):
        # Return list of users and beamline managers that can access data
            users = users.split(',')
        beamlineManagers = ConfigurationManager.getInstance().getBeamlineManagers()
        if beamlineManagers:
            beamlineManagers = beamlineManagers.split(',')
        else:
            beamlineManagers = []
        # Remove duplicates by converting into set
        return list(set(users+beamlineManagers))
    def runCommand(self):
        self.parseArgs(usage="""
    dm-add-experiment 
        --experiment=EXPERIMENTNAME --station=STATIONNAME --type=TYPENAME|--type-id=TYPEID
        [--description=DESCRIPTION] 
        [--start-date=STARTDATE] 
        [--end-date=ENDDATE]
        [--users=USERS]
        [--proposal-id=PROPOSALID]
        [--run=RUNNAME]
        [--bss-login-file=BSSLOGINFILE]
    Add new experiment to the DM database. If list of users or proposal id is specified, this command will also add roles for all users listed on the proposal.
        dsExperimentApi = ExperimentDsApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
        dsUserApi = UserDsApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())

        description = self.getDescription()
        proposalId = self.getProposalId()
        experimenters = []
        if proposalId:
            bssApi = ApsBssApi(loginFile=self.options.bssLoginFile)
            proposal = bssApi.getBeamlineProposal(proposalId=proposalId, runName=self.options.runName)
            experimenters = proposal.get('experimenters', [])
            if not description:
                description = '%s (Proposal id: %s)' % (proposal['title'], proposalId)


        users = self.getUsers()
        pis = []
        for experimenter in experimenters:
            badge = int(experimenter['badge'])
            if not badge:
                #print 'Skipping user %s due to invalid badge.' % lastName 
                continue
            username = 'd%s' % badge

            # Clasify user
            if experimenter.get('piFlag') == 'Y':
                if not pis.count(username):
                    pis.append(username)
                if users.count(username):
                    users.remove(username)
            else:
                if not users.count(username):
                    users.append(username)

        for username in users+pis:
            # Check that user exists
            dsUserApi.getUserByUsername(username)
           

        # Everything looks good, add experiment and users
        experiment = dsExperimentApi.addExperiment(self.getExperimentName(), self.getStationName(), self.getTypeName(), description, self.getStartDate(), self.getEndDate())

        # Add pis.
        experimentName = experiment['name']
        roleName = 'PI'
        for username in pis:
            dsUserApi.addUserExperimentRole(username, roleName, experimentName)
        roleName = 'User'
        for username in users:
            dsUserApi.addUserExperimentRole(username, roleName, experimentName)

        if len(users+pis):
            experiment = dsExperimentApi.getExperimentByName(experimentName)
        print experiment.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())

#######################################################################
# Run command.
if __name__ == '__main__':
    cli = AddExperimentCli()
    cli.run()