Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save ZTF alerts as sources by objectId #44

Merged
merged 24 commits into from
Sep 30, 2020

Conversation

dmitryduev
Copy link
Member

@dmitryduev dmitryduev commented Sep 29, 2020

In this PR:

  • extensions/skyportal/skyportal/handlers/api/alert.py:
    • new endpoint ZTFAlertHandler.post to save ZTF alerts as sources by their objectId, e.g. api('POST', '<fritz_instance_location>/api/alerts/ztf/<objectId>'), {"candid": <candid>, "group_ids": <list of group ids>}. Under the hood, F pulls the required data from K, massages them, and posts to SP's /api/sources, /api/photometry, and /api/thumbnail. If candid is not provided, metadata and thumbnails will be pulled from the latest alert/candid. If no list of group_ids is provided, the object will be saved to all user's groups
    • async api calls to Kowalski using tornado.httpclient instead of requests
  • extensions/skyportal/static/js/components/ZTFAlert.jsx
    • Re-skin that makes the page look a lot more like the Source and Candidate pages
    • Replaced MUI table with MUI datatable to display the alerts
    • A button to save alerts as sources
  • extensions/skyportal/static/js/components/SaveAlertButton.jsx
    • Mostly a copy-paste of SaveCandidateButton.jsx with a couple modifications necessary here
  • fix linting in extensions/skyportal/static/js/components/Filter.jsx

ztf-alert-03

@dmitryduev dmitryduev changed the title Save ZTF alerts by objectId Save ZTF alerts as sources by objectId Sep 29, 2020
w = df["candid"] == str(candid)

if candid is None or sum(w) == 0:
candids = {int(can) for can in df["candid"] if not pd.isnull(can)}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got sick of pandas relationship with long ints and implemented it this way.

log(f"Failed to post photometry of {objectId}")
# do not return anything yet
self.clear()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Monsieur knows a lot about perversion, don't you think @dannygoldstein? :) Hope you appreciate the "beauty"!

except Exception:
log(f"Failed to post photometry of {objectId}")
# do not return anything yet
self.clear()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't do this, the photometry handler would try to .write()

@dmitryduev dmitryduev linked an issue Sep 30, 2020 that may be closed by this pull request
@dannygoldstein
Copy link
Member

merge conflicts

Copy link
Member

@dannygoldstein dannygoldstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main comment is: what happens when a user attempts to save an alert to a group without permissions to see the data or that the object exists?

E.g., an object with all PID=3 alerts saved to the sitewide_group

import * as sourcetActions from "../ducks/source";
import FormValidationError from "./FormValidationError";

const SaveAlertButton = ({ alert, userGroups }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when a user tries to save an object with only PID=3 alerts to the sitewide group?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point, addressed here. It will now fail.

@@ -141,10 +207,313 @@ def get(self, objectId: str = None):
_err = traceback.format_exc()
return self.error(f'failure: {_err}')

@auth_or_token
async def post(self, objectId):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why async?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because I am calling K asynchronously and awaiting the results; you can await only inside an async function.

if len(alert_data) > 0:
alert_data = alert_data[0]
else:
return self.error(f"{objectId} not found on Kowalski")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, what about the case where someone saves an object to a group without permissions to see the data?

ztf_filters = {1: 'ztfg', 2: 'ztfr', 3: 'ztfi'}
df['ztf_filter'] = df['fid'].apply(lambda x: ztf_filters[x])
df['magsys'] = "ab"
df['zp'] = 25.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used downstream?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, removed.

@dmitryduev
Copy link
Member Author

@dannygoldstein Feedback addressed, please re-review.

Copy link
Collaborator

@kmshin1397 kmshin1397 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments but otherwise looks good

group_ids = [
int(_id)
for _id in group_ids
if int(_id) in user_accessible_group_ids
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, it seems like we just silently ignore any groups the user doesn't have access to. Should we send a specific error if a group_id passed in isn't part of the user_accessilbe_group_ids? To let someone know if they think they're part of a group but aren't for whatever reason?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a check on that

import { useForm, Controller } from "react-hook-form";

import * as alertActions from "../ducks/alert";
import * as sourcetActions from "../ducks/source";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import * as sourcetActions from "../ducks/source";
import * as sourceActions from "../ducks/source";

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

} else {
setDialogOpen(false);
reset();
await dispatch(sourcetActions.fetchSource(alert.id));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await dispatch(sourcetActions.fetchSource(alert.id));
await dispatch(sourceActions.fetchSource(alert.id));

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Member

@dannygoldstein dannygoldstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dmitryduev dmitryduev requested review from kmshin1397 and removed request for acrellin September 30, 2020 19:55
@kmshin1397 kmshin1397 merged commit bd87afe into fritz-marshal:master Sep 30, 2020
@dmitryduev dmitryduev linked an issue Oct 6, 2020 that may be closed by this pull request
@dmitryduev dmitryduev deleted the save_alert_by_id branch February 24, 2021 23:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Command "./fritz run --init" broken due to recent config changes save source by source ID
3 participants