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

Import spectra from Fritz #2

Merged
merged 1 commit into from
Sep 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ Create `secrets.json` with confidential/secret data:
"token": null // set to your token
}
},
"fritz": {
"url": "https://fritz.science",
"token": null // set to your token, optional
}
}
}
```
Expand Down
131 changes: 131 additions & 0 deletions ztf-variable-marshal/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import aiofiles
import aiohttp
from astropy.time import Time
import aiohttp_jinja2
import jinja2
import jwt
Expand Down Expand Up @@ -183,6 +184,30 @@ async def add_master_program(_mongo):
print(_err)


# query fritz
def api(endpoint, method="GET", data=None):
import requests

try:
base_url = config["fritz"]["url"]
token = config["fritz"]["token"]
response = requests.request(
method,
f"{base_url}/api/{endpoint}",
headers={"Authorization": f"token {token}"}, # noqa
json=data,
)
if response.status_code != 200:
raise Exception(response.text)
else:
q = response.json()["data"]
return q
except Exception:
return None


fritz_instruments = api("instrument")

routes = web.RouteTableDef()


Expand Down Expand Up @@ -2142,6 +2167,14 @@ async def source_get_handler(request):
.to_list(length=None)
)

data = api(
f"sources?ra={source['ra']}&dec={source['dec']}&radius={3/3600}&hasSpectrum=true"
)
if data is not None and len(data.get("sources", [])) > 0:
source["fritz_sources"] = [d["id"] for d in data["sources"]]
else:
source["fritz_sources"] = []

context = {
"logo": config["server"]["logo"],
"user": session["user_id"],
Expand Down Expand Up @@ -3625,6 +3658,104 @@ async def source_post_handler(request):

return web.json_response({"message": "success"}, status=200)

elif _r["action"] == "import_fritz_spectra":
# fetch spectra from Fritz for the source in _r.get('source_id', None)
# and ingest them into the source

fritz_source_id = _r.get("source_id", None)
data = api(f"sources/{fritz_source_id}/spectra", method="GET")
if data is not None and len(data.get("spectra", [])) > 0:
new = False
for fritz_spectrum in data["spectra"]:
try:
telescope = [
fritz_instrument["telescope"]
for fritz_instrument in fritz_instruments
if fritz_instrument["name"]
== fritz_spectrum["instrument_name"]
][0]["nickname"]
except Exception:
telescope = "Unknown"

flux_unit = fritz_spectrum["units"]
if flux_unit in [None, "None", ""]:
flux_unit = fritz_spectrum.get("altdata", {}).get(
"BUNIT", "Unknown"
)

spectrum = {
"instrument": fritz_spectrum["instrument_name"],
"telescope": telescope,
"filter": "Unknown",
"wavelength_unit": "A",
"flux_unit": flux_unit,
"data": {
"wavelength": fritz_spectrum["wavelengths"],
"flux": fritz_spectrum["fluxes"],
"fluxerr": fritz_spectrum["errors"],
},
"mjd": Time(
fritz_spectrum["observed_at"], format="isot"
).mjd,
}

# check that there isn't a spectrum with the same mjd, instrument, telescope, filter already
# in the source
existing_spectra = source["spec"]
exists = False
for existing_spectrum in existing_spectra:
if (
existing_spectrum["mjd"] == spectrum["mjd"]
and existing_spectrum["instrument"]
== spectrum["instrument"]
and existing_spectrum["telescope"]
== spectrum["telescope"]
and existing_spectrum["filter"] == spectrum["filter"]
):
exists = True
break

if exists:
continue

# generate unique _id:
spectrum["_id"] = random_alphanumeric_str(length=24)

# make history
time_tag = utc_now()
h = {
"note_type": "spec",
"time_tag": time_tag,
"user": user,
"note": f'{spectrum["telescope"]} {spectrum["instrument"]} {spectrum["filter"]}',
}

await request.app["mongo"].sources.update_one(
{"_id": _id},
{
"$push": {"spec": spectrum, "history": h},
"$set": {"last_modified": utc_now()},
},
)
new = True

if not new:
return web.json_response(
{
"message": f"All spectra from fritz source {fritz_source_id} already imported"
},
status=200,
)

return web.json_response({"message": "success"}, status=200)
else:
return web.json_response(
{
"message": f"failure: no spectra found in fritz for {fritz_source_id}"
},
status=200,
)

else:
return web.json_response(
{"message": "failure: unknown action requested"}, status=200
Expand Down
1 change: 0 additions & 1 deletion ztf-variable-marshal/templates/template-search.html
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,6 @@ <h5 class="modal-title" id="modal-query-id"></h5>
// display details
function detailFormatter(index, row, element) {
var html = [];
console.log(row)

{#let jdd = new JulianDate();#}
{#let date_utc = moment(jdd.julian(parseFloat(row['jd'])).getDate()).utc().format('YYYYMMDD');#}
Expand Down
72 changes: 67 additions & 5 deletions ztf-variable-marshal/templates/template-source.html
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,6 @@ <h4>
{% else %}
{% set dec_string = source['dec'] | string %}
{% endif %}
<a href="javascript:document.getElementById('kowalski_form').submit();"
role="button" class="btn btn-secondary btn-sm"
id="survey_ztf_alerts">ZTF Alerts</a>
<a href="https://ps1images.stsci.edu/cgi-bin/ps1cutouts?pos={{ source['ra'] }}{{ dec_string }}&filter=color&filter=g&filter=r&filter=i&filter=z&filter=y&filetypes=stack&auxiliary=data&size=240&output_size=0&verbose=0&autoscale=99.500000&catlist="
target="_blank" role="button" class="btn btn-secondary btn-sm"
id="survey_panstarrs">PanSTARRS-1</a>
Expand Down Expand Up @@ -327,10 +324,31 @@ <h4>
...
]
}</code></pre>
"wavelen_unit" can be "A", "nm", or "m".
"wavelength_unit" can be "A", "nm", or "m".
You can use either mjd or hjd for the time stamp.
Other fields above are mandatory, however you can add any custom fields.
</p>
<!-- if the source has 'has_fritz_spectra' True, show a test like: "Nearby sources with spectra found in Fritz" -->
<div class="mt-2">
<b>Fritz sources (with spectra, within 3 arcsec):</b>
{% if source['fritz_sources'] | length > 0 %}
{% for fritz_source in source['fritz_sources'] %}
<div class="mt-1" style="display: flex; flex-direction: row; align-items: center;">
<p>
<a href="http://fritz.science/source/{{ fritz_source }}" target="_blank" role="button" class="btn btn-secondary btn-sm">
{{ fritz_source }}
</a>
<!-- add a button to import spectra -->
<button type="button" class="btn btn-dark btn-sm"
id="import_fritz_spectra" onclick="import_fritz_spectra('{{ fritz_source }}')">Import</button>
</p>
</div>
{% endfor %}
{% else %}
<p><em>No sources found.</em></p>
{% endif %}
</div>

</div>

<div class="tab-pane fade mt-2" id="nav-auxiliary"
Expand Down Expand Up @@ -541,7 +559,7 @@ <h5 class="modal-title" id="modal-query-id"></h5>
error_y: {type: 'data',
array: {{ lc['data'][key]['magerr'] }},
width: 2,
thickness: 0.8,
thickness: 0.4,
color: "{{ lc['color'] }}",
opacity: 0.5,
visible: true},
Expand Down Expand Up @@ -1269,6 +1287,50 @@ <h5 class="modal-title" id="modal-query-id"></h5>
{% endfor %}
});
{% endif %}

{# import spectra from a fritz source, takes the source id as input #}
function import_fritz_spectra(source_id) {
bootbox.confirm({
message: "Do you want to import spectra from a fritz source?",
buttons: {
cancel: {
label: '<i class="fas fa-times"></i> No'
},
confirm: {
label: '<i class="fas fa-check"></i> Yes'
}
},
callback: function (result) {
// confirmed?
if (result) {
$.ajax({url: '{{-script_root-}}/sources/{{-source["_id"]-}}',
method: 'POST',
data: JSON.stringify({'action': 'import_fritz_spectra', 'source_id': source_id}),
processData: false,
contentType: 'application/json',
success: function(data) {
if (data['message'] === 'success') {
showFlashingMessage('Info:', 'Successfully imported spectra: ' + data['message'], 'success');
setTimeout(window.location.href = '{{-script_root-}}/sources/{{ source["_id"] }}', 1000);
}
else if (data['message'] === `All spectra from fritz source ${source_id} already imported`) {
showFlashingMessage('Info:', `All spectra from fritz source ${source_id} already imported`, 'info');
}
else {
showFlashingMessage('Info:', 'Failed to import spectra: ' + data['message'], 'danger');
}
},
error: function(data) {
showFlashingMessage('Info:', 'Failed to import spectra', 'danger');
}
});
}
}
});
}

{# import light curves from a fritz source, takes the source id as input #}

</script>

{% endblock %}
Loading