def get(self, obj_id): phase_fold_data = self.get_query_argument("phaseFoldData", False) if Obj.get_if_accessible_by(obj_id, self.current_user) is None: raise AccessError( f"Insufficient permissions for User {self.current_user.id} to read Obj {obj_id}" ) photometry = Photometry.query_records_accessible_by( self.current_user).filter(Photometry.obj_id == obj_id) format = self.get_query_argument('format', 'mag') outsys = self.get_query_argument('magsys', 'ab') self.verify_and_commit() data = [serialize(phot, outsys, format) for phot in photometry] if phase_fold_data: period, modified = None, arrow.Arrow(1, 1, 1) annotations = (Annotation.query_records_accessible_by( self.current_user).filter(Annotation.obj_id == obj_id).all()) period_str_options = ['period', 'Period', 'PERIOD'] for an in annotations: if not isinstance(an.data, dict): continue for period_str in period_str_options: if period_str in an.data and arrow.get( an.modified) > modified: period = an.data[period_str] modified = arrow.get(an.modified) if period is None: self.error(f'No period for object {obj_id}') for ii in range(len(data)): data[ii]['phase'] = np.mod(data[ii]['mjd'], period) / period return self.success(data=data)
def parse_id_list(self, id_list, model_class): """ Return a list of integer IDs from the comma separated string of IDs given by the query argument, and the model/table to be queried. Parameters ---------- id_list: string Comma separated list of integer values. model_class: class A skyportal data model class, e.g., Group, Instrument. """ if id_list is None: return # silently pass through any None values try: accessible_rows = model_class.get_records_accessible_by( self.current_user) validated_ids = [] for id in id_list.split(','): id = int(id) if id not in [row.id for row in accessible_rows]: raise AccessError( f'Invalid {model_class.__name__} IDs field ("{id_list}"); ' f'Not all {model_class.__name__} IDs are valid/accessible' ) validated_ids.append(id) except ValueError: raise ValueError( f'Invalid {model_class.__name__} IDs field ("{id_list}"); ' f'Could not parse all elements to integers') return validated_ids
def get_source_if_owned_by(obj_id, user_or_token, options=[]): if Source.query.filter(Source.obj_id == obj_id).first() is None: return None user_group_ids = [g.id for g in user_or_token.groups] s = (Source.query.filter(Source.obj_id == obj_id).filter( Source.group_id.in_(user_group_ids)).options(options).first()) if s is None: raise AccessError("Insufficient permissions.") return s.obj
async def post(self): data = self.get_json() featureset_name = data.get('featuresetName', '') dataset_id = int(data['datasetID']) features_to_use = [ feature for (feature, selected) in data.items() if feature in dask_feature_graph and selected ] if not features_to_use: return self.error("At least one feature must be selected.") custom_feats_code = data['customFeatsCode'].strip() custom_script_path = None dataset = Dataset.query.filter(Dataset.id == dataset_id).one() if not dataset.is_owned_by(self.current_user): raise AccessError('No such data set') fset_path = pjoin(self.cfg['paths:features_folder'], '{}_featureset.npz'.format(uuid.uuid4())) fset = Featureset(name=featureset_name, file_uri=fset_path, project=dataset.project, features_list=features_to_use, custom_features_script=None) DBSession().add(fset) client = await self._get_client() all_time_series = client.map(time_series.load, [f.uri for f in dataset.files]) all_labels = client.map(lambda ts: ts.label, all_time_series) all_features = client.map(featurize.featurize_single_ts, all_time_series, features_to_use=features_to_use, custom_script_path=custom_script_path, raise_exceptions=False) computed_fset = client.submit(featurize.assemble_featureset, all_features, all_time_series) imputed_fset = client.submit(featurize.impute_featureset, computed_fset, inplace=False) future = client.submit(featurize.save_featureset, imputed_fset, fset_path, labels=all_labels) fset.task_id = future.key DBSession().commit() loop = tornado.ioloop.IOLoop.current() loop.spawn_callback(self._await_featurization, future, fset) self.success(fset, 'cesium/FETCH_FEATURESETS')
def get_candidate_if_owned_by(obj_id, user_or_token, options=[]): if Candidate.query.filter(Candidate.obj_id == obj_id).first() is None: return None user_group_ids = [g.id for g in user_or_token.groups] c = (Candidate.query.filter(Candidate.obj_id == obj_id).filter( Candidate.filter_id.in_( DBSession.query(Filter.id).filter( Filter.group_id.in_(user_group_ids)))).options( options).first()) if c is None: raise AccessError("Insufficient permissions.") return c.obj
def get_obj_if_owned_by(obj_id, user_or_token, options=[]): try: obj = Source.get_obj_if_owned_by(obj_id, user_or_token, options) except AccessError: # They may still be able to view the associated Candidate obj = Candidate.get_obj_if_owned_by(obj_id, user_or_token, options) if obj is None: # If user can't view associated Source, and there's no Candidate they can # view, raise AccessError raise if obj is None: # There is no associated Source/Cand, so check based on photometry if Obj.get_photometry_owned_by_user(obj_id, user_or_token): return Obj.query.options(options).get(obj_id) raise AccessError("Insufficient permissions.") # If we get here, the user has access to either the associated Source or Candidate return obj
def add_linked_thumbnails_and_push_ws_msg(obj_id, user_id): with Session() as session: try: user = session.query(User).get(user_id) if Obj.get_if_accessible_by(obj_id, user) is None: raise AccessError( f"Insufficient permissions for User {user_id} to read Obj {obj_id}" ) obj = session.query(Obj).get(obj_id) obj.add_linked_thumbnails(session=session) flow = Flow() flow.push( '*', "skyportal/REFRESH_SOURCE", payload={"obj_key": obj.internal_key} ) flow.push( '*', "skyportal/REFRESH_CANDIDATE", payload={"id": obj.internal_key} ) except Exception as e: log(f"Unable to add linked thumbnails to {obj_id}: {e}") session.rollback()