示例#1
0
    def _form_upload_post(self, send_status):
        """Process the POST request and create new Model resource from form data.

        :param send_status: callback method to signal completion
        """
        import time
        data = self.application.data
        ctx = yield self._create_upload_context()
        now = time.clock()

        content_type = self.handler.request.headers["Content-Type"]
        if not content_type.startswith("multipart/form-data;"):
            send_status(415, ctx)
            return

        ctx.model["lattice_id"] = self.handler.get_argument("lattice_id", "")
        if len(ctx.model["lattice_id"]) == 0:
            ctx.errors["lattice_id"] = "Lattice is required"
        else:
            ctx.model["lattice_id"] = ObjectId(ctx.model["lattice_id"])
            for lattice in ctx.lattices:
                if lattice._id == ctx.model["lattice_id"]:
                    break
            else:
                ctx.errors["lattice_id"] = "Lattice not found"

        ctx.model.name = self.handler.get_argument("name", "")
        if len(ctx.model.name) == 0:
            ctx.errors.name = "Name is required"

        ctx.model.description = self.handler.get_argument("description", "")

        ctx.model.status_type = self.handler.get_argument("status_type", "")

        ctx.model.created_by = self.handler.current_user

        ctx.model.created_date = datetime.now()

        ctx.model._id = ObjectId()

        ctx.model.files = []

        file_content = {}

        request_files = self.handler.request.files

        modelfiles = {
            "fort18":"model_fort18",
            "fort24":"model_fort24",
            "fort25":"model_fort25",
            "fort26":"model_fort26"
        }

        modelargs = {}

        for key, name in modelfiles.iteritems():
            if name in request_files and len(request_files[name]) > 0:
                modelargs[key] = StringIO(request_files[name][0].body)
                # find a unique file ID
                while True:
                    file_id=_create_file_id()
                    if file_id not in file_content:
                        break
                ctx.model.files.append(ObjectDict(
                    id=file_id,
                    name="ModelData",
                    size=len(request_files[name][0].body),
                    filename=request_files[name][0].filename,
                    location=_create_file_location(request_files[name][0])
                ))
                file_content[file_id] = request_files[name][0].body
            else:
                ctx.errors[name] = "Model data file is required"

        if ctx.errors:
            send_status(400, ctx)
            return

        for p in lattice.properties:
            if p.name == "OutputMode":
                outputMode = p.value
                break
        else:
            ctx.errors.lattice_id = "Lattice missing 'OutputMode' property"
            send_status(400, ctx)
            return

        if outputMode not in [1, 2, 3, 4, 5, 6]:
            ctx.errors.lattice_id = "Lattice 'OutputMode' unsupported"
            send_status(400, ctx)
            return

        try:
            model = build_result(**modelargs)
        except Exception as e:
            LOGGER.warning("Error building model: %s", e)
            ctx.errors._global = "Model invalid format"
            send_status(400, ctx)
            return

        ctx.model.properties = []

        if "attachments" in request_files:
            for attachment_file in request_files["attachments"]:
                while True:
                    file_id=_create_file_id()
                    if file_id not in file_content:
                        break
                ctx.model.files.append(ObjectDict(
                    id=file_id,
                    name="Attachment",
                    size=len(attachment_file.body),
                    filename=attachment_file.filename,
                    location=_create_file_location(attachment_file)
                ))
                file_content[file_id] = attachment_file.body


        attachment_path = self.settings.get("attachment_path", "")
        if len(attachment_path) == 0:
            LOGGER.warn("setting 'attachment_path' not found")
            ctx.errors._global = "Attachment directory not specified"
            send_status(500, ctx)
            return


        try:
            yield data.validate_model(ctx.model)
        except Exception as e:
            LOGGER.error("model validation error: %s", e)
            ctx.errors._global = "Model validation error"
            send_status(500, ctx)
            return

        idx = -1
        if outputMode in [1, 2]:
            # First line of data file is initial
            # values BEFORE the first element.
            idx = 0

        model_elements = []

        lattice_elements = yield data.find_lattice_elements_by_lattice_id(
                                                        ctx.model.lattice_id)

        for lattice_element in lattice_elements:

            for p in lattice_element.properties:
                if p.name == "ITYPE":
                    elem_itype =  p.value
                    break
            else:
                ctx.errors._global = ("Lattice Element ({}) missing ITYPE property"
                                                    .format(lattice_element.order))
                send_status(400, ctx)
                return

            for p in lattice_element.properties:
                if p.name == "STEPS":
                    elem_steps =  p.value
                    break
            else:
                ctx.errors._global = ("Lattice Element ({}) missing STEPS property"
                                                    .format(lattice_element.order))
                send_status(400, ctx)
                return

            if outputMode in [1, 2]:
                loop = elem_steps
                if elem_itype in [ -2, 4 ]:
                    # no output for these elements
                    loop = 0
                elif elem_itype < 0:
                    loop = elem_steps + 1
            elif outputMode in [3, 4]:
                loop = 0
                if elem_itype == -28:
                    # only output from monitor
                    loop = 1
            elif outputMode in [5, 6]:
                loop = 1

            for _ in range(loop):

                idx += 1

                try:
                    model_element = ObjectDict()
                    model_element._id = ObjectId()
                    model_element.order = idx+1
                    model_element.model_id = ctx.model._id
                    model_element.lattice_element_id = lattice_element._id
                    model_element.position = model.getSPosition(idx)
                    model_element.properties = []
                    model_element.properties.append(dict(
                        name="BeamCenterX",
                        value=model.getOrbit("X", idx),
                        unit="mm"
                    ))
                    model_element.properties.append(dict(
                        name="BeamCenterY",
                        value=model.getOrbit("Y", idx),
                        unit="mm"
                    ))
                    model_element.properties.append(dict(
                        name="BeamEnergy",
                        value=model.getEnergy(idx),
                        unit="eV"
                    ))
                    model_element.properties.append(dict(
                        name="BeamMomentumCenterX",
                        value=model.getBeamMomentumCentroid("X", idx),
                        unit="rad"
                    ))
                    model_element.properties.append(dict(
                        name="BeamMomentumCenterY",
                        value=model.getBeamMomentumCentroid("Y", idx),
                        unit="rad"
                    ))
                    model_element.properties.append(dict(
                        name="BeamMomentumCenterZ",
                        value=model.getBeamMomentumCentroid("Z", idx),
                        unit="MeV"
                    ))
                    model_element.properties.append(dict(
                        name="BeamRMSX",
                        value=model.getBeamRms("X", idx),
                        unit="mm"
                    ))
                    model_element.properties.append(dict(
                        name="BeamRMSY",
                        value=model.getBeamRms("Y", idx),
                        unit="mm"
                    ))
                    model_element.properties.append(dict(
                        name="BeamRMSZ",
                        value=model.getBeamRms("Z", idx),
                        unit="deg"
                    ))
                    model_element.properties.append(dict(
                        name="BeamMomentumRMSX",
                        value=model.getMomentumRms("X", idx),
                        unit="rad"
                    ))
                    model_element.properties.append(dict(
                        name="BeamMomentumRMSY",
                        value=model.getMomentumRms("Y", idx),
                        unit="rad"
                    ))
                    model_element.properties.append(dict(
                        name="BeamMomentumRMSZ",
                        value=model.getMomentumRms("Z", idx),
                        unit="MeV"
                    ))
                    model_element.properties.append(dict(
                        name="EmittanceX",
                        value=model.getEmittance("X", idx),
                        unit="m-rad"
                    ))
                    model_element.properties.append(dict(
                        name="EmittanceY",
                        value=model.getEmittance("Y", idx),
                        unit="m-rad"
                    ))
                    model_element.properties.append(dict(
                        name="EmittanceZ",
                        value=model.getEmittance("Z", idx),
                        unit="m-rad"
                    ))
                    model_element.properties.append(dict(
                        name="TwissBetaX",
                        value=model.getTwissBeta("X", idx),
                        unit=""
                    ))
                    model_element.properties.append(dict(
                        name="TwissBetaY",
                        value=model.getTwissBeta("Y", idx),
                        unit=""
                    ))
                    model_element.properties.append(dict(
                        name="TwissBetaZ",
                        value=model.getTwissBeta("Z", idx),
                        unit=""
                    ))
                    model_element.properties.append(dict(
                        name="TwissAlphaX",
                        value=model.getTwissAlpha("X", idx),
                        unit=""
                    ))
                    model_element.properties.append(dict(
                        name="TwissAlphaY",
                        value=model.getTwissAlpha("Y", idx),
                        unit=""
                    ))
                    model_element.properties.append(dict(
                        name="TwissAlphaZ",
                        value=model.getTwissAlpha("Z", idx),
                        unit=""
                    ))
                except IndexError:
                    ctx.errors._global = ("Model data not found at index: {}".format(idx))
                    send_status(400, ctx)
                    return

                try:
                    data.validate_model_element(model_element)
                except:
                    LOGGER.exception("model element validation error: %s", e)
                    ctx.errors._global = "Model Element validation error"
                    send_status(500, ctx)
                    return

                model_elements.append(model_element)

        try:
            yield data.insert_model(ctx.model, validate=False)
        except Exception as e:
            LOGGER.error("lattice database insert error: %s", e)
            ctx.errors._global = "Lattice database insert error"
            send_status(500, ctx)
            return


        try:
            for model_element in model_elements:
                #lattice_element.lattice_id = lattice_id
                data.insert_model_element(model_element, validate=False)
        except Exception as e:
            LOGGER.error("model element database insert error: %s", e)
            ctx.errors._global = "Mattice element database insert error"
            # Rollback?
            send_status(500, ctx)
            return


        try:
            for f in ctx.model.files:
                _write_file_content(attachment_path, f.location, file_content[f.id])
        except Exception as e:
            LOGGER.error("model attachment write error: %s", e)
            ctx.errors._global = "Model attachment write error"
            #Rollback?
            send_status(500, ctx)
            return

        LOGGER.debug("model processing complete: %ss", (time.clock() - now))

        send_status(201, ctx)
        return
示例#2
0
    def _form_upload_post(self, send_status):
        """Process the request and create new Lattice resource.

        :param send_status: callback method to signal completion
        """
        data = self.application.data
        ctx = yield self._create_upload_context()

        content_type = self.handler.request.headers["Content-Type"]
        if not content_type.startswith("multipart/form-data;"):
            send_status(415)
            return

        ctx.lattice.particle_type = self.handler.get_argument("particle_type", "")
        if len(ctx.lattice.particle_type) == 0:
            ctx.errors.particle_type = "Particle Type is required"
        else:
            for p in ctx.particle_types:
                if p["type"] == ctx.lattice.particle_type:
                    particle_type = ObjectDict(p)
                    break
            else:
                ctx.errors.particle_type = "Particle Type '{}' is invalid" \
                                             .format(ctx.lattice.particle_type)

        ctx.lattice.name = self.handler.get_argument("name", "")
        if len(ctx.lattice.name) == 0:
            ctx.errors.name = "Name is required"

        ctx.lattice.branch = self.handler.get_argument("branch", "")
        if len(ctx.lattice.branch) == 0:
            ctx.errors.branch = "Branch is required"

        if self.handler.get_argument("autoversion", "off") == "on":
            ctx.lattice_autoversion = True
        else:
            ctx.lattice_autoversion = False

        ctx.lattice.version = self.handler.get_argument("version", "")
        if not ctx.lattice_autoversion:
            if len(ctx.lattice.version) == 0:
                ctx.errors.version = "Version is required"
            else:
                try:
                    ctx.lattice.version = int(ctx.lattice.version)
                except ValueError:
                    ctx.lattice.version = self._INITIAL_VERSION
                    ctx.errors.version = "Version must be an integer"
                if ctx.lattice.version <= 0:
                    ctx.errors.version = "Version must be greater than zero"

        ctx.lattice.description = self.handler.get_argument("description", "")

        ctx.lattice.status_type = self.handler.get_argument("status_type", "")

        ctx.lattice.created_by = self.handler.current_user

        ctx.lattice.created_date = datetime.now()

        ctx.lattice._id = ObjectId()

        request_files = self.handler.request.files

        if "lattice_file" not in request_files:
            ctx.errors.lattice_file = "Lattice File is required"

        elif len(request_files["lattice_file"]) == 0:
            ctx.errors.lattice_file = "Lattice File is required"

        if ctx.errors:
            send_status(400, ctx)
            return

        # check for another lattice with name, branch and version
        if ctx.lattice_autoversion:
            lattice = yield data.find_lattice_by_name(ctx.lattice.name,
                                                        ctx.lattice.branch)
        else:
            lattice = yield data.find_lattice_by_name(ctx.lattice.name,
                                    ctx.lattice.branch, ctx.lattice.version)

        if ctx.lattice_autoversion:
            if lattice:
                ctx.lattice.version = lattice.version + 1
            else:
                ctx.lattice.version = self._INITIAL_VERSION
        else:
            if lattice:
                ctx.errors.version = "Version already exists"

        if ctx.errors:
            send_status(400, ctx)
            return

        lattice_file = request_files["lattice_file"][0]

        try:
            lattice = read_lattice(StringIO(lattice_file.body))
        except Exception as e:
            LOGGER.warning("Error reading lattice: %s", e)
            ctx.errors.lattice_file = "Lattice File invalid format"

        if ctx.errors:
            send_status(400, ctx)
            return

        ctx.lattice.properties = []

        ctx.lattice.properties.append(dict(
            name="ParticleMass",
            value=lattice.particleMass,
            unit="MeV/c^2"
        ))

        ctx.lattice.properties.append(dict(
            name="ParticleCount",
            value=lattice.nparticles
        ))

        ctx.lattice.properties.append(dict(
            name="ParticleCurrent",
            value=lattice.current,
            unit="A"
        ))

        ctx.lattice.properties.append(dict(
            name="PositionMismatch",
            value=lattice.mismatch
        ))

        ctx.lattice.properties.append(dict(
            name="EnergyMismatch",
            value=lattice.emismatch
        ))

        ctx.lattice.properties.append(dict(
            name="PositionOffset",
            value=lattice.offset
        ))

        ctx.lattice.properties.append(dict(
            name="EnergyOffset",
            value=lattice.eoffset
        ))

        ctx.lattice.properties.append(dict(
            name="DistSigma",
            value=lattice.distSigma
        ))

        ctx.lattice.properties.append(dict(
            name="DistLambda",
            value=lattice.distLambda
        ))

        ctx.lattice.properties.append(dict(
            name="DistMu",
            value=lattice.distMu
        ))

        ctx.lattice.properties.append(dict(
            name="OutputMode",
            value=lattice.outputMode
        ))

        ctx.lattice.properties.append(dict(
            name="IntegratorType",
            value=lattice.integrator
        ))

        nucleons = particle_type.protons + particle_type.neutrons

        # lattice charge states
        if isinstance(lattice.charge, (tuple, list)):
            lattice_charge = []
            for charge in lattice.charge:
                lattice_charge.append(int(charge * lattice.particleMass * nucleons))
        else:
            lattice_charge = int(lattice.charge * lattice.particleMass * nucleons)

        ctx.lattice.properties.append(dict(
            name="ParticleCharge",
            value=lattice_charge
        ))

        ctx.lattice.files = []
        file_content = {}

        file_id = _create_file_id()
        ctx.lattice.files.append(ObjectDict(
            id=file_id,
            name="LatticeFile",
            size=len(lattice_file.body),
            filename=lattice_file.filename,
            location=_create_file_location(lattice_file)
        ))
        file_content[file_id] = lattice_file.body

        for data_file in request_files.get("data_file", []):
            # find a unique file ID
            while True:
                file_id=_create_file_id()
                if file_id not in file_content:
                    break
            ctx.lattice.files.append(ObjectDict(
                id=file_id,
                name="DataFile",
                size=len(data_file.body),
                filename=data_file.filename,
                location=_create_file_location(data_file)
            ))
            file_content[file_id] = data_file.body

        # check that all the data files specified by the
        # lattice have been submitted as attachments
        for filename in lattice.files:
            for f in ctx.lattice.files:
                if f.filename == filename:
                    break
            else:
                ctx.errors.data_file = "Missing data file: " + filename
                send_status(400, ctx)
                return

        attachment_path = self.settings.get("attachment_path", "")
        if len(attachment_path) == 0:
            LOGGER.warn("setting 'attachment_path' not found")
            ctx.errors._global = "Attachment directory not specified"
            send_status(500, ctx)
            return

        if not os.path.isdir(attachment_path):
            LOGGER.error("attachment path '%s' not found", attachment_path)
            ctx.errors._global = "Attachment directory not found"
            send_status(500, ctx)
            return

        try:
            yield data.validate_lattice(ctx.lattice)
        except Exception as e:
            LOGGER.error("lattice validation error: %s", e)
            ctx.errors._global = "Lattice validation error"
            send_status(500, ctx)
            return

        lattice_elements = []
        for idx, element in enumerate(lattice.elements):
            lattice_element = ObjectDict()
            lattice_element.lattice_id = ctx.lattice._id
            lattice_element.order = idx+1
            lattice_element.name = element.name
            lattice_element.type = element.etype
            lattice_element.length = element.length
            lattice_element.position = element.position
            lattice_element.properties = []
            lattice_element.properties.append(dict(
                name="ITYPE",
                value=element.itype
            ))
            lattice_element.properties.append(dict(
                name="STEPS",
                value=element.steps
            ))
            for field in element.fields:
                lattice_element.properties.append(dict(
                    name = field.name,
                    unit = field.unit,
                    value = element.getfield(field.name)
                ))

            try:
                yield data.validate_lattice_element(lattice_element)
            except Exception as e:
                LOGGER.error("lattice element validation error: %s", e)
                ctx.errors._global = "Lattice element validation error"
                send_status(500, ctx)
                return

            lattice_elements.append(lattice_element)

        try:
            lattice_id = yield data.insert_lattice(ctx.lattice, validate=False)
        except Exception as e:
            LOGGER.error("lattice database insert error: %s", e)
            ctx.errors._global = "Lattice database insert error"
            send_status(500, ctx)
            return

        try:
            for lattice_element in lattice_elements:
                lattice_element.lattice_id = lattice_id
                data.insert_lattice_element(lattice_element, validate=False)
        except Exception as e:
            LOGGER.error("lattice element database insert error: %s", e)
            ctx.errors._global = "Lattice element database insert error"
            # Rollback?
            send_status(500, ctx)
            return

        try:
            for f in ctx.lattice.files:
                _write_file_content(attachment_path, f.location, file_content[f.id])
        except Exception as e:
            LOGGER.exception("lattice file write error: %s", e)
            ctx.errors._global = "Lattice file write error"
            #Rollback?
            send_status(500, ctx)
            return

        send_status(201, ctx)
        return