disco.server — HTTP API Reference

The GUI backend is implemented as a FastAPI application (app) served by Uvicorn on http://0.0.0.0:8000. The application maintains a single in-memory session via the module-level singleton state (an instance of GlobalState). All state is cleared on startup and on server shutdown.

CORS is enabled for all origins (allow_origins=["*"]) to permit access from the bundled React application.


Global State

The GlobalState class holds the current session data:

Attribute

Description

data

numpy.ndarray | None — the currently-loaded 2D FITS image.

header

FITS header object, or None.

filename

Resolved file path of the loaded FITS file, or None.

results

dict — pipeline output images keyed by type ("deproj", "model", "residuals", "polar").

extents

dict — Matplotlib extent (physical axis limits) for each image type, used for correct axis labelling.

profile_data

dict | None — radial profile data with keys "radius" and "tb" (brightness temperature profile).


Pydantic Request Models

class disco.server.PlotParams[source]

Request body for POST /render_plot.

Parameters:
  • type (str) – Image type to render. One of: "data", "deproj", "model", "residuals", "polar", "profile".

  • cmap (str) – Matplotlib colormap name. Default: "magma".

  • stretch (str) – Intensity stretch. One of: "asinh" (default), "log", "linear", "sqrt".

  • vmax_percentile (float | None) – If set, the vmax is computed as this percentile of the image data.

  • vmin (float | None) – Manual lower intensity limit.

  • vmax (float | None) – Manual upper intensity limit.

  • contours (bool) – Overlay contours. Default: False.

  • contour_levels (int) – Number of contour levels. Default: 5.

  • show_beam (bool) – Overlay beam ellipse. Default: False.

  • show_grid (bool) – Overlay grid lines. Default: False.

  • show_axes (bool) – Show axes and labels. Default: True.

  • show_colorbar (bool) – Show colorbar. Default: True.

  • title (str | None) – Optional plot title.

  • dpi (int) – Figure DPI. Default: 150.

class disco.server.PipelineParams[source]

Request body for POST /run_pipeline.

Parameters:
  • cx (float) – Disk centre x-coordinate in pixels.

  • cy (float) – Disk centre y-coordinate in pixels (GUI convention: measured from the top of the image).

  • pa (float) – Position angle in degrees.

  • incl (float) – Inclination in degrees.

  • rout (float) – Outer disk radius in arcseconds.

  • fit_rmin (float) – Inner radius for Gaussian ring fitting. Default: 0.0.

  • fit_rmax (float) – Outer radius for Gaussian ring fitting. Default: 0.0.

class disco.server.OptimizeParams[source]

Request body for POST /optimize_geometry.

Parameters:
  • cx (float) – Centre x in pixels.

  • cy (float) – Centre y in pixels.

  • pa (float) – Current position angle in degrees.

  • incl (float) – Current inclination in degrees.

  • rout (float) – Outer radius in arcseconds.

  • fit_rmin (float) – Inner fitting radius in arcseconds. Default: 0.0.

  • fit_rmax (float) – Outer fitting radius in arcseconds. Default: 0.0.

class disco.server.LoadLocalParams[source]

Request body for POST /load_local.

Parameters:

filename (str) – Base filename (not a full path) to load from the upload directory .disco_uploads/.


Endpoints

Session Management

POST /reset_session

Clears all session state (GlobalState fields reset to None / empty) and deletes all files in the .disco_uploads/ directory.

Status Codes:
  • 200 OK{"status": "Session cleared"}

File Loading

POST /upload

Accept a multipart FITS file upload, save it to .disco_uploads/, load the primary HDU into state.data and state.header, and return basic image metadata.

If the data maximum is below 0.1, the array is multiplied by 1 000 (Jy/beam → mJy/beam normalisation).

Form field: file — the FITS file.

Status Codes:
  • 200 OK – JSON object with keys: filename (str), status ("loaded"), shape (list[int, int]), pixel_scale (float, arcsec/pixel).

  • 500 Internal Server Error – On any read or FITS parse error.

POST /load_local

Load a previously-uploaded FITS file from .disco_uploads/ by base filename. Applies the same unit normalisation as /upload.

Request body: LoadLocalParams

Status Codes:
  • 200 OK – JSON object with keys: status ("loaded"), filename (str), shape (list[int, int]), pixel_scale (float).

  • 404 Not Found – If the file does not exist in the upload directory.

  • 500 Internal Server Error – On parse error.

GET /preview

Return a base64-encoded PNG preview of the currently-loaded image, rendered with the inferno colormap and an AsinhStretch normalisation (stretch_val=0.02).

Status Codes:
GET /get_header

Return the FITS header as a list of keyword–value–comment triples, excluding COMMENT and HISTORY records.

Status Codes:
  • 200 OK{"header": [{"key": str, "value": str, "comment": str}, ...]} Returns an empty list if no header is loaded.

Pipeline and Optimisation

POST /run_pipeline

Execute the deprojection pipeline on the currently-loaded image with the supplied geometry, and store the results in state.results.

Procedure:

  1. Convert GUI pixel-y to image-y convention.

  2. Generate the deprojected image by applying the inclination and PA transform on a \(1000 \times 1000\) grid using scipy.ndimage.map_coordinates (order 3).

  3. Compute the polar map (radius vs azimuth, 361 × 500 pixels).

  4. Build the azimuthal model (mean profile tiled over the polar grid, then reprojected to Cartesian).

  5. Compute the residual map (deprojected − model).

  6. Extract the azimuthally-averaged profile via disco.core.fits_utils.extract_profile().

  7. If fit_rmin < fit_rmax, fit a Gaussian to the profile segment using scipy.optimize.curve_fit with the model \(G(r) = a\exp(-(r-r_0)^2/(2\sigma^2)) + c\).

  8. Read beam geometry from the header and construct a beam info dict.

  9. Store all results in state.

Request body: PipelineParams

Status Codes:
  • 200 OK – JSON object with the following structure:

{
  "images": {
    "deproj":    "data:image/png;base64,...",
    "polar":     "data:image/png;base64,...",
    "model":     "data:image/png;base64,...",
    "residuals": "data:image/png;base64,..."
  },
  "profile": {
    "radius":        [...],
    "intensity":     [...],
    "raw_intensity": [...]
  },
  "geometry": {
    "fov_cartesian": <float>,
    "fov_polar":     <float>,
    "beam":          {"major": <float>, "minor": <float>, "pa": <float>},
    "pixel_scale":   <float>
  },
  "fit": {
    "peak_radius": <float>,
    "fwhm":        <float>
  }
}

The fit key is null if no fit range is specified or fitting fails.

Status Codes:
POST /optimize_geometry

Run a grid-seeded Nelder-Mead optimisation of disco.core.optimization.geometric_loss() to refine inclination and position angle.

Procedure:

  1. Convert GUI coordinates to image-space.

  2. Apply zero-padding (1000 pixels) and crop around the centre.

  3. Evaluate the loss at a grid of \((i, \phi)\) candidates: test_incls = [10, 30, 50, 70] degrees, test_pas   = range(0, 180, 30) degrees.

  4. Run Nelder-Mead (bounds [0,85] × [0,180] × [-10,10]², dim=400, order=3) starting from the best grid point.

Request body: OptimizeParams

Status Codes:
{
  "optimized_incl": <float>,
  "optimized_pa":   <float>
}
Status Codes:

Rendering

POST /render_plot

Render a Matplotlib figure of the requested image type and return it as a base64-encoded PNG.

For 2D image types ("data", "deproj", "model", "residuals", "polar"):

  • Intensity normalisation uses the selected stretch function (AsinhStretch, LogStretch, LinearStretch, or SqrtStretch).

  • If show_axes is True, axis labels, title, and optionally a colorbar and grid are rendered.

  • If show_beam is True and BMAJ/BMIN are present in the header, a beam ellipse is overlaid in the lower-left region.

  • If contours is True, ax.contour is called with contour_levels levels.

For "profile" type:

  • A log-scale 1D plot of the brightness temperature profile is generated.

Request body: PlotParams

Status Codes:
{
  "image": "data:image/png;base64,...",
  "stats": {
    "min": <float>,
    "max": <float>,
    "vmin_used": <float>,
    "vmax_used": <float>,
    "cmap_used": <str>
  }
}
Status Codes:

Download and Metadata

GET /download_fits

Return a pipeline output array as a binary FITS file, preserving the original FITS header.

Query parameter: type — one of "data", "deproj", "model", "residuals", "polar".

Status Codes:
  • 200 OK – Binary FITS file with Content-Disposition: attachment; filename=result_<type>.fits

  • 400 Bad Request – If the requested data type is not available.

GET /query_simbad

Query CDS SIMBAD for objects within 2 arcmin of the loaded FITS image centre. Reads the WCS from the header to compute the sky position.

Requests the following VOTable fields: otype, flux(V), distance.

Requires astroquery to be installed.

Status Codes:

Static File Serving

GET /assets/<path>

Serves static assets from disco/static/assets/ (Vite build output).

GET /{full_path}

Catch-all route. If the path resolves to an existing file in disco/static/, serves it directly; otherwise serves disco/static/index.html (enabling React client-side routing).

All responses include Cache-Control: no-cache headers to prevent stale asset delivery.


Server Lifecycle

disco.server.start_server()[source]

Called by disco.main.run() when gui is the first argument. Prints the server address to stdout, starts a background thread that opens the default browser at http://localhost:8000 after a 1.5-second delay, and starts Uvicorn:

uvicorn.run(app, host="0.0.0.0", port=8000, log_level="warning")

On shutdown, the @app.on_event("shutdown") handler calls wipe_session_logic() to clean up the upload directory and reset session state.