A cli wrapper and downloader built around jwstapi.com
- This is a hobby project which is being used to learn elixir's OTP, whilst scratching an itch to explore the new jwstapi.com.
- This API is to accompany dreamily staring into nebuli.
- Use with caution.
JwstCli.Api
may get factored out for reuse as a stand alone library, which wraps HTTPoison.
Will grow as more API endpoints and the project matures.
- Clone
mix release
If available in Hex, the package can be installed
by adding jwst_cli
to your list of dependencies in mix.exs
:
def deps do
[
{:jwst_cli, "~> 0.1.0"}
]
end
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/jwst_cli.
Let's not go there yet. But do contribute back if you do.
- Set JWST_API_KEY in your shell. Eg.
export JWST_API_KEY=abcdKitten1234
- Run mix release
- As below, start the release in
start_iex
, or withdaemon
andremote
You can obtain a new API key from jwstapi.com
This provided from the environment and baked into the release at build time. It may be customised per environment using (./config/config.exs)[./config/config.exs] and sibling overides.
Eg.
î‚° export JWST_API_KEY=abcdKitten1234
We simply run mix release
î‚° mix release
Compiling 5 files (.ex)
warning: module attribute @me was set but never used
lib/jwst_cli/repl/executor.ex:9
Generated jwst_cli app
Release jwst_cli-0.1.0 already exists. Overwrite? [Yn] y
* assembling jwst_cli-0.1.0 on MIX_ENV=dev
* skipping runtime configuration (config/runtime.exs not found)
* skipping elixir.bat for windows (bin/elixir.bat not found in the Elixir installation)
* skipping iex.bat for windows (bin/iex.bat not found in the Elixir installation)
Release created at _build/dev/rel/jwst_cli!
As mentioned there are two methods
This scenario is better suited to a long running scenario where you may want to connect remotely.
This will leave the GenServer (with supervisor) running in the background
î‚° _build/dev/rel/jwst_cli/bin/jwst_cli daemon
This does not produce any output.
Very similar but you pass in remote
. This pattern allows you abort each iex session, but still connect
back to the same daemon to query the API.
Eg. The following connects and queries the list of JWST program id's:
î‚° _build/dev/rel/jwst_cli/bin/jwst_cli remote
Erlang/OTP 25 [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.13.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(jwst_cli@feynman)1> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_program_list"})
[2731, 2732, 2733, 2734]
See also: Elixir Mix Release by Example
This creates a blocking process which will terminate on exit from iex
.
It also produces greater visibility of logging output from the GenServer.
Eg.
î‚° _build/dev/rel/jwst_cli/bin/jwst_cli start_iex
Erlang/OTP 25 [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
10:16:22.183 [info] Using Children
10:16:22.183 [info] [{JwstCli.Repl.Executor, [%{api_key: "**************"}]}]
10:16:22.183 [info] [%{api_key: "***************"}]
10:16:22.183 [info] Start on #PID<0.905.0>
10:16:22.183 [info] [active: 1, specs: 1, supervisors: 0, workers: 1]
Interactive Elixir (1.13.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(jwst_cli@feynman)1> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_program_list"})
10:16:49.465 [info] "get_program_list"
10:16:49.466 [debug] Invoking /program/list with *********
10:16:50.605 [info] [2731, 2732, 2733, 2734]
[2731, 2732, 2733, 2734]``
Once you're in a session, you can query the GenServer by using call
with the following general form:
iex> GenServer.call(JwstCli.Repl.Executor, {:execute, "<name of operation>"})
Operations with names ending in _raw
will typically return the raw content of the equivalent remote resources
as JSON (wrapped in a JASON.Response).
See below for you choice of operations
Returns all JWST program ids as an array
Eg.
iex> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_program_list"})
[2731, 2732, 2733, 2734]
Returns all JWST program ids contained in the response from /program/list defined by the JWST API
Eg.
GenServer.call(JwstCli.Repl.Executor, {:execute, "get_program_list_raw"})
Returns last 30 jpgs defined by the JWST API
Eg.
GenServer.call(JwstCli.Repl.Executor, {:execute, "get_recent_jpg"})
iex(jwst_cli@feynman)6> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_recent_jpg"})
Returns all JWST jpegs URLs from JWST defined by the JWST API
Eg.
GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_jpg"})
iex(jwst_cli@feynman)6> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_jpg"})
Returns all JWST jpegs from JWST defined by the JWST API
Eg.
GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_jpg_raw"})
iex(jwst_cli@feynman)6> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_jpg_raw"})
{:ok,
%HTTPoison.Response{
body: "{\"statusCode\":200,\"body\":[{\"id\":\"jw02731002001_02107_00004_mirimage_o002_crf_thumb.jpg\",\"observation_id\":\"jw02731002001_02107_00004_mirimage_o002\",\"program\":2731,\"details\":{\"mission\":\"JWST\",\"instruments\":[{\"instrument\":\"FGS\"},{\"instrument\":\"NIRCam\"},{\"instrument\":\"NIRISS\"},{\"instrument\":\"NIRSpec\"},{\"instrument\":\"MIRI\"}],\"suffix\":\"_thumb\",\"description\":\"thumbnail image of the FITS data product\"},\"file_type\":\"jpg\",\"thumbnail\":\"\",\"location\":\"https://stpubdata-jwst.stsci.edu/ero/jw02731/jw02731002001/jw02731002001_02107_00004_mirimage_o002_crf_thumb.jpg\"], ....
headers: [...],
request: %HTTPoison.Request{ .... },
request_url: ....,
status_code: 200
}}
Returns all JWST FITS imagse from JWST defined by the JWST API
Eg.
GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_fits_raw"})
iex(jwst_cli@feynman)6> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_fits_raw"})
{:ok,
%HTTPoison.Response{
body: "{\"statusCode\":200,\"body\":[{\"id\":\"jw02731001003_02105_00001_nrca1_i2d.fits\",\"observation_id\":\"jw02731001003_02105_00001_nrca1\",\"program\":2731,\"details\":{\"mission\":\"JWST\",\"instruments\":[{\"instrument\":\"FGS\"},{\"instrument\":\"NIRCam\"},{\"instrument\":\"NIRISS\"},{\"instrument\":\"NIRSpec\"},{\"instrument\":\"MIRI\"}],\"suffix\":\"_i2d\",\"description\":\"exposure/target (L2b/L3): rectified 2D image\"},\"file_type\":\"fits\",\"thumbnail\":\"\",\"location\":\"https://stpubdata-jwst.stsci.edu/ero/jw02731/jw02731001003/jw02731001003_02105_00001_nrca1_i2d.fits\",...
headers: [...],
request: %HTTPoison.Request{ .... },
request_url: ....,
status_code: 200
}}
Returns all ecsv file url's from JWST defined by the JWST API
Eg.
GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_ecsv_raw"})
iex(jwst_cli@feynman)6> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_ecsv_raw"})
{:ok,
%HTTPoison.Response{
body: "{\"statusCode\":200,\"body\":[{\"id\":\"jw02731-o001_t017_nircam_clear-f444w_cat.ecsv\",\"observation_id\":\"jw02731-o001_t017_nircam_clear-f444w\",\"program\":2731,\"details\":{\"mission\":\"JWST\",\"instruments\":[{\"instrument\":\"FGS\"},{\"instrument\":\"NIRISS\"}],\"suffix\":\"_cat\",\"description\":\"target (L3) : source catalog\"},\"file_type\":\"ecsv\",\"thumbnail\":\"\",\"location\":\"https://stpubdata-jwst.stsci.edu/ero/jw02731/L3/t/jw02731-o001_t017_nircam_clear-f444w_cat.ecsv\"},{\"id\":\"jw02731-o001_t017_nircam_f444w-f470n_cat.ecsv\",\"observation_id\":\"jw02731-o001_t017_nircam_f444w-f470n\",\"program\":2731,\"details\":{\"mission\":\"JWST\",\"instruments\":[{\"instrument\":\"FGS\"},{\"instrument\":\"NIRISS\"}],\"suffix\":\"_cat\",\"description\":\"target (L3) : source catalog\"},\"file_type\":\"ecsv\",\"thumbnail\":\"\",\"location\":\"https://stpubdata-jwst.stsci.edu/ero/jw02731/L3/t/jw02731-o001_t017_nircam_f444w-f470n_cat.ecsv\",...
headers: [...],
request: %HTTPoison.Request{ .... },
request_url: ....,
status_code: 200
}}
Returns all json file url's from JWST defined by the JWST API
Eg.
GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_json_raw"})
iex(jwst_cli@feynman)6> GenServer.call(JwstCli.Repl.Executor, {:execute, "get_all_json_raw"})
{:ok,
%HTTPoison.Response{
body: "{\"statusCode\":200,\"body\":[{\"id\":\"jw02731-o001_20220712t165318_image2_317_asn.json\",\"observation_id\":\"jw02731-o001_20220712t165318_image2_317\",\"program\":2731,\"details\":{\"mission\":\"JWST\",\"instruments\":[{\"instrument\":\"FGS\"},{\"instrument\":\"NIRCam\"},{\"instrument\":\"NIRISS\"},{\"instrument\":\"NIRSpec\"},{\"instrument\":\"MIRI\"}],\"suffix\":\"_asn\",\"description\":\"source/target (L3) : association generator\"},\"file_type\":\"json\",\"thumbnail\":\"\",\"location\":\"https://stpubdata-jwst.stsci.edu/ero/jw02731/asn/jw02731-o001_20220712t165318_image2_317_asn.json\"}, ...
headers: [...],
request: %HTTPoison.Request{ .... },
request_url: ....,
status_code: 200
}}
The app is currently VERY chatting. You may want to reduce the default log levels; this is on my TODO.
In iex:
iex> Logger.configure(level: :error)
In the config/config.exs
config :logger, level: :error
This is a work in progres and will ulimately provide a more powerful standalone repl. Run the following to generate the jwst_cli executable in the parent directory.
mix escript.build
Still in progress - this will be a cli app to query the GenServer session as a connected node.
You could potentially run this by starting iex with elixir --cookie <common value> and -s script
I've yet to document this properly.
Thank you to Kyle Redelinghuys who has provided the JWST API