Skip to content

Commit

Permalink
Remove Unions (#137)
Browse files Browse the repository at this point in the history
* removed union response models from getters of surface normals and reference vectors

* removed CoordinateResponse object and separated into other response models
  • Loading branch information
rosesyrett authored Nov 30, 2022
1 parent 41d8d68 commit 930e098
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 50 deletions.
29 changes: 23 additions & 6 deletions src/diffcalc_api/models/response.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Pydantic models relating to all endpoint responses."""
from typing import Dict, List, Union
from typing import Dict, List

from pydantic import BaseModel

Expand Down Expand Up @@ -46,14 +46,31 @@ class DiffractorAnglesResponse(BaseModel):
payload: List[Dict[str, float]]


class CoordinateResponse(BaseModel):
"""Coordinate response model.
class SphericalResponse(BaseModel):
"""Spherical coordinate response model.
Returns coordinates, in three dimensions, for a given coordinate system.
Supported systems include spherical coordinates, reciprocal and real space.
Returns a payload in spherical coordinates.
"""

payload: Union[SphericalCoordinates, HklModel, XyzModel]
payload: SphericalCoordinates


class ReciprocalSpaceResponse(BaseModel):
"""Reciprocal space coordinate response model.
Returns a payload in reciprocal space (hkl) coordinates.
"""

payload: HklModel


class RealSpaceResponse(BaseModel):
"""Reciprocal space coordinate response model.
Returns a payload in xyz coordinates.
"""

payload: XyzModel


class MiscutResponse(BaseModel):
Expand Down
8 changes: 4 additions & 4 deletions src/diffcalc_api/routes/hkl.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from diffcalc_api.errors.hkl import InvalidSolutionBoundsError
from diffcalc_api.models.hkl import SolutionConstraints
from diffcalc_api.models.response import (
CoordinateResponse,
DiffractorAnglesResponse,
ReciprocalSpaceResponse,
ScanResponse,
)
from diffcalc_api.models.ub import HklModel, PositionModel
Expand Down Expand Up @@ -60,7 +60,7 @@ async def lab_position_from_miller_indices(
return DiffractorAnglesResponse(payload=positions)


@router.get("/{name}/position/hkl", response_model=CoordinateResponse)
@router.get("/{name}/position/hkl", response_model=ReciprocalSpaceResponse)
async def miller_indices_from_lab_position(
name: str,
pos: PositionModel = Depends(),
Expand All @@ -78,12 +78,12 @@ async def miller_indices_from_lab_position(
collection: collection within which the hkl object resides.
Returns:
CoordinateResponse containing the miller indices.
ReciprocalSpaceResponse containing the miller indices.
"""
hkl = await service.miller_indices_from_lab_position(
name, pos, wavelength, store, collection
)
return CoordinateResponse(payload=hkl)
return ReciprocalSpaceResponse(payload=hkl)


@router.get("/{name}/scan/hkl", response_model=ScanResponse)
Expand Down
75 changes: 35 additions & 40 deletions src/diffcalc_api/routes/ub.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Endpoints relating to the management of setting up the UB calculation."""

from typing import List, Optional, Union
from typing import List, Optional, cast

from fastapi import APIRouter, Body, Depends, Query

Expand All @@ -12,9 +12,10 @@
from diffcalc_api.examples import ub as examples
from diffcalc_api.models.response import (
ArrayResponse,
CoordinateResponse,
InfoResponse,
MiscutResponse,
ReciprocalSpaceResponse,
SphericalResponse,
StringResponse,
)
from diffcalc_api.models.ub import (
Expand Down Expand Up @@ -611,7 +612,7 @@ async def set_miller_surface_normal(
)


@router.get("/{name}/nphi", response_model=Union[ArrayResponse, InfoResponse])
@router.get("/{name}/nphi", response_model=ArrayResponse)
async def get_lab_reference_vector(
name: str,
store: HklCalcStore = Depends(get_store),
Expand All @@ -625,20 +626,20 @@ async def get_lab_reference_vector(
collection: collection within which the hkl object resides.
Returns:
ArrayResponse with the vector, or
InfoResponse if it doesn't exist
ArrayResponse with the vector. If it doesn't exist, a null vector is returned.
"""
lab_vector: Optional[List[List[float]]] = await service.get_lab_reference_vector(
vector: Optional[List[List[float]]] = await service.get_lab_reference_vector(
name, store, collection
)
if lab_vector is not None:
return ArrayResponse(payload=lab_vector)
else:
return InfoResponse(message="This vector does not exist.")

if vector is None:
return ArrayResponse(payload=[[]])

@router.get("/{name}/nhkl", response_model=Union[ArrayResponse, InfoResponse])
return ArrayResponse(payload=vector)


@router.get("/{name}/nhkl", response_model=ArrayResponse)
async def get_miller_reference_vector(
name: str,
store: HklCalcStore = Depends(get_store),
Expand All @@ -652,20 +653,18 @@ async def get_miller_reference_vector(
collection: collection within which the hkl object resides.
Returns:
ArrayResponse with the vector, or
InfoResponse if it doesn't exist
ArrayResponse with the vector. By default, newly instantiated
Hkl objects always have this vector.
"""
lab_vector: Optional[List[List[float]]] = await service.get_miller_reference_vector(
vector: Optional[List[List[float]]] = await service.get_miller_reference_vector(
name, store, collection
)
if lab_vector is not None:
return ArrayResponse(payload=lab_vector)
else:
return InfoResponse(message="This vector does not exist.")

return ArrayResponse(payload=cast(List[List[float]], vector))

@router.get("/{name}/surface/nphi", response_model=Union[ArrayResponse, InfoResponse])

@router.get("/{name}/surface/nphi", response_model=ArrayResponse)
async def get_lab_surface_normal(
name: str,
store: HklCalcStore = Depends(get_store),
Expand All @@ -679,20 +678,17 @@ async def get_lab_surface_normal(
collection: collection within which the hkl object resides.
Returns:
ArrayResponse with the vector, or
InfoResponse if it doesn't exist
ArrayResponse with the vector. By default, newly instantiated
Hkl objects always have this vector.
"""
lab_vector: Optional[List[List[float]]] = await service.get_lab_surface_normal(
vector: Optional[List[List[float]]] = await service.get_lab_surface_normal(
name, store, collection
)
if lab_vector is not None:
return ArrayResponse(payload=lab_vector)
else:
return InfoResponse(message="This vector does not exist.")
return ArrayResponse(payload=cast(List[List[float]], vector))


@router.get("/{name}/surface/nhkl", response_model=Union[ArrayResponse, InfoResponse])
@router.get("/{name}/surface/nhkl", response_model=ArrayResponse)
async def get_miller_surface_normal(
name: str,
store: HklCalcStore = Depends(get_store),
Expand All @@ -706,25 +702,22 @@ async def get_miller_surface_normal(
collection: collection within which the hkl object resides.
Returns:
ArrayResponse with the vector, or
InfoResponse if it doesn't exist
ArrayResponse with the vector. By default, newly instantiated
Hkl objects always have this vector.
"""
lab_vector: Optional[List[List[float]]] = await service.get_miller_surface_normal(
vector: Optional[List[List[float]]] = await service.get_miller_surface_normal(
name, store, collection
)
if lab_vector is not None:
return ArrayResponse(payload=lab_vector)
else:
return InfoResponse(message="This vector does not exist.")
return ArrayResponse(payload=cast(List[List[float]], vector))


#######################################################################################
# Vector Calculations in HKL Space #
#######################################################################################


@router.get("/{name}/vector", response_model=CoordinateResponse)
@router.get("/{name}/vector", response_model=ReciprocalSpaceResponse)
async def calculate_vector_from_hkl_and_offset(
name: str,
hkl_ref: HklModel = Depends(),
Expand All @@ -747,18 +740,20 @@ async def calculate_vector_from_hkl_and_offset(
collection: collection within which the hkl object resides.
Returns:
CoordinateResponse
ReciprocalSpaceResponse
Containing the calculated reciprocal space vector as h, k, l indices.
"""
vector = await service.calculate_vector_from_hkl_and_offset(
name, hkl_ref, polar_angle, azimuth_angle, store, collection
)

return CoordinateResponse(payload=HklModel(h=vector[0], k=vector[1], l=vector[2]))
return ReciprocalSpaceResponse(
payload=HklModel(h=vector[0], k=vector[1], l=vector[2])
)


@router.get("/{name}/offset", response_model=CoordinateResponse)
@router.get("/{name}/offset", response_model=SphericalResponse)
async def calculate_offset_from_vector_and_hkl(
name: str,
h1: float = Query(..., example=0.0),
Expand Down Expand Up @@ -787,7 +782,7 @@ async def calculate_offset_from_vector_and_hkl(
collection: collection within which the hkl object resides.
Returns:
CoordinateResponse
SphericalResponse
The offset, in spherical coordinates, between the two reciprocal space vectors,
containing the polar angle, azimuth angle and magnitude between them.
Expand All @@ -799,7 +794,7 @@ async def calculate_offset_from_vector_and_hkl(
name, hkl_offset, hkl_ref, store, collection
)

return CoordinateResponse(
return SphericalResponse(
payload=SphericalCoordinates(
polar_angle=vector[0], azimuth_angle=vector[1], magnitude=vector[2]
)
Expand Down
9 changes: 9 additions & 0 deletions tests/test_ubcalc.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,15 @@ def test_get_and_set_reference_vectors_hkl(
)


def test_get_reference_vectors_for_null_vectors():
ubcalc = UBCalculation()
hkl = HklCalculation(ubcalc, Constraints())
client = Client(hkl).client

response = client.get("/ub/test/nphi?collection=B07")
assert literal_eval(response.content.decode())["payload"] == [[]]


def test_calculate_vector_from_hkl_and_offset():
ubcalc = UBCalculation()
ubcalc.UB = np.identity(3)
Expand Down

0 comments on commit 930e098

Please sign in to comment.