def create(self, params):
        body = self.getBodyJson()
        user = self.getCurrentUser()
        public = body.get('public', True)
        gen3d = body.get('generate3D', True)
        gen3d_forcefield = body.get('gen3dForcefield', 'mmff94')
        gen3d_steps = body.get('gen3dSteps', 100)
        provenance = body.get('provenance', 'uploaded by user')
        mol = None
        if 'fileId' in body:
            file_id = body['fileId']
            file = ModelImporter.model('file').load(file_id, user=user)
            parts = file['name'].split('.')
            input_format = parts[-1]
            name = '.'.join(parts[:-1])

            if input_format not in Molecule.input_formats:
                raise RestException('Input format not supported.', code=400)

            with File().open(file) as f:
                data_str = f.read().decode()

            mol = create_molecule(data_str, input_format, user, public, gen3d,
                                  provenance, gen3d_forcefield, gen3d_steps,
                                  body)
        elif 'inchi' in body:
            input_format = 'inchi'
            data = body['inchi']
            if not data.startswith('InChI='):
                data = 'InChI=' + data

            mol = create_molecule(data, input_format, user, public, gen3d,
                                  provenance, gen3d_forcefield, gen3d_steps,
                                  body)

        for key in body:
            if key in Molecule.input_formats:
                input_format = key
                data = body[input_format]
                # Convert to str if necessary
                if isinstance(data, dict):
                    data = json.dumps(data)
                mol = create_molecule(data, input_format, user, public, gen3d,
                                      provenance, gen3d_forcefield,
                                      gen3d_steps, body)
                break

        if not mol:
            raise RestException('Invalid request', code=400)

        return self._clean(mol)
    def search(self, params):
        limit, offset, sort = parse_pagination_params(params)

        query_string = params.get('q')
        formula = params.get('formula')
        cactus = params.get('cactus')
        if query_string is None and formula is None and cactus is None:
            raise RestException(
                'Either \'q\', \'formula\' or \'cactus\' is required.')

        if query_string is not None:
            try:
                mongo_query = query.to_mongo_query(query_string)
            except query.InvalidQuery:
                raise RestException('Invalid query', 400)

            fields = ['inchikey', 'smiles', 'properties', 'name']
            cursor = MoleculeModel().find(query=mongo_query,
                                          fields=fields,
                                          limit=limit,
                                          offset=offset,
                                          sort=sort)
            mols = [x for x in cursor]
            num_matches = cursor.collection.count_documents(mongo_query)

            return search_results_dict(mols, num_matches, limit, offset, sort)

        elif formula:
            # Search using formula
            return MoleculeModel().findmol(params)

        elif cactus:
            if getCurrentUser() is None:
                raise RestException('Must be logged in to search with cactus.')

            # Disable cert verification for now
            # TODO Ensure we have the right root certs so this just works.
            r = requests.get(
                'https://cactus.nci.nih.gov/chemical/structure/%s/file?format=sdf'
                % cactus,
                verify=False)

            if r.status_code == 404:
                return []
            else:
                r.raise_for_status()

            sdf_data = r.content.decode('utf8')
            provenance = 'cactus: ' + cactus
            mol = create_molecule(sdf_data,
                                  'sdf',
                                  getCurrentUser(),
                                  True,
                                  provenance=provenance)

            return search_results_dict([mol], 1, limit, offset, sort)
    def create_calc(self, params):
        body = getBodyJson()
        if 'cjson' not in body and ('fileId' not in body
                                    or 'format' not in body):
            raise RestException('Either cjson or fileId is required.')

        user = getCurrentUser()

        cjson = body.get('cjson')
        props = body.get('properties', {})
        molecule_id = body.get('moleculeId', None)
        geometry_id = body.get('geometryId', None)
        public = body.get('public', True)
        notebooks = body.get('notebooks', [])
        image = body.get('image')
        input_parameters = body.get('input', {}).get('parameters')
        if input_parameters is None:
            input_parameters = body.get('inputParameters', {})
        file_id = None
        file_format = body.get('format', 'cjson')

        if 'fileId' in body:
            file = File().load(body['fileId'], user=getCurrentUser())
            file_id = file['_id']
            cjson = self._file_to_cjson(file, file_format)

        if molecule_id is None:
            mol = create_molecule(json.dumps(cjson),
                                  'cjson',
                                  user,
                                  public,
                                  parameters=input_parameters)
            molecule_id = mol['_id']

        calc = CalculationModel().create_cjson(
            user,
            cjson,
            props,
            molecule_id,
            geometry_id=geometry_id,
            image=image,
            input_parameters=input_parameters,
            file_id=file_id,
            notebooks=notebooks,
            public=public)

        cherrypy.response.status = 201
        cherrypy.response.headers['Location'] \
            = '/calculations/%s' % (str(calc['_id']))

        return CalculationModel().filter(calc, user)