Spaces:
Sleeping
Sleeping
Update yt/mcp_output/mcp_plugin/mcp_service.py
Browse files
yt/mcp_output/mcp_plugin/mcp_service.py
CHANGED
|
@@ -1,72 +1,404 @@
|
|
| 1 |
import os
|
| 2 |
import sys
|
| 3 |
-
|
| 4 |
-
# Path settings to include the local source directory
|
| 5 |
-
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 6 |
-
if source_path not in sys.path:
|
| 7 |
-
sys.path.insert(0, source_path)
|
| 8 |
|
| 9 |
from fastmcp import FastMCP
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
from yt
|
|
|
|
| 14 |
|
| 15 |
# Create the FastMCP service application
|
| 16 |
mcp = FastMCP("yt_service")
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
"""
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
"""
|
| 26 |
try:
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
except Exception as e:
|
| 30 |
-
return {"success": False, "error": str(e)}
|
|
|
|
| 31 |
|
| 32 |
-
@mcp.tool(name="
|
| 33 |
-
def
|
| 34 |
"""
|
| 35 |
-
|
| 36 |
|
| 37 |
-
:
|
| 38 |
-
|
| 39 |
-
:param axis: The axis to plot along.
|
| 40 |
-
:return: Dictionary with success status and plot window object or error message.
|
| 41 |
"""
|
| 42 |
try:
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
except Exception as e:
|
| 46 |
-
return {"success": False, "error": str(e)}
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
|
|
|
| 50 |
"""
|
| 51 |
-
|
| 52 |
|
| 53 |
-
:
|
| 54 |
-
|
| 55 |
-
:return: Dictionary with success status and field info or error message.
|
| 56 |
"""
|
| 57 |
try:
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
except Exception as e:
|
| 61 |
-
return {"success": False, "error": str(e)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
| 63 |
def create_app() -> FastMCP:
|
| 64 |
"""
|
| 65 |
Create and return the FastMCP application instance.
|
| 66 |
|
| 67 |
-
:
|
|
|
|
| 68 |
"""
|
| 69 |
return mcp
|
| 70 |
-
|
| 71 |
-
# Ensure the application is created when the module is imported
|
| 72 |
-
app = create_app()
|
|
|
|
| 1 |
import os
|
| 2 |
import sys
|
| 3 |
+
from typing import List, Optional, Dict, Any
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
from fastmcp import FastMCP
|
| 6 |
+
|
| 7 |
+
# Import yt from PyPI (will be installed via requirements.txt)
|
| 8 |
+
import yt
|
| 9 |
+
from yt import load
|
| 10 |
+
from yt.units import dimensions
|
| 11 |
|
| 12 |
# Create the FastMCP service application
|
| 13 |
mcp = FastMCP("yt_service")
|
| 14 |
|
| 15 |
+
|
| 16 |
+
@mcp.tool(name="get_yt_version", description="Get yt library version and configuration")
|
| 17 |
+
def get_yt_version() -> dict:
|
| 18 |
+
"""
|
| 19 |
+
Get the yt library version and configuration.
|
| 20 |
+
|
| 21 |
+
Returns:
|
| 22 |
+
- dict: Version and configuration information.
|
| 23 |
+
"""
|
| 24 |
+
try:
|
| 25 |
+
return {
|
| 26 |
+
"success": True,
|
| 27 |
+
"result": {
|
| 28 |
+
"version": yt.__version__,
|
| 29 |
+
"description": "yt is a toolkit for analyzing and visualizing volumetric data"
|
| 30 |
+
},
|
| 31 |
+
"error": None
|
| 32 |
+
}
|
| 33 |
+
except Exception as e:
|
| 34 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
@mcp.tool(name="list_sample_datasets", description="List available sample datasets in yt")
|
| 38 |
+
def list_sample_datasets() -> dict:
|
| 39 |
+
"""
|
| 40 |
+
List available sample datasets that can be loaded with yt.load_sample().
|
| 41 |
+
|
| 42 |
+
Returns:
|
| 43 |
+
- dict: List of sample datasets.
|
| 44 |
+
"""
|
| 45 |
+
try:
|
| 46 |
+
# Common sample datasets in yt
|
| 47 |
+
datasets = {
|
| 48 |
+
"IsolatedGalaxy": "Isolated galaxy simulation (ENZO)",
|
| 49 |
+
"enzo_tiny_cosmology": "Tiny cosmology dataset (ENZO)",
|
| 50 |
+
"output_00080": "RAMSES output",
|
| 51 |
+
"GasSloshingLowRes": "Gas sloshing simulation",
|
| 52 |
+
"WindTunnel": "Wind tunnel test problem",
|
| 53 |
+
"DD0010": "ENZO data dump",
|
| 54 |
+
"cluster_merger_rockstar_halos": "Cluster merger with Rockstar halos",
|
| 55 |
+
"KelvinHelmholtz_hdf5_chk_0100": "Kelvin-Helmholtz instability (FLASH)",
|
| 56 |
+
}
|
| 57 |
+
return {"success": True, "result": datasets, "error": None}
|
| 58 |
+
except Exception as e:
|
| 59 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
@mcp.tool(name="list_frontends", description="List available data frontends in yt")
|
| 63 |
+
def list_frontends() -> dict:
|
| 64 |
+
"""
|
| 65 |
+
List available data frontends (simulation code formats) supported by yt.
|
| 66 |
+
|
| 67 |
+
Returns:
|
| 68 |
+
- dict: Dictionary of frontends and descriptions.
|
| 69 |
+
"""
|
| 70 |
+
try:
|
| 71 |
+
frontends = {
|
| 72 |
+
"enzo": "Enzo AMR cosmology code",
|
| 73 |
+
"flash": "FLASH multiphysics code",
|
| 74 |
+
"ramses": "RAMSES AMR code",
|
| 75 |
+
"athena": "Athena MHD code",
|
| 76 |
+
"athena_pp": "Athena++ MHD code",
|
| 77 |
+
"gadget": "Gadget N-body/SPH code",
|
| 78 |
+
"tipsy": "Tipsy/ChaNGa SPH code",
|
| 79 |
+
"arepo": "Arepo moving-mesh code",
|
| 80 |
+
"gizmo": "GIZMO meshless code",
|
| 81 |
+
"swift": "SWIFT SPH code",
|
| 82 |
+
"art": "ART cosmology code",
|
| 83 |
+
"chombo": "Chombo AMR library",
|
| 84 |
+
"boxlib": "BoxLib/AMReX framework",
|
| 85 |
+
"fits": "FITS astronomical format",
|
| 86 |
+
"hdf5": "Generic HDF5",
|
| 87 |
+
"stream": "In-memory particle/grid data"
|
| 88 |
+
}
|
| 89 |
+
return {"success": True, "result": frontends, "error": None}
|
| 90 |
+
except Exception as e:
|
| 91 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
@mcp.tool(name="list_field_types", description="List common field types in yt")
|
| 95 |
+
def list_field_types() -> dict:
|
| 96 |
+
"""
|
| 97 |
+
List common field types available in yt datasets.
|
| 98 |
+
|
| 99 |
+
Returns:
|
| 100 |
+
- dict: Field categories and examples.
|
| 101 |
"""
|
| 102 |
+
try:
|
| 103 |
+
field_types = {
|
| 104 |
+
"gas": {
|
| 105 |
+
"description": "Gas/fluid fields",
|
| 106 |
+
"examples": ["density", "temperature", "pressure", "velocity_x", "velocity_y", "velocity_z", "entropy", "specific_thermal_energy"]
|
| 107 |
+
},
|
| 108 |
+
"particle": {
|
| 109 |
+
"description": "Particle fields (dark matter, stars)",
|
| 110 |
+
"examples": ["particle_mass", "particle_position", "particle_velocity"]
|
| 111 |
+
},
|
| 112 |
+
"derived": {
|
| 113 |
+
"description": "Derived/computed fields",
|
| 114 |
+
"examples": ["cell_volume", "cell_mass", "sound_speed", "mach_number", "magnetic_field_strength"]
|
| 115 |
+
},
|
| 116 |
+
"index": {
|
| 117 |
+
"description": "Grid index fields",
|
| 118 |
+
"examples": ["x", "y", "z", "dx", "dy", "dz", "radius"]
|
| 119 |
+
}
|
| 120 |
+
}
|
| 121 |
+
return {"success": True, "result": field_types, "error": None}
|
| 122 |
+
except Exception as e:
|
| 123 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 124 |
+
|
| 125 |
|
| 126 |
+
@mcp.tool(name="list_plot_types", description="List available plot types in yt")
|
| 127 |
+
def list_plot_types() -> dict:
|
| 128 |
+
"""
|
| 129 |
+
List available visualization/plot types in yt.
|
| 130 |
+
|
| 131 |
+
Returns:
|
| 132 |
+
- dict: Plot types and descriptions.
|
| 133 |
"""
|
| 134 |
try:
|
| 135 |
+
plot_types = {
|
| 136 |
+
"SlicePlot": {
|
| 137 |
+
"description": "2D slice through data at a specific location",
|
| 138 |
+
"usage": "yt.SlicePlot(ds, 'z', 'density')"
|
| 139 |
+
},
|
| 140 |
+
"ProjectionPlot": {
|
| 141 |
+
"description": "2D projection (integral) along an axis",
|
| 142 |
+
"usage": "yt.ProjectionPlot(ds, 'z', 'density')"
|
| 143 |
+
},
|
| 144 |
+
"PhasePlot": {
|
| 145 |
+
"description": "2D histogram of two fields colored by third",
|
| 146 |
+
"usage": "yt.PhasePlot(ad, 'density', 'temperature', 'cell_mass')"
|
| 147 |
+
},
|
| 148 |
+
"ProfilePlot": {
|
| 149 |
+
"description": "1D binned profile of fields",
|
| 150 |
+
"usage": "yt.ProfilePlot(ad, 'radius', 'density')"
|
| 151 |
+
},
|
| 152 |
+
"ParticlePlot": {
|
| 153 |
+
"description": "Scatter plot of particle positions",
|
| 154 |
+
"usage": "yt.ParticlePlot(ds, 'particle_position_x', 'particle_position_y')"
|
| 155 |
+
},
|
| 156 |
+
"OffAxisSlicePlot": {
|
| 157 |
+
"description": "Slice along arbitrary vector",
|
| 158 |
+
"usage": "yt.OffAxisSlicePlot(ds, normal, 'density')"
|
| 159 |
+
},
|
| 160 |
+
"OffAxisProjectionPlot": {
|
| 161 |
+
"description": "Projection along arbitrary vector",
|
| 162 |
+
"usage": "yt.OffAxisProjectionPlot(ds, normal, 'density')"
|
| 163 |
+
}
|
| 164 |
+
}
|
| 165 |
+
return {"success": True, "result": plot_types, "error": None}
|
| 166 |
except Exception as e:
|
| 167 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 168 |
+
|
| 169 |
|
| 170 |
+
@mcp.tool(name="list_data_objects", description="List available data selection objects in yt")
|
| 171 |
+
def list_data_objects() -> dict:
|
| 172 |
"""
|
| 173 |
+
List available data selection objects for extracting regions of data.
|
| 174 |
|
| 175 |
+
Returns:
|
| 176 |
+
- dict: Data object types and descriptions.
|
|
|
|
|
|
|
| 177 |
"""
|
| 178 |
try:
|
| 179 |
+
data_objects = {
|
| 180 |
+
"all_data": {
|
| 181 |
+
"description": "Select entire domain",
|
| 182 |
+
"usage": "ds.all_data()"
|
| 183 |
+
},
|
| 184 |
+
"sphere": {
|
| 185 |
+
"description": "Spherical region",
|
| 186 |
+
"usage": "ds.sphere(center, radius)"
|
| 187 |
+
},
|
| 188 |
+
"region": {
|
| 189 |
+
"description": "Rectangular box region",
|
| 190 |
+
"usage": "ds.region(center, left_edge, right_edge)"
|
| 191 |
+
},
|
| 192 |
+
"disk": {
|
| 193 |
+
"description": "Cylindrical disk region",
|
| 194 |
+
"usage": "ds.disk(center, normal, radius, height)"
|
| 195 |
+
},
|
| 196 |
+
"ray": {
|
| 197 |
+
"description": "1D ray through domain",
|
| 198 |
+
"usage": "ds.ray(start_point, end_point)"
|
| 199 |
+
},
|
| 200 |
+
"slice": {
|
| 201 |
+
"description": "2D slice at fixed coordinate",
|
| 202 |
+
"usage": "ds.slice(axis, coordinate)"
|
| 203 |
+
},
|
| 204 |
+
"covering_grid": {
|
| 205 |
+
"description": "Uniformly spaced grid covering region",
|
| 206 |
+
"usage": "ds.covering_grid(level, left_edge, dims)"
|
| 207 |
+
},
|
| 208 |
+
"arbitrary_grid": {
|
| 209 |
+
"description": "Grid with arbitrary spacing",
|
| 210 |
+
"usage": "ds.arbitrary_grid(left_edge, right_edge, dims)"
|
| 211 |
+
},
|
| 212 |
+
"cut_region": {
|
| 213 |
+
"description": "Region defined by conditional expression",
|
| 214 |
+
"usage": "ad.cut_region(['obj[\"temperature\"] > 1e6'])"
|
| 215 |
+
}
|
| 216 |
+
}
|
| 217 |
+
return {"success": True, "result": data_objects, "error": None}
|
| 218 |
except Exception as e:
|
| 219 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 220 |
|
| 221 |
+
|
| 222 |
+
@mcp.tool(name="list_units", description="List common units and unit systems in yt")
|
| 223 |
+
def list_units() -> dict:
|
| 224 |
"""
|
| 225 |
+
List common units and unit systems available in yt.
|
| 226 |
|
| 227 |
+
Returns:
|
| 228 |
+
- dict: Unit categories and examples.
|
|
|
|
| 229 |
"""
|
| 230 |
try:
|
| 231 |
+
units = {
|
| 232 |
+
"length": ["cm", "m", "km", "pc", "kpc", "Mpc", "AU", "ly", "Rsun"],
|
| 233 |
+
"mass": ["g", "kg", "Msun", "Mjup", "Mearth"],
|
| 234 |
+
"time": ["s", "yr", "Myr", "Gyr"],
|
| 235 |
+
"velocity": ["cm/s", "m/s", "km/s", "km/h"],
|
| 236 |
+
"density": ["g/cm**3", "kg/m**3", "Msun/kpc**3"],
|
| 237 |
+
"temperature": ["K", "keV"],
|
| 238 |
+
"energy": ["erg", "J", "eV", "keV"],
|
| 239 |
+
"magnetic": ["gauss", "T"],
|
| 240 |
+
"cgs_units": "Base CGS system (cm, g, s)",
|
| 241 |
+
"mks_units": "Base MKS/SI system (m, kg, s)",
|
| 242 |
+
"galactic_units": "Galactic units (kpc, Msun, Myr)"
|
| 243 |
+
}
|
| 244 |
+
return {"success": True, "result": units, "error": None}
|
| 245 |
except Exception as e:
|
| 246 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
@mcp.tool(name="list_colormaps", description="List recommended colormaps for yt")
|
| 250 |
+
def list_colormaps() -> dict:
|
| 251 |
+
"""
|
| 252 |
+
List recommended colormaps for scientific visualization in yt.
|
| 253 |
+
|
| 254 |
+
Returns:
|
| 255 |
+
- dict: Colormap categories and names.
|
| 256 |
+
"""
|
| 257 |
+
try:
|
| 258 |
+
colormaps = {
|
| 259 |
+
"yt_native": ["algae", "kamae", "arbre", "octarine", "kelp", "dusk", "B-W LINEAR"],
|
| 260 |
+
"sequential": ["viridis", "plasma", "inferno", "magma", "cividis"],
|
| 261 |
+
"diverging": ["RdBu", "RdYlBu", "coolwarm", "seismic", "bwr"],
|
| 262 |
+
"perceptually_uniform": ["viridis", "plasma", "inferno", "magma", "cividis"],
|
| 263 |
+
"notes": {
|
| 264 |
+
"default": "arbre is the default yt colormap",
|
| 265 |
+
"recommendation": "Use perceptually uniform colormaps for quantitative data",
|
| 266 |
+
"diverging_use": "Diverging colormaps are good for data with a meaningful midpoint"
|
| 267 |
+
}
|
| 268 |
+
}
|
| 269 |
+
return {"success": True, "result": colormaps, "error": None}
|
| 270 |
+
except Exception as e:
|
| 271 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
@mcp.tool(name="get_yt_code_example", description="Get example code for common yt operations")
|
| 275 |
+
def get_yt_code_example(operation: str) -> dict:
|
| 276 |
+
"""
|
| 277 |
+
Get example code for common yt operations.
|
| 278 |
+
|
| 279 |
+
Parameters:
|
| 280 |
+
- operation: The operation to get example code for.
|
| 281 |
+
Options: "load", "slice", "projection", "profile", "phase", "sphere", "volume_render"
|
| 282 |
+
|
| 283 |
+
Returns:
|
| 284 |
+
- dict: Example code and explanation.
|
| 285 |
+
"""
|
| 286 |
+
try:
|
| 287 |
+
examples = {
|
| 288 |
+
"load": {
|
| 289 |
+
"code": """
|
| 290 |
+
import yt
|
| 291 |
+
# Load a dataset
|
| 292 |
+
ds = yt.load("path/to/dataset")
|
| 293 |
+
# Print basic info
|
| 294 |
+
print(ds)
|
| 295 |
+
print(ds.field_list)
|
| 296 |
+
print(ds.derived_field_list)
|
| 297 |
+
""",
|
| 298 |
+
"description": "Load a dataset and inspect its properties"
|
| 299 |
+
},
|
| 300 |
+
"slice": {
|
| 301 |
+
"code": """
|
| 302 |
+
import yt
|
| 303 |
+
ds = yt.load("path/to/dataset")
|
| 304 |
+
# Create a slice plot along z-axis
|
| 305 |
+
slc = yt.SlicePlot(ds, 'z', 'density')
|
| 306 |
+
slc.set_cmap('density', 'viridis')
|
| 307 |
+
slc.annotate_grids() # Show AMR grid structure
|
| 308 |
+
slc.save('slice.png')
|
| 309 |
+
""",
|
| 310 |
+
"description": "Create a 2D slice plot of density"
|
| 311 |
+
},
|
| 312 |
+
"projection": {
|
| 313 |
+
"code": """
|
| 314 |
+
import yt
|
| 315 |
+
ds = yt.load("path/to/dataset")
|
| 316 |
+
# Create a projection (column density)
|
| 317 |
+
prj = yt.ProjectionPlot(ds, 'z', 'density', weight_field='density')
|
| 318 |
+
prj.set_unit('density', 'g/cm**2')
|
| 319 |
+
prj.save('projection.png')
|
| 320 |
+
""",
|
| 321 |
+
"description": "Create a 2D projection plot"
|
| 322 |
+
},
|
| 323 |
+
"profile": {
|
| 324 |
+
"code": """
|
| 325 |
+
import yt
|
| 326 |
+
ds = yt.load("path/to/dataset")
|
| 327 |
+
ad = ds.all_data()
|
| 328 |
+
# Create 1D radial profile
|
| 329 |
+
profile = yt.create_profile(ad, 'radius', 'density', weight_field='cell_mass')
|
| 330 |
+
# Plot it
|
| 331 |
+
plot = yt.ProfilePlot.from_profiles(profile)
|
| 332 |
+
plot.save('profile.png')
|
| 333 |
+
""",
|
| 334 |
+
"description": "Create a 1D radial profile"
|
| 335 |
+
},
|
| 336 |
+
"phase": {
|
| 337 |
+
"code": """
|
| 338 |
+
import yt
|
| 339 |
+
ds = yt.load("path/to/dataset")
|
| 340 |
+
ad = ds.all_data()
|
| 341 |
+
# Create 2D phase plot
|
| 342 |
+
phase = yt.PhasePlot(ad, 'density', 'temperature', 'cell_mass', weight_field=None)
|
| 343 |
+
phase.set_unit('density', 'g/cm**3')
|
| 344 |
+
phase.set_unit('temperature', 'K')
|
| 345 |
+
phase.save('phase.png')
|
| 346 |
+
""",
|
| 347 |
+
"description": "Create a 2D phase diagram"
|
| 348 |
+
},
|
| 349 |
+
"sphere": {
|
| 350 |
+
"code": """
|
| 351 |
+
import yt
|
| 352 |
+
ds = yt.load("path/to/dataset")
|
| 353 |
+
# Create spherical region around center
|
| 354 |
+
center = ds.domain_center
|
| 355 |
+
sp = ds.sphere(center, (100, 'kpc'))
|
| 356 |
+
# Get data from sphere
|
| 357 |
+
density = sp['gas', 'density']
|
| 358 |
+
temperature = sp['gas', 'temperature']
|
| 359 |
+
# Compute quantities
|
| 360 |
+
total_mass = sp.quantities.total_mass()
|
| 361 |
+
""",
|
| 362 |
+
"description": "Extract data from a spherical region"
|
| 363 |
+
},
|
| 364 |
+
"volume_render": {
|
| 365 |
+
"code": """
|
| 366 |
+
import yt
|
| 367 |
+
ds = yt.load("path/to/dataset")
|
| 368 |
+
# Create volume rendering
|
| 369 |
+
sc = yt.create_scene(ds, field='density')
|
| 370 |
+
# Customize transfer function
|
| 371 |
+
source = sc[0]
|
| 372 |
+
source.tfh.set_bounds((1e-30, 1e-23))
|
| 373 |
+
source.tfh.set_log(True)
|
| 374 |
+
# Render and save
|
| 375 |
+
sc.save('volume_render.png', sigma_clip=4)
|
| 376 |
+
""",
|
| 377 |
+
"description": "Create a 3D volume rendering"
|
| 378 |
+
}
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
if operation.lower() in examples:
|
| 382 |
+
return {"success": True, "result": examples[operation.lower()], "error": None}
|
| 383 |
+
else:
|
| 384 |
+
return {
|
| 385 |
+
"success": True,
|
| 386 |
+
"result": {
|
| 387 |
+
"available_operations": list(examples.keys()),
|
| 388 |
+
"message": f"Operation '{operation}' not found. Available: {list(examples.keys())}"
|
| 389 |
+
},
|
| 390 |
+
"error": None
|
| 391 |
+
}
|
| 392 |
+
except Exception as e:
|
| 393 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 394 |
+
|
| 395 |
|
| 396 |
def create_app() -> FastMCP:
|
| 397 |
"""
|
| 398 |
Create and return the FastMCP application instance.
|
| 399 |
|
| 400 |
+
Returns:
|
| 401 |
+
- FastMCP: The FastMCP application instance.
|
| 402 |
"""
|
| 403 |
return mcp
|
| 404 |
+
|
|
|
|
|
|