"""Module template was autogenerated from sharepoint list schema."""

from dataclasses import dataclass
from datetime import date, datetime
from enum import Enum
from typing import Any, List, Optional

from aind_data_schema.procedures import (
    Anaesthetic,
    BrainInjection,
    CoordinateReferenceLocation,
    Craniotomy,
    CraniotomyType,
    FiberImplant,
    Headframe,
    InjectionMaterial,
    IontophoresisInjection,
    NanojectInjection,
    OphysProbe,
    ProbeName,
    Side,
    SubjectProcedure,
)
from aind_data_schema.subject import Sex

from aind_metadata_service.sharepoint.nsb2023.models import NSBList
from aind_metadata_service.sharepoint.nsb2023.models import (
    Procedure as NSBProcedure,
)
from aind_metadata_service.sharepoint.nsb2023.models import (
    ProcedureCategory as NSBProcedureCategory,
)


class BurrHoleProcedure(Enum):
    """Enum class for BurrHoleProcedure"""

    INJECTION = "Injection"
    FIBER_IMPLANT = "Fiber Implant"
    INJECTION_FIBER_IMPLANT = "Injection and Fiber Implant"


class During(Enum):
    """Enum class for During"""

    INITIAL = "Initial Surgery"
    FOLLOW_UP = "Follow-up"


class HeadPost(Enum):
    """Enum class for HeadPost"""

    AI_HEADBAR = "AI Straight bar"
    WHC_NP = "WHC NP"
    WHC_2P = "WHC 2P"
    VISUAL_CTX = "Visual Ctx"
    FRONTAL_CTX = "Frontal Ctx"
    MOTOR_CTX = "Motor Ctx"


class HeadPostType(Enum):
    """Enum class for HeadPostType"""

    NEUROPIXEL = "Neuropixel"
    MESOSCOPE = "Mesoscope"
    NO_WELL = "No Well"
    CAM = "Scientifica (CAM)"
    WHC_NP = "WHC NP"
    WHC_2P = "WHC 2P"


class InjectionType(Enum):
    """Enum class for Injection Types"""

    NANOJECT = "Nanoject"
    IONTOPHORESIS = "Iontophoresis"


@dataclass
class SurgeryDuringInfo:
    """Container for information related to surgeries during initial or
    follow-up sessions"""

    anaesthetic_duration_in_minutes: Optional[int] = None
    anaesthetic_level: Optional[float] = None
    start_date: Optional[datetime] = None
    workstation_id: Optional[str] = None
    recovery_time: Optional[float] = None
    weight_prior: Optional[float] = None
    weight_post: Optional[float] = None
    instrument_id: Optional[str] = None


@dataclass
class BurrHoleInfo:
    """Container for burr hole information"""

    hemisphere: Optional[Side] = None
    coordinate_ml: Optional[float] = None
    coordinate_ap: Optional[float] = None
    coordinate_depth: Optional[float] = None
    angle: Optional[float] = None
    during: Optional[During] = None
    inj_type: Optional[InjectionType] = None
    virus_strain: Optional[str] = None
    inj_current: Optional[float] = None
    alternating_current: Optional[str] = None
    inj_duration: Optional[float] = None
    inj_volume: Optional[float] = None
    fiber_implant_depth: Optional[float] = None


@dataclass
class HeadPostInfo:
    """Extends HeadPostInfo data container to include extra constructor"""

    headframe_type: Optional[str] = None
    headframe_part_number: Optional[str] = None
    well_type: Optional[str] = None
    well_part_number: Optional[str] = None

    # flake8: noqa: C901
    @classmethod
    def from_hp_and_hp_type(
        cls, hp: Optional[HeadPost], hp_type: Optional[HeadPostType]
    ):
        """Construct HeadPostInfo2023 from headpost and headpost_type"""
        headframe_type = hp.value
        well_type = hp_type.value
        if hp == HeadPost.VISUAL_CTX:
            headframe_part_number = "0160-100-10"
        elif hp == HeadPost.WHC_NP:
            headframe_part_number = "0160-100-42"
        elif hp == HeadPost.WHC_2P:
            headframe_part_number = "0160-100-45"
        elif hp == HeadPost.FRONTAL_CTX:
            headframe_part_number = "0160-100-46"
        elif hp == HeadPost.MOTOR_CTX:
            headframe_part_number = "0160-100-51"
        else:
            headframe_part_number = None
        if hp_type == HeadPostType.CAM:
            well_part_number = "Rev A"
        elif hp_type == HeadPostType.MESOSCOPE:
            well_part_number = "0160-200-20"
        elif hp_type == HeadPostType.NEUROPIXEL:
            well_part_number = "0160-200-36"
        elif hp_type == HeadPostType.WHC_NP:
            well_part_number = "0160-055-08"
        elif hp_type == HeadPostType.WHC_2P:
            well_part_number = "0160-200-62"
        else:
            well_part_number = None
        return cls(
            headframe_type=headframe_type,
            headframe_part_number=headframe_part_number,
            well_type=well_type,
            well_part_number=well_part_number,
        )


class MappedNSBList:
    """Mapped Fields in Sharepoint list"""

    def __init__(self, nsb: NSBList):
        """Class constructor"""
        self._nsb = nsb

    @staticmethod
    def _parse_basic_float_str(float_str: Optional[str]) -> Optional[float]:
        """Parse string representation of float such as '0.25'."""
        try:
            return None if float_str is None else float(float_str)
        except ValueError:
            return None

    @staticmethod
    def _parse_ap_str(_: Optional[str]) -> Optional[float]:
        """Parse AP String"""
        # TODO: Figure out how to parse AP fields
        return None

    @staticmethod
    def _parse_dv_str(_: Optional[str]) -> Optional[float]:
        """Parse dv String"""
        # TODO: Figure out how to parse DV fields
        return None

    @staticmethod
    def _parse_ml_str(_: Optional[str]) -> Optional[float]:
        """Parse ml string"""
        # TODO: Figure out how to parse ML fields
        return None

    @staticmethod
    def _parse_angle_str(_: Optional[str]) -> Optional[float]:
        """Parse angle strings"""
        # TODO: Figure out how to parse angle fields
        return None

    @staticmethod
    def _parse_alt_time_str(_: Optional[str]) -> Optional[float]:
        """Parse alternating time strings"""
        # TODO: Figure out how to parse alternating time fields
        return None

    @staticmethod
    def _parse_current_str(_: Optional[str]) -> Optional[float]:
        """Parse current strings"""
        # TODO: Figure out how to parse current fields
        return None

    @staticmethod
    def _parse_length_of_time_str(_: Optional[str]) -> Optional[float]:
        """Parse length of time strings"""
        # TODO: Figure out how to parse length of time fields
        return None

    @staticmethod
    def _parse_datetime_to_date(dt: Optional[datetime]) -> Optional[date]:
        """Parse date from datetime"""
        return None if dt is None else dt.date()

    @staticmethod
    def _parse_fiber_implant_d(_: Optional[str]) -> Optional[float]:
        """Parse fiber implant d String"""
        # TODO: Figure out how to parse fiber_implantN_d fields
        return None

    @staticmethod
    def _parse_virus_strain_str(_: Optional[str]) -> Optional[str]:
        """Parse virus strain strings"""
        # TODO: Figure out how to parse virus strain fields
        return None

    @staticmethod
    def _parse_inj_vol_str(_: Optional[str]) -> Optional[float]:
        """Parse injection volume strings"""
        # TODO: Figure out how to parse injection volume fields
        return None

    @property
    def aind_age_at_injection(self) -> Optional[float]:
        """Maps age_at_injection to aind model"""
        return self._parse_basic_float_str(self._nsb.age_at_injection)

    @property
    def aind_ap2nd_inj(self) -> Optional[float]:
        """Maps ap2nd_inj to aind model"""
        return self._parse_ap_str(self._nsb.ap2nd_inj)

    @property
    def aind_author_id(self) -> Optional[int]:
        """Maps author_id to aind model"""
        return self._nsb.author_id

    @property
    def aind_breg2_lamb(self) -> Optional[float]:
        """Maps breg2_lamb to aind model"""
        return self._nsb.breg2_lamb

    @property
    def aind_burr1_injection_devi(self) -> Optional[Any]:
        """Maps burr1_injection_devi to aind model"""
        return (
            None
            if self._nsb.burr1_injection_devi is None
            else {
                self._nsb.burr1_injection_devi.SELECT: None,
                self._nsb.burr1_injection_devi.NANO_1: None,
                self._nsb.burr1_injection_devi.IONTO_1: None,
                self._nsb.burr1_injection_devi.NANO_2: None,
                self._nsb.burr1_injection_devi.IONTO_2: None,
                self._nsb.burr1_injection_devi.NANO_3: None,
                self._nsb.burr1_injection_devi.IONTO_3: None,
                self._nsb.burr1_injection_devi.NANO_4: None,
                self._nsb.burr1_injection_devi.IONTO_4: None,
                self._nsb.burr1_injection_devi.NANO_5: None,
                self._nsb.burr1_injection_devi.IONTO_5: None,
                self._nsb.burr1_injection_devi.NANO_6: None,
                self._nsb.burr1_injection_devi.IONTO_6: None,
                self._nsb.burr1_injection_devi.NANO_7: None,
                self._nsb.burr1_injection_devi.IONTO_7: None,
                self._nsb.burr1_injection_devi.NANO_8: None,
                self._nsb.burr1_injection_devi.IONTO_8: None,
                self._nsb.burr1_injection_devi.NANO_9: None,
                self._nsb.burr1_injection_devi.IONTO_9: None,
            }.get(self._nsb.burr1_injection_devi, None)
        )

    @property
    def aind_burr1_perform_during(self) -> Optional[During]:
        """Maps burr1_perform_during to aind model"""
        return (
            None
            if self._nsb.burr1_perform_during is None
            else {
                self._nsb.burr1_perform_during.INITIAL_SURGERY: During.INITIAL,
                self._nsb.burr1_perform_during.FOLLOW_UP_SURGERY: During.FOLLOW_UP,
            }.get(self._nsb.burr1_perform_during, None)
        )

    @property
    def aind_burr1_virus_biosafte(self) -> Optional[Any]:
        """Maps burr1_virus_biosafte to aind model"""
        return (
            None
            if self._nsb.burr1_virus_biosafte is None
            else {
                self._nsb.burr1_virus_biosafte.SELECT: None,
                self._nsb.burr1_virus_biosafte.BSL_1_AAV: None,
                self._nsb.burr1_virus_biosafte.BSL_1_BEADS: None,
                self._nsb.burr1_virus_biosafte.BSL_1_AAV_BEADS: None,
                self._nsb.burr1_virus_biosafte.BSL_1_OTHER_WRITE_IN_COMM: None,
                self._nsb.burr1_virus_biosafte.BSL_2_RABIES: None,
                self._nsb.burr1_virus_biosafte.BSL_2_CAV: None,
                self._nsb.burr1_virus_biosafte.BSL_2_6OHDA: None,
                self._nsb.burr1_virus_biosafte.BSL_2_SINDBIS: None,
                self._nsb.burr1_virus_biosafte.BSL_2_HSV1: None,
                self._nsb.burr1_virus_biosafte.BSL_2_LENTI: None,
                self._nsb.burr1_virus_biosafte.BSL_2_CHOLERA_TOXIN_B: None,
                self._nsb.burr1_virus_biosafte.BSL_2_OTHER_WRITE_IN_COMM: None,
            }.get(self._nsb.burr1_virus_biosafte, None)
        )

    @property
    def aind_burr2_injection_devi(self) -> Optional[Any]:
        """Maps burr2_injection_devi to aind model"""
        return (
            None
            if self._nsb.burr2_injection_devi is None
            else {
                self._nsb.burr2_injection_devi.SELECT: None,
                self._nsb.burr2_injection_devi.NANO_1: None,
                self._nsb.burr2_injection_devi.IONTO_1: None,
                self._nsb.burr2_injection_devi.NANO_2: None,
                self._nsb.burr2_injection_devi.IONTO_2: None,
                self._nsb.burr2_injection_devi.NANO_3: None,
                self._nsb.burr2_injection_devi.IONTO_3: None,
                self._nsb.burr2_injection_devi.NANO_4: None,
                self._nsb.burr2_injection_devi.IONTO_4: None,
                self._nsb.burr2_injection_devi.NANO_5: None,
                self._nsb.burr2_injection_devi.IONTO_5: None,
                self._nsb.burr2_injection_devi.NANO_6: None,
                self._nsb.burr2_injection_devi.IONTO_6: None,
                self._nsb.burr2_injection_devi.NANO_7: None,
                self._nsb.burr2_injection_devi.IONTO_7: None,
                self._nsb.burr2_injection_devi.NANO_8: None,
                self._nsb.burr2_injection_devi.IONTO_8: None,
                self._nsb.burr2_injection_devi.NANO_9: None,
                self._nsb.burr2_injection_devi.IONTO_9: None,
            }.get(self._nsb.burr2_injection_devi, None)
        )

    @property
    def aind_burr2_perform_during(self) -> Optional[During]:
        """Maps burr2_perform_during to aind model"""
        return (
            None
            if self._nsb.burr2_perform_during is None
            else {
                self._nsb.burr2_perform_during.INITIAL_SURGERY: During.INITIAL,
                self._nsb.burr2_perform_during.FOLLOW_UP_SURGERY: During.FOLLOW_UP,
            }.get(self._nsb.burr2_perform_during, None)
        )

    @property
    def aind_burr2_status(self) -> Optional[Any]:
        """Maps burr2_status to aind model"""
        return (
            None
            if self._nsb.burr2_status is None
            else {
                self._nsb.burr2_status.COMPLETE: None,
            }.get(self._nsb.burr2_status, None)
        )

    @property
    def aind_burr2_virus_biosafte(self) -> Optional[Any]:
        """Maps burr2_virus_biosafte to aind model"""
        return (
            None
            if self._nsb.burr2_virus_biosafte is None
            else {
                self._nsb.burr2_virus_biosafte.SELECT: None,
                self._nsb.burr2_virus_biosafte.BSL_1_AAV: None,
                self._nsb.burr2_virus_biosafte.BSL_1_BEADS: None,
                self._nsb.burr2_virus_biosafte.BSL_1_AAV_BEADS: None,
                self._nsb.burr2_virus_biosafte.BSL_1_OTHER_WRITE_IN_COMM: None,
                self._nsb.burr2_virus_biosafte.BSL_2_RABIES: None,
                self._nsb.burr2_virus_biosafte.BSL_2_CAV: None,
                self._nsb.burr2_virus_biosafte.BSL_2_6OHDA: None,
                self._nsb.burr2_virus_biosafte.BSL_2_SINDBIS: None,
                self._nsb.burr2_virus_biosafte.BSL_2_HSV1: None,
                self._nsb.burr2_virus_biosafte.BSL_2_LENTI: None,
                self._nsb.burr2_virus_biosafte.BSL_2_CHOLERA_TOXIN_B: None,
                self._nsb.burr2_virus_biosafte.BSL_2_OTHER_WRITE_IN_COMM: None,
            }.get(self._nsb.burr2_virus_biosafte, None)
        )

    @property
    def aind_burr3_a_p(self) -> Optional[float]:
        """Maps burr3_a_p to aind model"""
        return self._parse_ap_str(self._nsb.burr3_a_p)

    @property
    def aind_burr3_d_v(self) -> Optional[float]:
        """Maps burr3_d_v to aind model"""
        return self._parse_dv_str(self._nsb.burr3_d_v)

    @property
    def aind_burr3_injection_devi(self) -> Optional[Any]:
        """Maps burr3_injection_devi to aind model"""
        return (
            None
            if self._nsb.burr3_injection_devi is None
            else {
                self._nsb.burr3_injection_devi.SELECT: None,
                self._nsb.burr3_injection_devi.NANO_1: None,
                self._nsb.burr3_injection_devi.IONTO_1: None,
                self._nsb.burr3_injection_devi.NANO_2: None,
                self._nsb.burr3_injection_devi.IONTO_2: None,
                self._nsb.burr3_injection_devi.NANO_3: None,
                self._nsb.burr3_injection_devi.IONTO_3: None,
                self._nsb.burr3_injection_devi.NANO_4: None,
                self._nsb.burr3_injection_devi.IONTO_4: None,
                self._nsb.burr3_injection_devi.NANO_5: None,
                self._nsb.burr3_injection_devi.IONTO_5: None,
                self._nsb.burr3_injection_devi.NANO_6: None,
                self._nsb.burr3_injection_devi.IONTO_6: None,
                self._nsb.burr3_injection_devi.NANO_7: None,
                self._nsb.burr3_injection_devi.IONTO_7: None,
                self._nsb.burr3_injection_devi.NANO_8: None,
                self._nsb.burr3_injection_devi.IONTO_8: None,
                self._nsb.burr3_injection_devi.NANO_9: None,
                self._nsb.burr3_injection_devi.IONTO_9: None,
            }.get(self._nsb.burr3_injection_devi, None)
        )

    @property
    def aind_burr3_m_l(self) -> Optional[float]:
        """Maps burr3_m_l to aind model"""
        return self._parse_ml_str(self._nsb.burr3_m_l)

    @property
    def aind_burr3_perform_during(self) -> Optional[During]:
        """Maps burr3_perform_during to aind model"""
        return (
            None
            if self._nsb.burr3_perform_during is None
            else {
                self._nsb.burr3_perform_during.INITIAL_SURGERY: During.INITIAL,
                self._nsb.burr3_perform_during.FOLLOW_UP_SURGERY: During.FOLLOW_UP,
            }.get(self._nsb.burr3_perform_during, None)
        )

    @property
    def aind_burr3_status(self) -> Optional[Any]:
        """Maps burr3_status to aind model"""
        return (
            None
            if self._nsb.burr3_status is None
            else {
                self._nsb.burr3_status.COMPLETE: None,
            }.get(self._nsb.burr3_status, None)
        )

    @property
    def aind_burr3_virus_biosafet(self) -> Optional[Any]:
        """Maps burr3_virus_biosafet to aind model"""
        return (
            None
            if self._nsb.burr3_virus_biosafet is None
            else {
                self._nsb.burr3_virus_biosafet.SELECT: None,
                self._nsb.burr3_virus_biosafet.BSL_1_AAV: None,
                self._nsb.burr3_virus_biosafet.BSL_1_BEADS: None,
                self._nsb.burr3_virus_biosafet.BSL_1_AAV_BEADS: None,
                self._nsb.burr3_virus_biosafet.BSL_1_OTHER_WRITE_IN_COMM: None,
                self._nsb.burr3_virus_biosafet.BSL_2_RABIES: None,
                self._nsb.burr3_virus_biosafet.BSL_2_CAV: None,
                self._nsb.burr3_virus_biosafet.BSL_2_6OHDA: None,
                self._nsb.burr3_virus_biosafet.BSL_2_SINDBIS: None,
                self._nsb.burr3_virus_biosafet.BSL_2_HSV1: None,
                self._nsb.burr3_virus_biosafet.BSL_2_LENTI: None,
                self._nsb.burr3_virus_biosafet.BSL_2_CHOLERA_TOXIN_B: None,
                self._nsb.burr3_virus_biosafet.BSL_2_OTHER_WRITE_IN_COMM: None,
            }.get(self._nsb.burr3_virus_biosafet, None)
        )

    @property
    def aind_burr4_a_p(self) -> Optional[float]:
        """Maps burr4_a_p to aind model"""
        return self._parse_ap_str(self._nsb.burr4_a_p)

    @property
    def aind_burr4_d_v(self) -> Optional[str]:
        """Maps burr4_d_v to aind model"""
        return self._parse_dv_str(self._nsb.burr4_d_v)

    @property
    def aind_burr4_injection_devi(self) -> Optional[Any]:
        """Maps burr4_injection_devi to aind model"""
        return (
            None
            if self._nsb.burr4_injection_devi is None
            else {
                self._nsb.burr4_injection_devi.SELECT: None,
                self._nsb.burr4_injection_devi.NANO_1: None,
                self._nsb.burr4_injection_devi.IONTO_1: None,
                self._nsb.burr4_injection_devi.NANO_2: None,
                self._nsb.burr4_injection_devi.IONTO_2: None,
                self._nsb.burr4_injection_devi.NANO_3: None,
                self._nsb.burr4_injection_devi.IONTO_3: None,
                self._nsb.burr4_injection_devi.NANO_4: None,
                self._nsb.burr4_injection_devi.IONTO_4: None,
                self._nsb.burr4_injection_devi.NANO_5: None,
                self._nsb.burr4_injection_devi.IONTO_5: None,
                self._nsb.burr4_injection_devi.NANO_6: None,
                self._nsb.burr4_injection_devi.IONTO_6: None,
                self._nsb.burr4_injection_devi.NANO_7: None,
                self._nsb.burr4_injection_devi.IONTO_7: None,
                self._nsb.burr4_injection_devi.NANO_8: None,
                self._nsb.burr4_injection_devi.IONTO_8: None,
                self._nsb.burr4_injection_devi.NANO_9: None,
                self._nsb.burr4_injection_devi.IONTO_9: None,
            }.get(self._nsb.burr4_injection_devi, None)
        )

    @property
    def aind_burr4_m_l(self) -> Optional[float]:
        """Maps burr4_m_l to aind model"""
        return self._parse_ml_str(self._nsb.burr4_m_l)

    @property
    def aind_burr4_perform_during(self) -> Optional[During]:
        """Maps burr4_perform_during to aind model"""
        return (
            None
            if self._nsb.burr4_perform_during is None
            else {
                self._nsb.burr4_perform_during.INITIAL_SURGERY: During.INITIAL,
                self._nsb.burr4_perform_during.FOLLOW_UP_SURGERY: During.FOLLOW_UP,
            }.get(self._nsb.burr4_perform_during, None)
        )

    @property
    def aind_burr4_status(self) -> Optional[Any]:
        """Maps burr4_status to aind model"""
        return (
            None
            if self._nsb.burr4_status is None
            else {
                self._nsb.burr4_status.COMPLETE: None,
            }.get(self._nsb.burr4_status, None)
        )

    @property
    def aind_burr4_virus_biosafte(self) -> Optional[Any]:
        """Maps burr4_virus_biosafte to aind model"""
        return (
            None
            if self._nsb.burr4_virus_biosafte is None
            else {
                self._nsb.burr4_virus_biosafte.SELECT: None,
                self._nsb.burr4_virus_biosafte.BSL_1_AAV: None,
                self._nsb.burr4_virus_biosafte.BSL_1_BEADS: None,
                self._nsb.burr4_virus_biosafte.BSL_1_AAV_BEADS: None,
                self._nsb.burr4_virus_biosafte.BSL_1_OTHER_WRITE_IN_COMM: None,
                self._nsb.burr4_virus_biosafte.BSL_2_RABIES: None,
                self._nsb.burr4_virus_biosafte.BSL_2_CAV: None,
                self._nsb.burr4_virus_biosafte.BSL_2_6OHDA: None,
                self._nsb.burr4_virus_biosafte.BSL_2_SINDBIS: None,
                self._nsb.burr4_virus_biosafte.BSL_2_HSV1: None,
                self._nsb.burr4_virus_biosafte.BSL_2_LENTI: None,
                self._nsb.burr4_virus_biosafte.BSL_2_CHOLERA_TOXIN_B: None,
                self._nsb.burr4_virus_biosafte.BSL_2_OTHER_WRITE_IN_COMM: None,
            }.get(self._nsb.burr4_virus_biosafte, None)
        )

    @property
    def aind_burr_3_angle(self) -> Optional[float]:
        """Maps burr_3_angle to aind model"""
        return self._parse_angle_str(self._nsb.burr_3_angle)

    @property
    def aind_burr_3_hemisphere(self) -> Optional[Side]:
        """Maps burr_3_hemisphere to aind model"""
        return (
            None
            if self._nsb.burr_3_hemisphere is None
            else {
                self._nsb.burr_3_hemisphere.SELECT: None,
                self._nsb.burr_3_hemisphere.LEFT: Side.LEFT,
                self._nsb.burr_3_hemisphere.RIGHT: Side.RIGHT,
            }.get(self._nsb.burr_3_hemisphere, None)
        )

    @property
    def aind_burr_4_angle(self) -> Optional[float]:
        """Maps burr_4_angle to aind model"""
        return self._parse_angle_str(self._nsb.burr_4_angle)

    @property
    def aind_burr_4_hemisphere(self) -> Optional[Side]:
        """Maps burr_4_hemisphere to aind model"""
        return (
            None
            if self._nsb.burr_4_hemisphere is None
            else {
                self._nsb.burr_4_hemisphere.SELECT: None,
                self._nsb.burr_4_hemisphere.LEFT: Side.LEFT,
                self._nsb.burr_4_hemisphere.RIGHT: Side.RIGHT,
            }.get(self._nsb.burr_4_hemisphere, None)
        )

    @property
    def aind_burr_hole_1(self) -> Optional[BurrHoleProcedure]:
        """Maps burr_hole_1 to aind model"""
        return (
            None
            if self._nsb.burr_hole_1 is None
            else {
                self._nsb.burr_hole_1.SELECT: None,
                self._nsb.burr_hole_1.INJECTION: BurrHoleProcedure.INJECTION,
                self._nsb.burr_hole_1.FIBER_IMPLANT: (
                    BurrHoleProcedure.FIBER_IMPLANT
                ),
                self._nsb.burr_hole_1.INJECTION_FIBER_IMPLANT: (
                    BurrHoleProcedure.INJECTION_FIBER_IMPLANT
                ),
            }.get(self._nsb.burr_hole_1, None)
        )

    @property
    def aind_burr_hole_1_st(self) -> Optional[Any]:
        """Maps burr_hole_1_st to aind model"""
        return (
            None
            if self._nsb.burr_hole_1_st is None
            else {
                self._nsb.burr_hole_1_st.COMPLETE: None,
            }.get(self._nsb.burr_hole_1_st, None)
        )

    @property
    def aind_burr_hole_2(self) -> Optional[BurrHoleProcedure]:
        """Maps burr_hole_2 to aind model"""
        return (
            None
            if self._nsb.burr_hole_2 is None
            else {
                self._nsb.burr_hole_2.SELECT: None,
                self._nsb.burr_hole_2.INJECTION: BurrHoleProcedure.INJECTION,
                self._nsb.burr_hole_2.FIBER_IMPLANT: (
                    BurrHoleProcedure.FIBER_IMPLANT
                ),
                self._nsb.burr_hole_2.INJECTION_FIBER_IMPLANT: (
                    BurrHoleProcedure.INJECTION_FIBER_IMPLANT
                ),
            }.get(self._nsb.burr_hole_2, None)
        )

    @property
    def aind_burr_hole_3(self) -> Optional[BurrHoleProcedure]:
        """Maps burr_hole_3 to aind model"""
        return (
            None
            if self._nsb.burr_hole_3 is None
            else {
                self._nsb.burr_hole_3.SELECT: None,
                self._nsb.burr_hole_3.INJECTION: BurrHoleProcedure.INJECTION,
                self._nsb.burr_hole_3.FIBER_IMPLANT: (
                    BurrHoleProcedure.FIBER_IMPLANT
                ),
                self._nsb.burr_hole_3.INJECTION_FIBER_IMPLANT: (
                    BurrHoleProcedure.INJECTION_FIBER_IMPLANT
                ),
            }.get(self._nsb.burr_hole_3, None)
        )

    @property
    def aind_burr_hole_4(self) -> Optional[BurrHoleProcedure]:
        """Maps burr_hole_4 to aind model"""
        return (
            None
            if self._nsb.burr_hole_4 is None
            else {
                self._nsb.burr_hole_4.SELECT: None,
                self._nsb.burr_hole_4.INJECTION: BurrHoleProcedure.INJECTION,
                self._nsb.burr_hole_4.FIBER_IMPLANT: (
                    BurrHoleProcedure.FIBER_IMPLANT
                ),
                self._nsb.burr_hole_4.INJECTION_FIBER_IMPLANT: (
                    BurrHoleProcedure.INJECTION_FIBER_IMPLANT
                ),
            }.get(self._nsb.burr_hole_4, None)
        )

    @property
    def aind_color_tag(self) -> Optional[str]:
        """Maps color_tag to aind model"""
        return self._nsb.color_tag

    @property
    def aind_com_coplanar(self) -> Optional[Any]:
        """Maps com_coplanar to aind model"""
        return (
            None
            if self._nsb.com_coplanar is None
            else {
                self._nsb.com_coplanar.SELECT: None,
                self._nsb.com_coplanar.NONE: None,
                self._nsb.com_coplanar.MILD: None,
                self._nsb.com_coplanar.MODERATE: None,
                self._nsb.com_coplanar.SEVERE: None,
                self._nsb.com_coplanar.NA: None,
            }.get(self._nsb.com_coplanar, None)
        )

    @property
    def aind_com_damage(self) -> Optional[Any]:
        """Maps com_damage to aind model"""
        return (
            None
            if self._nsb.com_damage is None
            else {
                self._nsb.com_damage.SELECT: None,
                self._nsb.com_damage.NONE: None,
                self._nsb.com_damage.MILD: None,
                self._nsb.com_damage.MODERATE: None,
                self._nsb.com_damage.SEVERE: None,
                self._nsb.com_damage.NA: None,
            }.get(self._nsb.com_damage, None)
        )

    @property
    def aind_com_durotomy(self) -> Optional[Any]:
        """Maps com_durotomy to aind model"""
        return (
            None
            if self._nsb.com_durotomy is None
            else {
                self._nsb.com_durotomy.SELECT: None,
                self._nsb.com_durotomy.COMPLETE: None,
                self._nsb.com_durotomy.TORN_COMPLETE: None,
                self._nsb.com_durotomy.PARTIAL: None,
                self._nsb.com_durotomy.NO: None,
                self._nsb.com_durotomy.UNINTENTIONAL: None,
                self._nsb.com_durotomy.NA: None,
            }.get(self._nsb.com_durotomy, None)
        )

    @property
    def aind_com_sinusbleed(self) -> Optional[Any]:
        """Maps com_sinusbleed to aind model"""
        return (
            None
            if self._nsb.com_sinusbleed is None
            else {
                self._nsb.com_sinusbleed.SELECT: None,
                self._nsb.com_sinusbleed.NONE: None,
                self._nsb.com_sinusbleed.MILD: None,
                self._nsb.com_sinusbleed.MODERATE: None,
                self._nsb.com_sinusbleed.SEVERE: None,
                self._nsb.com_sinusbleed.NA: None,
            }.get(self._nsb.com_sinusbleed, None)
        )

    @property
    def aind_com_swelling(self) -> Optional[Any]:
        """Maps com_swelling to aind model"""
        return (
            None
            if self._nsb.com_swelling is None
            else {
                self._nsb.com_swelling.SELECT: None,
                self._nsb.com_swelling.NONE: None,
                self._nsb.com_swelling.MILD: None,
                self._nsb.com_swelling.MODERATE: None,
                self._nsb.com_swelling.SEVERE: None,
                self._nsb.com_swelling.NA: None,
            }.get(self._nsb.com_swelling, None)
        )

    @property
    def aind_com_window(self) -> Optional[Any]:
        """Maps com_window to aind model"""
        return (
            None
            if self._nsb.com_window is None
            else {
                self._nsb.com_window.SELECT: None,
                self._nsb.com_window.CENTRAL: None,
                self._nsb.com_window.ANTERIOR: None,
                self._nsb.com_window.LATERAL: None,
                self._nsb.com_window.MEDIAL: None,
                self._nsb.com_window.POSTERIOR: None,
                self._nsb.com_window.OTHER_IN_COMMENTS: None,
                self._nsb.com_window.NA: None,
            }.get(self._nsb.com_window, None)
        )

    @property
    def aind_compliance_asset_id(self) -> Optional[str]:
        """Maps compliance_asset_id to aind model"""
        return self._nsb.compliance_asset_id

    @property
    def aind_contusion(self) -> Optional[Any]:
        """Maps contusion to aind model"""
        return (
            None
            if self._nsb.contusion is None
            else {
                self._nsb.contusion.SELECT: None,
                self._nsb.contusion.NONE: None,
                self._nsb.contusion.MILD: None,
                self._nsb.contusion.MODERATE: None,
                self._nsb.contusion.SEVERE: None,
                self._nsb.contusion.NA: None,
            }.get(self._nsb.contusion, None)
        )

    @property
    def aind_craniotomy_perform_d(self) -> Optional[During]:
        """Maps craniotomy_perform_d to aind model"""
        return (
            None
            if self._nsb.craniotomy_perform_d is None
            else {
                self._nsb.craniotomy_perform_d.INITIAL_SURGERY: During.INITIAL,
                self._nsb.craniotomy_perform_d.FOLLOW_UP_SURGERY: During.FOLLOW_UP,
            }.get(self._nsb.craniotomy_perform_d, None)
        )

    @property
    def aind_craniotomy_type(self) -> Optional[CraniotomyType]:
        """Maps craniotomy_type to aind model"""
        return (
            None
            if self._nsb.craniotomy_type is None
            else {
                self._nsb.craniotomy_type.SELECT: None,
                self._nsb.craniotomy_type.N_3MM: CraniotomyType.THREE_MM,
                self._nsb.craniotomy_type.N_5MM: CraniotomyType.FIVE_MM,
                self._nsb.craniotomy_type.WHC: CraniotomyType.WHC,
            }.get(self._nsb.craniotomy_type, None)
        )

    @property
    def aind_created(self) -> Optional[datetime]:
        """Maps created to aind model"""
        return self._nsb.created

    @property
    def aind_date1st_injection(self) -> Optional[date]:
        """Maps date1st_injection to aind model"""
        return self._parse_datetime_to_date(self._nsb.date1st_injection)

    @property
    def aind_date_of_birth(self) -> Optional[datetime]:
        """Maps date_of_birth to aind model"""
        return self._nsb.date_of_birth

    @property
    def aind_date_of_surgery(self) -> Optional[date]:
        """Maps date_of_surgery to aind model"""
        return self._parse_datetime_to_date(self._nsb.date_of_surgery)

    @property
    def aind_date_range_start(self) -> Optional[datetime]:
        """Maps date_range_start to aind model"""
        return self._nsb.date_range_start

    @property
    def aind_dv2nd_inj(self) -> Optional[float]:
        """Maps dv2nd_inj to aind model"""
        return self._parse_dv_str(self._nsb.dv2nd_inj)

    @property
    def aind_editor_id(self) -> Optional[int]:
        """Maps editor_id to aind model"""
        return self._nsb.editor_id

    @property
    def aind_fiber_implant1_dv(self) -> Optional[float]:
        """Maps fiber_implant1_dv to aind model"""
        return self._parse_dv_str(self._nsb.fiber_implant1_dv)

    @property
    def aind_fiber_implant1_lengt(self) -> Optional[Any]:
        """Maps fiber_implant1_lengt to aind model"""
        return (
            None
            if self._nsb.fiber_implant1_lengt is None
            else {
                self._nsb.fiber_implant1_lengt.SELECT: None,
                self._nsb.fiber_implant1_lengt.N_20_MM: None,
                self._nsb.fiber_implant1_lengt.N_25_MM: None,
                self._nsb.fiber_implant1_lengt.N_30_MM: None,
                self._nsb.fiber_implant1_lengt.N_35_MM: None,
                self._nsb.fiber_implant1_lengt.N_40_MM: None,
                self._nsb.fiber_implant1_lengt.N_45_MM: None,
                self._nsb.fiber_implant1_lengt.N_50_MM: None,
            }.get(self._nsb.fiber_implant1_lengt, None)
        )

    @property
    def aind_fiber_implant2_dv(self) -> Optional[float]:
        """Maps fiber_implant2_dv to aind model"""
        return self._parse_dv_str(self._nsb.fiber_implant2_dv)

    @property
    def aind_fiber_implant2_lengt(self) -> Optional[Any]:
        """Maps fiber_implant2_lengt to aind model"""
        return (
            None
            if self._nsb.fiber_implant2_lengt is None
            else {
                self._nsb.fiber_implant2_lengt.SELECT: None,
                self._nsb.fiber_implant2_lengt.N_20_MM: None,
                self._nsb.fiber_implant2_lengt.N_25_MM: None,
                self._nsb.fiber_implant2_lengt.N_30_MM: None,
                self._nsb.fiber_implant2_lengt.N_35_MM: None,
                self._nsb.fiber_implant2_lengt.N_40_MM: None,
                self._nsb.fiber_implant2_lengt.N_45_MM: None,
                self._nsb.fiber_implant2_lengt.N_50_MM: None,
            }.get(self._nsb.fiber_implant2_lengt, None)
        )

    @property
    def aind_fiber_implant3_d_x00(self) -> Optional[float]:
        """Maps fiber_implant3_d_x00 to aind model"""
        return self._parse_fiber_implant_d(self._nsb.fiber_implant3_d_x00)

    @property
    def aind_fiber_implant3_lengt(self) -> Optional[Any]:
        """Maps fiber_implant3_lengt to aind model"""
        return (
            None
            if self._nsb.fiber_implant3_lengt is None
            else {
                self._nsb.fiber_implant3_lengt.SELECT: None,
                self._nsb.fiber_implant3_lengt.N_20_MM: None,
                self._nsb.fiber_implant3_lengt.N_25_MM: None,
                self._nsb.fiber_implant3_lengt.N_30_MM: None,
                self._nsb.fiber_implant3_lengt.N_35_MM: None,
                self._nsb.fiber_implant3_lengt.N_40_MM: None,
                self._nsb.fiber_implant3_lengt.N_45_MM: None,
                self._nsb.fiber_implant3_lengt.N_50_MM: None,
            }.get(self._nsb.fiber_implant3_lengt, None)
        )

    @property
    def aind_fiber_implant4_d_x00(self) -> Optional[float]:
        """Maps fiber_implant4_d_x00 to aind model"""
        return self._parse_fiber_implant_d(self._nsb.fiber_implant4_d_x00)

    @property
    def aind_fiber_implant4_lengt(self) -> Optional[Any]:
        """Maps fiber_implant4_lengt to aind model"""
        return (
            None
            if self._nsb.fiber_implant4_lengt is None
            else {
                self._nsb.fiber_implant4_lengt.SELECT: None,
                self._nsb.fiber_implant4_lengt.N_20_MM: None,
                self._nsb.fiber_implant4_lengt.N_25_MM: None,
                self._nsb.fiber_implant4_lengt.N_30_MM: None,
                self._nsb.fiber_implant4_lengt.N_35_MM: None,
                self._nsb.fiber_implant4_lengt.N_40_MM: None,
                self._nsb.fiber_implant4_lengt.N_45_MM: None,
                self._nsb.fiber_implant4_lengt.N_50_MM: None,
            }.get(self._nsb.fiber_implant4_lengt, None)
        )

    @property
    def aind_first_inj_recovery(self) -> Optional[float]:
        """Maps first_inj_recovery to aind model"""
        return self._nsb.first_inj_recovery

    @property
    def aind_first_injection_iso_durat(self) -> Optional[float]:
        """Maps first_injection_iso_durat to aind model"""
        return (
            None
            if self._nsb.first_injection_iso_durat is None
            else self._nsb.first_injection_iso_durat * 60
        )

    @property
    def aind_first_injection_weight_af(self) -> Optional[float]:
        """Maps first_injection_weight_af to aind model"""
        return self._nsb.first_injection_weight_af

    @property
    def aind_first_injection_weight_be(self) -> Optional[float]:
        """Maps first_injection_weight_be to aind model"""
        return self._nsb.first_injection_weight_be

    @property
    def aind_headpost(self) -> Optional[HeadPost]:
        """Maps headpost to aind model"""
        return (
            None
            if self._nsb.headpost is None
            else {
                self._nsb.headpost.SELECT: None,
                self._nsb.headpost.VISUAL_CTX: HeadPost.VISUAL_CTX,
                self._nsb.headpost.FRONTAL_CTX: HeadPost.FRONTAL_CTX,
                self._nsb.headpost.MOTOR_CTX: HeadPost.MOTOR_CTX,
                self._nsb.headpost.WHC_2_P: HeadPost.WHC_2P,
                self._nsb.headpost.WHC_NP: HeadPost.WHC_NP,
                self._nsb.headpost.AI_STRAIGHT_BAR: HeadPost.AI_HEADBAR,
                self._nsb.headpost.OTHER_ADD_DETAILS_IN_REQU: None,
            }.get(self._nsb.headpost, None)
        )

    @property
    def aind_headpost_perform_dur(self) -> Optional[During]:
        """Maps headpost_perform_dur to aind model"""
        return (
            None
            if self._nsb.headpost_perform_dur is None
            else {
                self._nsb.headpost_perform_dur.INITIAL_SURGERY: During.INITIAL,
                self._nsb.headpost_perform_dur.FOLLOW_UP_SURGERY: During.FOLLOW_UP,
            }.get(self._nsb.headpost_perform_dur, None)
        )

    @property
    def aind_headpost_type(self) -> Optional[HeadPostType]:
        """Maps headpost_type to aind model"""
        return (
            None
            if self._nsb.headpost_type is None
            else {
                self._nsb.headpost_type.SELECT: None,
                self._nsb.headpost_type.NO_WELL: HeadPostType.NO_WELL,
                self._nsb.headpost_type.SCIENTIFICA_CAM: HeadPostType.CAM,
                self._nsb.headpost_type.MESOSCOPE: HeadPostType.MESOSCOPE,
                self._nsb.headpost_type.NEUROPIXEL: HeadPostType.NEUROPIXEL,
                self._nsb.headpost_type.WHC_2_P: HeadPostType.WHC_2P,
                self._nsb.headpost_type.WHC_NP: HeadPostType.WHC_NP,
                self._nsb.headpost_type.OTHER_SEE_REQUESTOR_COMME: None,
            }.get(self._nsb.headpost_type, None)
        )

    @property
    def aind_hemisphere2nd_inj(self) -> Optional[Side]:
        """Maps hemisphere2nd_inj to aind model"""
        return (
            None
            if self._nsb.hemisphere2nd_inj is None
            else {
                self._nsb.hemisphere2nd_inj.SELECT: None,
                self._nsb.hemisphere2nd_inj.LEFT: Side.LEFT,
                self._nsb.hemisphere2nd_inj.RIGHT: Side.RIGHT,
            }.get(self._nsb.hemisphere2nd_inj, None)
        )

    @property
    def aind_hp_iso_level(self) -> Optional[float]:
        """Maps hp_iso_level to aind model"""
        return self._nsb.hp_iso_level

    @property
    def aind_hp_recovery(self) -> Optional[float]:
        """Maps hp_recovery to aind model"""
        return self._nsb.hp_recovery

    @property
    def aind_hp_surgeon_comments(self) -> Optional[str]:
        """Maps hp_surgeon_comments to aind model"""
        return self._nsb.hp_surgeon_comments

    @property
    def aind_hp_work_station(self) -> Optional[str]:
        """Maps hp_work_station to aind model"""
        return (
            None
            if self._nsb.hp_work_station is None
            else {
                self._nsb.hp_work_station.SELECT: None,
                self._nsb.hp_work_station.SWS_1: (
                    self._nsb.hp_work_station.SWS_1.value
                ),
                self._nsb.hp_work_station.SWS_2: (
                    self._nsb.hp_work_station.SWS_2.value
                ),
                self._nsb.hp_work_station.SWS_3: (
                    self._nsb.hp_work_station.SWS_3.value
                ),
                self._nsb.hp_work_station.SWS_4: (
                    self._nsb.hp_work_station.SWS_4.value
                ),
                self._nsb.hp_work_station.SWS_5: (
                    self._nsb.hp_work_station.SWS_5.value
                ),
                self._nsb.hp_work_station.SWS_6: (
                    self._nsb.hp_work_station.SWS_6.value
                ),
                self._nsb.hp_work_station.SWS_7: (
                    self._nsb.hp_work_station.SWS_7.value
                ),
                self._nsb.hp_work_station.SWS_8: (
                    self._nsb.hp_work_station.SWS_8.value
                ),
                self._nsb.hp_work_station.SWS_9: (
                    self._nsb.hp_work_station.SWS_9.value
                ),
            }.get(self._nsb.hp_work_station, None)
        )

    @property
    def aind_iacuc_protocol(self) -> Optional[str]:
        """Maps iacuc_protocol to aind model"""
        return (
            None
            if self._nsb.iacuc_protocol is None
            else {
                self._nsb.iacuc_protocol.SELECT: None,
                self._nsb.iacuc_protocol.N_1906: (
                    self._nsb.iacuc_protocol.N_1906.value
                ),
                self._nsb.iacuc_protocol.N_2001: (
                    self._nsb.iacuc_protocol.N_2001.value
                ),
                self._nsb.iacuc_protocol.N_2003: (
                    self._nsb.iacuc_protocol.N_2003.value
                ),
                self._nsb.iacuc_protocol.N_2004: (
                    self._nsb.iacuc_protocol.N_2004.value
                ),
                self._nsb.iacuc_protocol.N_2005: (
                    self._nsb.iacuc_protocol.N_2005.value
                ),
                self._nsb.iacuc_protocol.N_2006: (
                    self._nsb.iacuc_protocol.N_2006.value
                ),
                self._nsb.iacuc_protocol.N_2011: (
                    self._nsb.iacuc_protocol.N_2011.value
                ),
                self._nsb.iacuc_protocol.N_2102: (
                    self._nsb.iacuc_protocol.N_2102.value
                ),
                self._nsb.iacuc_protocol.N_2103: (
                    self._nsb.iacuc_protocol.N_2103.value
                ),
                self._nsb.iacuc_protocol.N_2104: (
                    self._nsb.iacuc_protocol.N_2104.value
                ),
                self._nsb.iacuc_protocol.N_2105: (
                    self._nsb.iacuc_protocol.N_2105.value
                ),
                self._nsb.iacuc_protocol.N_2106: (
                    self._nsb.iacuc_protocol.N_2106.value
                ),
                self._nsb.iacuc_protocol.N_2107: (
                    self._nsb.iacuc_protocol.N_2107.value
                ),
                self._nsb.iacuc_protocol.N_2108: (
                    self._nsb.iacuc_protocol.N_2108.value
                ),
                self._nsb.iacuc_protocol.N_2109: (
                    self._nsb.iacuc_protocol.N_2109.value
                ),
                self._nsb.iacuc_protocol.N_2110: (
                    self._nsb.iacuc_protocol.N_2110.value
                ),
                self._nsb.iacuc_protocol.N_2113: (
                    self._nsb.iacuc_protocol.N_2113.value
                ),
                self._nsb.iacuc_protocol.N_2115: (
                    self._nsb.iacuc_protocol.N_2115.value
                ),
                self._nsb.iacuc_protocol.N_2117: (
                    self._nsb.iacuc_protocol.N_2117.value
                ),
                self._nsb.iacuc_protocol.N_2201: (
                    self._nsb.iacuc_protocol.N_2201.value
                ),
                self._nsb.iacuc_protocol.N_2202: (
                    self._nsb.iacuc_protocol.N_2202.value
                ),
                self._nsb.iacuc_protocol.N_2205: (
                    self._nsb.iacuc_protocol.N_2205.value
                ),
                self._nsb.iacuc_protocol.N_2212: (
                    self._nsb.iacuc_protocol.N_2212.value
                ),
                self._nsb.iacuc_protocol.N_2301: (
                    self._nsb.iacuc_protocol.N_2301.value
                ),
            }.get(self._nsb.iacuc_protocol, None)
        )

    @property
    def aind_id(self) -> Optional[int]:
        """Maps id to aind model"""
        return self._nsb.id

    @property
    def aind_implant_id_coverslip_type(self) -> Optional[Any]:
        """Maps implant_id_coverslip_type to aind model"""
        return (
            None
            if self._nsb.implant_id_coverslip_type is None
            else {
                self._nsb.implant_id_coverslip_type.SELECT: None,
                self._nsb.implant_id_coverslip_type.N_2001: None,
                self._nsb.implant_id_coverslip_type.N_2002: None,
                self._nsb.implant_id_coverslip_type.N_3001: None,
                self._nsb.implant_id_coverslip_type.N_3002: None,
                self._nsb.implant_id_coverslip_type.N_3MM: None,
                self._nsb.implant_id_coverslip_type.N_3MM_STACKED_COVERSLIP: None,
                self._nsb.implant_id_coverslip_type.N_5MM_STACKED_COVERSLIP: None,
                self._nsb.implant_id_coverslip_type.N_5MM_STACKED_COVERSLIP_W: (
                    None
                ),
            }.get(self._nsb.implant_id_coverslip_type, None)
        )

    @property
    def aind_inj1_alternating_time(self) -> Optional[float]:
        """Maps inj1_alternating_time to aind model"""
        return self._parse_alt_time_str(self._nsb.inj1_alternating_time)

    @property
    def aind_inj1_angle_v2(self) -> Optional[float]:
        """Maps inj1_angle_v2 to aind model"""
        return self._parse_angle_str(self._nsb.inj1_angle_v2)

    @property
    def aind_inj1_current(self) -> Optional[float]:
        """Maps inj1_current to aind model"""
        return self._parse_current_str(self._nsb.inj1_current)

    @property
    def aind_inj1_ionto_time(self) -> Optional[float]:
        """Maps inj1_ionto_time to aind model"""
        return self._parse_length_of_time_str(self._nsb.inj1_ionto_time)

    @property
    def aind_inj1_storage_location(self) -> Optional[str]:
        """Maps inj1_storage_location to aind model"""
        return self._nsb.inj1_storage_location

    @property
    def aind_inj1_type(self) -> Optional[InjectionType]:
        """Maps inj1_type to aind model"""
        return (
            None
            if self._nsb.inj1_type is None
            else {
                self._nsb.inj1_type.SELECT: None,
                self._nsb.inj1_type.IONTOPHORESIS: InjectionType.IONTOPHORESIS,
                self._nsb.inj1_type.NANOJECT_PRESSURE: InjectionType.NANOJECT,
            }.get(self._nsb.inj1_type, None)
        )

    @property
    def aind_inj1_virus_strain_rt(self) -> Optional[str]:
        """Maps inj1_virus_strain_rt to aind model"""
        return self._parse_virus_strain_str(self._nsb.inj1_virus_strain_rt)

    @property
    def aind_inj1volperdepth(self) -> Optional[float]:
        """Maps inj1volperdepth to aind model"""
        return self._parse_inj_vol_str(self._nsb.inj1volperdepth)

    @property
    def aind_inj2_alternating_time(self) -> Optional[float]:
        """Maps inj2_alternating_time to aind model"""
        return self._parse_alt_time_str(self._nsb.inj2_alternating_time)

    @property
    def aind_inj2_angle_v2(self) -> Optional[float]:
        """Maps inj2_angle_v2 to aind model"""
        return self._parse_angle_str(self._nsb.inj2_angle_v2)

    @property
    def aind_inj2_current(self) -> Optional[float]:
        """Maps inj2_current to aind model"""
        return self._parse_current_str(self._nsb.inj2_current)

    @property
    def aind_inj2_ionto_time(self) -> Optional[float]:
        """Maps inj2_ionto_time to aind model"""
        return self._parse_length_of_time_str(self._nsb.inj2_ionto_time)

    @property
    def aind_inj2_storage_location(self) -> Optional[str]:
        """Maps inj2_storage_location to aind model"""
        return self._nsb.inj2_storage_location

    @property
    def aind_inj2_type(self) -> Optional[InjectionType]:
        """Maps inj2_type to aind model"""
        return (
            None
            if self._nsb.inj2_type is None
            else {
                self._nsb.inj2_type.SELECT: None,
                self._nsb.inj2_type.IONTOPHORESIS: InjectionType.IONTOPHORESIS,
                self._nsb.inj2_type.NANOJECT_PRESSURE: InjectionType.NANOJECT,
            }.get(self._nsb.inj2_type, None)
        )

    @property
    def aind_inj2_virus_strain_rt(self) -> Optional[str]:
        """Maps inj2_virus_strain_rt to aind model"""
        return self._parse_virus_strain_str(self._nsb.inj2_virus_strain_rt)

    @property
    def aind_inj2volperdepth(self) -> Optional[float]:
        """Maps inj2volperdepth to aind model"""
        return self._parse_inj_vol_str(self._nsb.inj2volperdepth)

    @property
    def aind_inj3_alternating_time(self) -> Optional[float]:
        """Maps inj3_alternating_time to aind model"""
        return self._parse_alt_time_str(self._nsb.inj3_alternating_time)

    @property
    def aind_inj3_current(self) -> Optional[float]:
        """Maps inj3_current to aind model"""
        return self._parse_current_str(self._nsb.inj3_current)

    @property
    def aind_inj3_ionto_time(self) -> Optional[float]:
        """Maps inj3_ionto_time to aind model"""
        return self._parse_length_of_time_str(self._nsb.inj3_ionto_time)

    @property
    def aind_inj3_storage_location(self) -> Optional[str]:
        """Maps inj3_storage_location to aind model"""
        return self._nsb.inj3_storage_location

    @property
    def aind_inj3_type(self) -> Optional[Any]:
        """Maps inj3_type to aind model"""
        return (
            None
            if self._nsb.inj3_type is None
            else {
                self._nsb.inj3_type.SELECT: None,
                self._nsb.inj3_type.IONTOPHORESIS: InjectionType.IONTOPHORESIS,
                self._nsb.inj3_type.NANOJECT_PRESSURE: InjectionType.NANOJECT,
            }.get(self._nsb.inj3_type, None)
        )

    @property
    def aind_inj3ret_setting(self) -> Optional[Any]:
        """Maps inj3ret_setting to aind model"""
        return (
            None
            if self._nsb.inj3ret_setting is None
            else {
                self._nsb.inj3ret_setting.OFF: None,
                self._nsb.inj3ret_setting.ON: None,
            }.get(self._nsb.inj3ret_setting, None)
        )

    @property
    def aind_inj3volperdepth(self) -> Optional[float]:
        """Maps inj3volperdepth to aind model"""
        return self._parse_inj_vol_str(self._nsb.inj3volperdepth)

    @property
    def aind_inj4_alternating_time(self) -> Optional[float]:
        """Maps inj4_alternating_time to aind model"""
        return self._parse_alt_time_str(self._nsb.inj4_alternating_time)

    @property
    def aind_inj4_current(self) -> Optional[float]:
        """Maps inj4_current to aind model"""
        return self._parse_current_str(self._nsb.inj4_current)

    @property
    def aind_inj4_ionto_time(self) -> Optional[float]:
        """Maps inj4_ionto_time to aind model"""
        return self._parse_length_of_time_str(self._nsb.inj4_ionto_time)

    @property
    def aind_inj4_storage_location(self) -> Optional[str]:
        """Maps inj4_storage_location to aind model"""
        return self._nsb.inj4_storage_location

    @property
    def aind_inj4_type(self) -> Optional[InjectionType]:
        """Maps inj4_type to aind model"""
        return (
            None
            if self._nsb.inj4_type is None
            else {
                self._nsb.inj4_type.SELECT: None,
                self._nsb.inj4_type.IONTOPHORESIS: InjectionType.IONTOPHORESIS,
                self._nsb.inj4_type.NANOJECT_PRESSURE: InjectionType.NANOJECT,
            }.get(self._nsb.inj4_type, None)
        )

    @property
    def aind_inj4_virus_strain_rt(self) -> Optional[str]:
        """Maps inj4_virus_strain_rt to aind model"""
        return self._parse_virus_strain_str(self._nsb.inj4_virus_strain_rt)

    @property
    def aind_inj4ret_setting(self) -> Optional[Any]:
        """Maps inj4ret_setting to aind model"""
        return (
            None
            if self._nsb.inj4ret_setting is None
            else {
                self._nsb.inj4ret_setting.OFF: None,
                self._nsb.inj4ret_setting.ON: None,
            }.get(self._nsb.inj4ret_setting, None)
        )

    @property
    def aind_inj4volperdepth(self) -> Optional[float]:
        """Maps inj4volperdepth to aind model"""
        return self._parse_inj_vol_str(self._nsb.inj4volperdepth)

    @property
    def aind_inj_virus_strain_rt(self) -> Optional[str]:
        """Maps inj_virus_strain_rt to aind model"""
        return self._parse_virus_strain_str(self._nsb.inj_virus_strain_rt)

    @property
    def aind_ionto_number_inj1(self) -> Optional[str]:
        """Maps ionto_number_inj1 to aind model"""
        return (
            None
            if self._nsb.ionto_number_inj1 is None
            else {
                self._nsb.ionto_number_inj1.SELECT: None,
                self._nsb.ionto_number_inj1.IONTO_1: (
                    self._nsb.ionto_number_inj1.IONTO_1.value
                ),
                self._nsb.ionto_number_inj1.IONTO_2: (
                    self._nsb.ionto_number_inj1.IONTO_2.value
                ),
                self._nsb.ionto_number_inj1.IONTO_3: (
                    self._nsb.ionto_number_inj1.IONTO_3.value
                ),
                self._nsb.ionto_number_inj1.IONTO_4: (
                    self._nsb.ionto_number_inj1.IONTO_4.value
                ),
                self._nsb.ionto_number_inj1.IONTO_5: (
                    self._nsb.ionto_number_inj1.IONTO_5.value
                ),
                self._nsb.ionto_number_inj1.IONTO_6: (
                    self._nsb.ionto_number_inj1.IONTO_6.value
                ),
                self._nsb.ionto_number_inj1.IONTO_7: (
                    self._nsb.ionto_number_inj1.IONTO_7.value
                ),
                self._nsb.ionto_number_inj1.IONTO_8: (
                    self._nsb.ionto_number_inj1.IONTO_8.value
                ),
                self._nsb.ionto_number_inj1.IONTO_9: (
                    self._nsb.ionto_number_inj1.IONTO_9.value
                ),
                self._nsb.ionto_number_inj1.IONTO_10: (
                    self._nsb.ionto_number_inj1.IONTO_10.value
                ),
                self._nsb.ionto_number_inj1.NA: None,
            }.get(self._nsb.ionto_number_inj1, None)
        )

    @property
    def aind_ionto_number_inj2(self) -> Optional[Any]:
        """Maps ionto_number_inj2 to aind model"""
        return (
            None
            if self._nsb.ionto_number_inj2 is None
            else {
                self._nsb.ionto_number_inj2.SELECT: None,
                self._nsb.ionto_number_inj2.IONTO_1: (
                    self._nsb.ionto_number_inj2.IONTO_1.value
                ),
                self._nsb.ionto_number_inj2.IONTO_2: (
                    self._nsb.ionto_number_inj2.IONTO_2.value
                ),
                self._nsb.ionto_number_inj2.IONTO_3: (
                    self._nsb.ionto_number_inj2.IONTO_3.value
                ),
                self._nsb.ionto_number_inj2.IONTO_4: (
                    self._nsb.ionto_number_inj2.IONTO_4.value
                ),
                self._nsb.ionto_number_inj2.IONTO_5: (
                    self._nsb.ionto_number_inj2.IONTO_5.value
                ),
                self._nsb.ionto_number_inj2.IONTO_6: (
                    self._nsb.ionto_number_inj2.IONTO_6.value
                ),
                self._nsb.ionto_number_inj2.IONTO_7: (
                    self._nsb.ionto_number_inj2.IONTO_7.value
                ),
                self._nsb.ionto_number_inj2.IONTO_8: (
                    self._nsb.ionto_number_inj2.IONTO_8.value
                ),
                self._nsb.ionto_number_inj2.IONTO_9: (
                    self._nsb.ionto_number_inj2.IONTO_9.value
                ),
                self._nsb.ionto_number_inj2.IONTO_10: (
                    self._nsb.ionto_number_inj2.IONTO_10.value
                ),
                self._nsb.ionto_number_inj2.NA: None,
            }.get(self._nsb.ionto_number_inj2, None)
        )

    @property
    def aind_iso_on(self) -> Optional[float]:
        """Maps iso_on to aind model"""
        return None if self._nsb.iso_on is None else self._nsb.iso_on * 60

    @property
    def aind_lab_tracks_group(self) -> Optional[str]:
        """Maps lab_tracks_group to aind model"""
        return self._nsb.lab_tracks_group

    @property
    def aind_lab_tracks_id1(self) -> Optional[str]:
        """Maps lab_tracks_id1 to aind model"""
        return self._nsb.lab_tracks_id1

    @property
    def aind_lab_tracks_requestor(self) -> Optional[str]:
        """Maps lab_tracks_requestor to aind model"""
        return self._nsb.lab_tracks_requestor

    @property
    def aind_li_ms_required(self) -> Optional[Any]:
        """Maps li_ms_required to aind model"""
        return (
            None
            if self._nsb.li_ms_required is None
            else {
                self._nsb.li_ms_required.SELECT: None,
                self._nsb.li_ms_required.YES: None,
                self._nsb.li_ms_required.NO: None,
            }.get(self._nsb.li_ms_required, None)
        )

    @property
    def aind_light_cycle(self) -> Optional[Any]:
        """Maps light_cycle to aind model"""
        return (
            None
            if self._nsb.light_cycle is None
            else {
                self._nsb.light_cycle.STANDARD_LIGHT_CYCLE_6AM: None,
                self._nsb.light_cycle.REVERSE_LIGHT_CYCLE_9PM_T: None,
            }.get(self._nsb.light_cycle, None)
        )

    @property
    def aind_lims_project(self) -> Optional[Any]:
        """Maps lims_project to aind model"""
        return (
            None
            if self._nsb.lims_project is None
            else {
                self._nsb.lims_project.N_0200: None,
                self._nsb.lims_project.N_0309: None,
                self._nsb.lims_project.N_0310: None,
                self._nsb.lims_project.N_0311: None,
                self._nsb.lims_project.N_0312: None,
                self._nsb.lims_project.N_0314: None,
                self._nsb.lims_project.N_0316: None,
                self._nsb.lims_project.N_0319: None,
                self._nsb.lims_project.N_0320: None,
                self._nsb.lims_project.N_0321: None,
                self._nsb.lims_project.N_03212: None,
                self._nsb.lims_project.N_03213: None,
                self._nsb.lims_project.N_03214: None,
                self._nsb.lims_project.N_0322: None,
                self._nsb.lims_project.N_0324: None,
                self._nsb.lims_project.N_0325: None,
                self._nsb.lims_project.N_0326: None,
                self._nsb.lims_project.N_0327: None,
                self._nsb.lims_project.N_03272: None,
                self._nsb.lims_project.N_0328: None,
                self._nsb.lims_project.N_0329: None,
                self._nsb.lims_project.N_0331: None,
                self._nsb.lims_project.N_0334: None,
                self._nsb.lims_project.N_03342: None,
                self._nsb.lims_project.N_0335: None,
                self._nsb.lims_project.N_0336: None,
                self._nsb.lims_project.N_0338: None,
                self._nsb.lims_project.N_0339: None,
                self._nsb.lims_project.N_03392: None,
                self._nsb.lims_project.N_0340: None,
                self._nsb.lims_project.N_0342: None,
                self._nsb.lims_project.N_03422: None,
                self._nsb.lims_project.N_0343: None,
                self._nsb.lims_project.N_0344: None,
                self._nsb.lims_project.N_0345: None,
                self._nsb.lims_project.N_0346: None,
                self._nsb.lims_project.N_0350: None,
                self._nsb.lims_project.N_0350X: None,
                self._nsb.lims_project.N_0351: None,
                self._nsb.lims_project.N_0351X: None,
                self._nsb.lims_project.N_0354: None,
                self._nsb.lims_project.N_0355: None,
                self._nsb.lims_project.N_0357: None,
                self._nsb.lims_project.N_0358: None,
                self._nsb.lims_project.N_0359: None,
                self._nsb.lims_project.N_0360: None,
                self._nsb.lims_project.N_03602: None,
                self._nsb.lims_project.N_0362: None,
                self._nsb.lims_project.N_0363: None,
                self._nsb.lims_project.N_0364: None,
                self._nsb.lims_project.N_0365: None,
                self._nsb.lims_project.N_0365X: None,
                self._nsb.lims_project.N_0366: None,
                self._nsb.lims_project.N_0366X: None,
                self._nsb.lims_project.N_0367: None,
                self._nsb.lims_project.N_0369: None,
                self._nsb.lims_project.N_0371: None,
                self._nsb.lims_project.N_0372: None,
                self._nsb.lims_project.N_0372X: None,
                self._nsb.lims_project.N_0374: None,
                self._nsb.lims_project.N_0376: None,
                self._nsb.lims_project.N_0376A: None,
                self._nsb.lims_project.N_0376X: None,
                self._nsb.lims_project.N_0378: None,
                self._nsb.lims_project.N_0378X: None,
                self._nsb.lims_project.N_0380: None,
                self._nsb.lims_project.N_0384: None,
                self._nsb.lims_project.N_0386: None,
                self._nsb.lims_project.N_0388: None,
                self._nsb.lims_project.AINDMSMA: None,
                self._nsb.lims_project.AINDDISCOVERY: None,
                self._nsb.lims_project.AINDEPHYS: None,
                self._nsb.lims_project.AINDOPHYS: None,
                self._nsb.lims_project.APR_OX: None,
                self._nsb.lims_project.A_XL_OX: None,
                self._nsb.lims_project.BRAIN_STIM: None,
                self._nsb.lims_project.BRAINTV_VIRAL_STRATEGIES: None,
                self._nsb.lims_project.C200: None,
                self._nsb.lims_project.C600: None,
                self._nsb.lims_project.C600_LATERAL: None,
                self._nsb.lims_project.C600X: None,
                self._nsb.lims_project.CELLTYPES_TRANSGENIC_CHAR: None,
                self._nsb.lims_project.CITRICACIDPILOT: None,
                self._nsb.lims_project.CON9999: None,
                self._nsb.lims_project.CONC505: None,
                self._nsb.lims_project.CONCS04: None,
                self._nsb.lims_project.DEEPSCOPE_SLM_DEVELOPMENT: None,
                self._nsb.lims_project.DYNAMIC_ROUTING_BEHAVIOR: None,
                self._nsb.lims_project.DYNAMIC_ROUTING_SURGICAL: None,
                self._nsb.lims_project.DYNAMIC_ROUTING_TASK1_PRO: None,
                self._nsb.lims_project.DYNAMIC_ROUTING_TASK2_PRO: None,
                self._nsb.lims_project.DYNAMIC_ROUTING_ULTRA_OPT: None,
                self._nsb.lims_project.H120: None,
                self._nsb.lims_project.H200: None,
                self._nsb.lims_project.H301: None,
                self._nsb.lims_project.H301T: None,
                self._nsb.lims_project.H301_X: None,
                self._nsb.lims_project.H501_X: None,
                self._nsb.lims_project.H504: None,
                self._nsb.lims_project.IS_IX: None,
                self._nsb.lims_project.LARGE_SCALE_VOLTAGE: None,
                self._nsb.lims_project.LEARNINGM_FISH_DEVELOPMEN: None,
                self._nsb.lims_project.LEARNINGM_FISH_TASK1_A: None,
                self._nsb.lims_project.M301T: None,
                self._nsb.lims_project.MESOSCOPE_DEVELOPMENT: None,
                self._nsb.lims_project.M_FISH_PLATFORM_DEVELOPME: None,
                self._nsb.lims_project.MINDSCOPE_TRANSGENIC_CHAR: None,
                self._nsb.lims_project.M_IVSCCMET: None,
                self._nsb.lims_project.M_IVSCCME_TX: None,
                self._nsb.lims_project.M_M_PATCHX: None,
                self._nsb.lims_project.M_MPATC_HX: None,
                self._nsb.lims_project.MOUSE_BRAIN_CELL_ATLAS_CH: None,
                self._nsb.lims_project.MOUSE_BRAIN_CELL_ATLA_001: None,
                self._nsb.lims_project.MOUSE_BRAIN_CELL_ATLAS_TR: None,
                self._nsb.lims_project.MOUSE_FULL_MORPHOLOGY_FMO: None,
                self._nsb.lims_project.MOUSE_GENETIC_TOOLS_PROJE: None,
                self._nsb.lims_project.M_VISPTAXLO: None,
                self._nsb.lims_project.MULTISCOPE_SIGNAL_NOISE: None,
                self._nsb.lims_project.N200: None,
                self._nsb.lims_project.N310: None,
                self._nsb.lims_project.NEUROPIXEL_VISUAL_BEHAVIO: None,
                self._nsb.lims_project.NEUROPIXEL_VISUAL_BEH_001: None,
                self._nsb.lims_project.NEUROPIXEL_VISUAL_CODING: None,
                self._nsb.lims_project.OLVSX: None,
                self._nsb.lims_project.OM_FIS_HCOREGISTRATIONPIL: None,
                self._nsb.lims_project.OM_FISH_CUX2_MESO: None,
                self._nsb.lims_project.OM_FISH_GAD2_MESO: None,
                self._nsb.lims_project.OM_FISH_GAD2_PILOT: None,
                self._nsb.lims_project.OM_FISH_RBP4_MESO: None,
                self._nsb.lims_project.OM_FISH_RORB_PILOT: None,
                self._nsb.lims_project.OM_FISHRO_BINJECTIONVIRUS: None,
                self._nsb.lims_project.OM_FISH_SST_MESO: None,
                self._nsb.lims_project.OPEN_SCOPE_DENDRITE_COUPL: None,
                self._nsb.lims_project.OPENSCOPE_DEVELOPMENT: None,
                self._nsb.lims_project.OPEN_SCOPE_ILLUSION: None,
                self._nsb.lims_project.OPEN_SCOPE_GLOBAL_LOCAL_O: None,
                self._nsb.lims_project.OPENSCOPE_GAMMA_PILOT: None,
                self._nsb.lims_project.OPENSCOPE_GAMMA_PRODUCTLO: None,
                self._nsb.lims_project.OPENSCOPELNJECTION_PILOT: None,
                self._nsb.lims_project.OPENSCOPE_MOTION_PLLOT: None,
                self._nsb.lims_project.OPENSCOPE_MOTION_PRODUCTI: None,
                self._nsb.lims_project.OPENSCOPE_MULTIPLEX_PILOT: None,
                self._nsb.lims_project.OPENSCOPE_MULTIPLEX_PRODU: None,
                self._nsb.lims_project.OPEN_SCOPE_SEQUENCE_LEARN: None,
                self._nsb.lims_project.OPEN_SCOPE_TEMPORAL_BARCO: None,
                self._nsb.lims_project.OPEN_SCOPE_VISION2_HIPPOC: None,
                self._nsb.lims_project.OPH5_X: None,
                self._nsb.lims_project.S200_C: None,
                self._nsb.lims_project.SMART_SPIM_GENETIC_TOOLS: None,
                self._nsb.lims_project.SURGERY_X: None,
                self._nsb.lims_project.T301: None,
                self._nsb.lims_project.T301T: None,
                self._nsb.lims_project.T301_X: None,
                self._nsb.lims_project.T503: None,
                self._nsb.lims_project.T503_X: None,
                self._nsb.lims_project.T504: None,
                self._nsb.lims_project.T504_X: None,
                self._nsb.lims_project.T600: None,
                self._nsb.lims_project.T601: None,
                self._nsb.lims_project.T601_X: None,
                self._nsb.lims_project.TCYTX: None,
                self._nsb.lims_project.TASK_TRAINED_NETWORKS_MUL: None,
                self._nsb.lims_project.TASK_TRAINED_NETWORKS_NEU: None,
                self._nsb.lims_project.TEMPLETON_PSYCHEDELICS: None,
                self._nsb.lims_project.TEMPLETON_TTOC: None,
                self._nsb.lims_project.TINY_BLUE_DOT_BEHAVIOR: None,
                self._nsb.lims_project.U01_BFCT: None,
                self._nsb.lims_project.VARIABILITY_AIM1: None,
                self._nsb.lims_project.VARIABILITY_AIM1_PILOT: None,
                self._nsb.lims_project.VARIABILITY_SPONTANEOUS: None,
                self._nsb.lims_project.VI_DEEP_DIVE_EM_VOLUME: None,
                self._nsb.lims_project.VI_DEEPDLVE_DEEPSCOPE_PIE: None,
                self._nsb.lims_project.VIP_AXONAL_V1_PHASE1: None,
                self._nsb.lims_project.VIP_SOMATIC_V1_MESO: None,
                self._nsb.lims_project.VIP_SOMATIC_V1_PHASE1: None,
                self._nsb.lims_project.VIP_SOMATIC_V1_PHASE2: None,
                self._nsb.lims_project.VISUAL_BEHAVIOR: None,
                self._nsb.lims_project.VISUAL_BEHAVIOR_DEVELOPME: None,
                self._nsb.lims_project.VISUAL_BEHAVIOR_MULTISCOP: None,
                self._nsb.lims_project.VISUAL_BEHAVIOR_MULTI_001: None,
                self._nsb.lims_project.VISUAL_BEHAV_IOR_MULTISCO: None,
                self._nsb.lims_project.VISUAL_BEHAVIOR_TASK1_B: None,
            }.get(self._nsb.lims_project, None)
        )

    @property
    def aind_lims_taskflow(self) -> Optional[Any]:
        """Maps lims_taskflow to aind model"""
        return (
            None
            if self._nsb.lims_taskflow is None
            else {
                self._nsb.lims_taskflow.AIND_EPHYS_SURGERY_ONLY: None,
                self._nsb.lims_taskflow.AIND_EPHYS_PASSIVE_BEHAVI: None,
                self._nsb.lims_taskflow.AIND_U19_AAV_RETROGRADE: None,
                self._nsb.lims_taskflow.AIND_U19_THALAMUS: None,
                self._nsb.lims_taskflow.BRAIN_LARGE_SCALE_RECORDI: None,
                self._nsb.lims_taskflow.BRAIN_MOUSE_BRAIN_CELL_AT: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_DEEPSCO: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_EPHYS_D: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_MAPSCOP: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_MESOSCO: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_MES_001: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_NEUROPI: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_TRANSGE: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_V1_DD: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_VISUAL: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_VIS_001: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_VIS_002: None,
                self._nsb.lims_taskflow.BRAIN_OBSERVATORY_VIS_003: None,
                self._nsb.lims_taskflow.BTV_BRAIN_VIRAL_STRATEGIE: None,
                self._nsb.lims_taskflow.CITRIC_ACID_PILOT: None,
                self._nsb.lims_taskflow.EPHYS_DEV_VISUAL_BEHAVIOR2: None,
                self._nsb.lims_taskflow.EPHYS_DEV_VISUAL_BEHAVIOR: None,
                self._nsb.lims_taskflow.EPHYS_TASK_DEV_DYNAMIC_RO: None,
                self._nsb.lims_taskflow.EPHYS_TASK_DEV_DYANMIC_RO: None,
                self._nsb.lims_taskflow.EPHYS_TASK_DEV_DYNAMI_001: None,
                self._nsb.lims_taskflow.IVSCC_HVA_RETRO_PATCH_SEQ: None,
                self._nsb.lims_taskflow.IVSC_CM_INJECTION: None,
                self._nsb.lims_taskflow.IVSP_CM_INJECTION: None,
                self._nsb.lims_taskflow.MGT_LAB: None,
                self._nsb.lims_taskflow.MGT_TISSUE_CYTE: None,
                self._nsb.lims_taskflow.MSP_DYNAMIC_ROUTING_BEHAV: None,
                self._nsb.lims_taskflow.MSP_DYNAMIC_ROUTING_SURGI: None,
                self._nsb.lims_taskflow.MSP_DYNAMIC_ROUTING_ULTRA: None,
                self._nsb.lims_taskflow.MSP_DYNAMIC_ROUTING_TASK: None,
                self._nsb.lims_taskflow.MSP_DYNAMIC_ROUTING_T_001: None,
                self._nsb.lims_taskflow.MSP_LEARNING_M_FISH_DEVEL: None,
                self._nsb.lims_taskflow.MSP_LEARNING_M_FISH_D_001: None,
                self._nsb.lims_taskflow.MSP_LEARNING_M_FISH_FRONT: None,
                self._nsb.lims_taskflow.MSP_LEARNING_M_FISH_VIRUS: None,
                self._nsb.lims_taskflow.MSP_OM_FISH_COREGISTRATIO: None,
                self._nsb.lims_taskflow.MSP_OM_FISH_CUX2_PILOT: None,
                self._nsb.lims_taskflow.MSP_OM_FISH_GAD2_PILOT: None,
                self._nsb.lims_taskflow.MSP_OM_FISH_RBP4_MESO: None,
                self._nsb.lims_taskflow.MSP_OM_FISH_RORB_PILOT: None,
                self._nsb.lims_taskflow.MSP_OM_FISH_ROB_INJECTION: None,
                self._nsb.lims_taskflow.MSP_OM_FISH_SST_MESO_GAMM: None,
                self._nsb.lims_taskflow.MSP_OPEN_SCOPE_DENDRITE_C: None,
                self._nsb.lims_taskflow.MSP_OPEN_SCOPE_ILLUSION: None,
                self._nsb.lims_taskflow.MSP_OPEN_SCOPE_GLOBAL_LOC: None,
                self._nsb.lims_taskflow.MSP_OPEN_SCOPE_GLOBAL_001: None,
                self._nsb.lims_taskflow.MSP_TASK_TRAINED_NETWORKS: None,
                self._nsb.lims_taskflow.MSP_TASK_TRAINED_NETW_001: None,
                self._nsb.lims_taskflow.MSP_U01_BRIDGING_FUNCTION: None,
                self._nsb.lims_taskflow.MSP_VARIABILITY_AIM_1: None,
                self._nsb.lims_taskflow.MSP_VARIABILITY_AIM_1_PIL: None,
                self._nsb.lims_taskflow.MSP_VARIABILITY_SPONTANEO: None,
                self._nsb.lims_taskflow.MSP_VIP_AXONAL_V1: None,
                self._nsb.lims_taskflow.MSP_VIP_SOMATIC_V1: None,
                self._nsb.lims_taskflow.OPENSCOPE_MOTION_PRODUCTI: None,
                self._nsb.lims_taskflow.OPENSCOPE_VIRUS_VALIDATIO: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_GAMMA_PILOT: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_GAMMA_PRODUCTI: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_LNJECTION_VOLU: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_MOTION_PILOT: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_MULTIPLEX_PILO: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_MULTIPLEX__001: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_MULTIPLEX_PROD: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_MULTLPLEX_PROD: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_SEQUENCE_LEARN: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_TEMPORAL_BARCO: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_TEMPORAL_B_001: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_VISION_2_HIPPO: None,
                self._nsb.lims_taskflow.OPEN_SCOPE_WHC_2_P_DEV: None,
                self._nsb.lims_taskflow.TINY_BLUE_DOT_BEHAVIOR: None,
                self._nsb.lims_taskflow.TRANSGENIC_CHARACTERIZATI: None,
                self._nsb.lims_taskflow.VIS_B_DEV_CONTROL_GROUP: None,
                self._nsb.lims_taskflow.VIS_B_LATERAL_PREP_DEVELO: None,
                self._nsb.lims_taskflow.VIS_B_TASK_2_DEVELOPMENT: None,
                self._nsb.lims_taskflow.VGT_ENHANCERS_TRANSSYNAPT: None,
            }.get(self._nsb.lims_taskflow, None)
        )

    @property
    def aind_long_requestor_comments(self) -> Optional[str]:
        """Maps long_requestor_comments to aind model"""
        return self._nsb.long_requestor_comments

    @property
    def aind_ml2nd_inj(self) -> Optional[float]:
        """Maps ml2nd_inj to aind model"""
        return self._parse_ml_str(self._nsb.ml2nd_inj)

    @property
    def aind_modified(self) -> Optional[datetime]:
        """Maps modified to aind model"""
        return self._nsb.modified

    @property
    def aind_nanoject_number_inj10(self) -> Optional[str]:
        """Maps nanoject_number_inj10 to aind model"""
        return (
            None
            if self._nsb.nanoject_number_inj10 is None
            else {
                self._nsb.nanoject_number_inj10.SELECT: None,
                self._nsb.nanoject_number_inj10.NJ1: (
                    self._nsb.nanoject_number_inj10.NJ1.value
                ),
                self._nsb.nanoject_number_inj10.NJ2: (
                    self._nsb.nanoject_number_inj10.NJ2.value
                ),
                self._nsb.nanoject_number_inj10.NJ3: (
                    self._nsb.nanoject_number_inj10.NJ3.value
                ),
                self._nsb.nanoject_number_inj10.NJ4: (
                    self._nsb.nanoject_number_inj10.NJ4.value
                ),
                self._nsb.nanoject_number_inj10.NJ5: (
                    self._nsb.nanoject_number_inj10.NJ5.value
                ),
                self._nsb.nanoject_number_inj10.NJ6: (
                    self._nsb.nanoject_number_inj10.NJ6.value
                ),
                self._nsb.nanoject_number_inj10.NJ7: (
                    self._nsb.nanoject_number_inj10.NJ7.value
                ),
                self._nsb.nanoject_number_inj10.NJ8: (
                    self._nsb.nanoject_number_inj10.NJ8.value
                ),
                self._nsb.nanoject_number_inj10.NA: None,
            }.get(self._nsb.nanoject_number_inj10, None)
        )

    @property
    def aind_nanoject_number_inj2(self) -> Optional[Any]:
        """Maps nanoject_number_inj2 to aind model"""
        return (
            None
            if self._nsb.nanoject_number_inj2 is None
            else {
                self._nsb.nanoject_number_inj2.SELECT: None,
                self._nsb.nanoject_number_inj2.NJ1: (
                    self._nsb.nanoject_number_inj2.NJ1.value
                ),
                self._nsb.nanoject_number_inj2.NJ2: (
                    self._nsb.nanoject_number_inj2.NJ2.value
                ),
                self._nsb.nanoject_number_inj2.NJ3: (
                    self._nsb.nanoject_number_inj2.NJ3.value
                ),
                self._nsb.nanoject_number_inj2.NJ4: (
                    self._nsb.nanoject_number_inj2.NJ4.value
                ),
                self._nsb.nanoject_number_inj2.NJ5: (
                    self._nsb.nanoject_number_inj2.NJ5.value
                ),
                self._nsb.nanoject_number_inj2.NJ6: (
                    self._nsb.nanoject_number_inj2.NJ6.value
                ),
                self._nsb.nanoject_number_inj2.NJ7: (
                    self._nsb.nanoject_number_inj2.NJ7.value
                ),
                self._nsb.nanoject_number_inj2.NJ8: (
                    self._nsb.nanoject_number_inj2.NJ8.value
                ),
                self._nsb.nanoject_number_inj2.NA: None,
            }.get(self._nsb.nanoject_number_inj2, None)
        )

    @property
    def aind_of_burr(self) -> Optional[int]:
        """Maps of_burr to aind model"""
        return (
            None
            if self._nsb.of_burr is None
            else {
                self._nsb.of_burr.SELECT: None,
                self._nsb.of_burr.N_1: 1,
                self._nsb.of_burr.N_2: 2,
                self._nsb.of_burr.N_3: 3,
                self._nsb.of_burr.N_4: 4,
            }.get(self._nsb.of_burr, None)
        )

    @property
    def aind_pedigree_name(self) -> Optional[str]:
        """Maps pedigree_name to aind model"""
        return self._nsb.pedigree_name

    @property
    def aind_procedure(self) -> Optional[NSBProcedure]:
        """Maps procedure to aind model"""
        return self._nsb.procedure

    @property
    def aind_procedure_family(self) -> Optional[NSBProcedureCategory]:
        """Maps procedure_family to aind model"""
        return self._nsb.procedure_family

    @property
    def aind_procedure_slots(self) -> Optional[Any]:
        """Maps procedure_slots to aind model"""
        return (
            None
            if self._nsb.procedure_slots is None
            else {
                self._nsb.procedure_slots.SELECT: None,
                self._nsb.procedure_slots.SINGLE_SURGICAL_SESSION: None,
                self._nsb.procedure_slots.INITIAL_SURGERY_WITH_FOLL: None,
            }.get(self._nsb.procedure_slots, None)
        )

    @property
    def aind_procedure_t2(self) -> Optional[Any]:
        """Maps procedure_t2 to aind model"""
        return (
            None
            if self._nsb.procedure_t2 is None
            else {
                self._nsb.procedure_t2.SELECT: None,
                self._nsb.procedure_t2.N_2_P: None,
                self._nsb.procedure_t2.NP: None,
                self._nsb.procedure_t2.NA: None,
            }.get(self._nsb.procedure_t2, None)
        )

    @property
    def aind_project_id(self) -> Optional[Any]:
        """Maps project_id to aind model"""
        return (
            None
            if self._nsb.project_id is None
            else {
                self._nsb.project_id.N_1010300110_COSTA_PGA_LA: None,
                self._nsb.project_id.N_1020100710_CTY_M_FISH: None,
                self._nsb.project_id.N_1020100910_CTY_MORPHOLO: None,
                self._nsb.project_id.N_1020101110_CTY_CONNECTO: None,
                self._nsb.project_id.N_1020101210_CTY_CONNECTO: None,
                self._nsb.project_id.N_1020101610_CTY_TAXONOMY: None,
                self._nsb.project_id.N_1020102720_CTY_BRAIN_AX: None,
                self._nsb.project_id.N_1020102920_CTY_BRAIN_CE: None,
                self._nsb.project_id.N_1020103120_W4_CTY_EU_HO: None,
                self._nsb.project_id.N_1020103120_W5_CTY_EU_HO: None,
                self._nsb.project_id.N_1020103220_CTY_MOUSE_AG: None,
                self._nsb.project_id.N_1020103620_CTY_DISSEMIN: None,
                self._nsb.project_id.N_1020104020_CTY_BRAIN_UG: None,
                self._nsb.project_id.N_1020104320_CTY_OPTICAL: None,
                self._nsb.project_id.N_1020104410_CTY_GENOMICS: None,
                self._nsb.project_id.N_1020104510_CTY_IVSCC: None,
                self._nsb.project_id.N_1020104620_CTY_WEILL_NE: None,
                self._nsb.project_id.N_1020104810_CTY_BARCODED: None,
                self._nsb.project_id.N_1020104920_CTY_OPIOID_T: None,
                self._nsb.project_id.N_1020105520_CTY_EM_MOTOR: None,
                self._nsb.project_id.N_1020105720_CTY_BRAIN_BG: None,
                self._nsb.project_id.N_1020105920_CTY_SCORCH: None,
                self._nsb.project_id.N_1020106020_CTY_BRAIN_DR: None,
                self._nsb.project_id.N_1020106220_CTY_BICAN_MO: None,
                self._nsb.project_id.N_1020106410_CTY_GENETIC: None,
                self._nsb.project_id.N_1020106920_PRE_SPEND: None,
                self._nsb.project_id.N_1020199910_CTY_PROGRAM: None,
                self._nsb.project_id.N_1020200410_BTV_VISUAL_B: None,
                self._nsb.project_id.N_1020201220_BTV_BRAIN_VI: None,
                self._nsb.project_id.N_1020201620_MSP_BRAIN_MO: None,
                self._nsb.project_id.N_1020201720_BTV_BRAIN_NE: None,
                self._nsb.project_id.N_1020400410_OTH_MERITORI: None,
                self._nsb.project_id.N_1020400620_OTH_MEASURIN: None,
                self._nsb.project_id.N_1020400710_APLD_TARGETE: None,
                self._nsb.project_id.N_1020400910_CAPSID_SCREE: None,
                self._nsb.project_id.N_1020400910_DRAVET_SYNDR: None,
                self._nsb.project_id.N_1020401010_CTY_SR_SLC6: None,
                self._nsb.project_id.N_1020401110_CTY_SR_SYNGA: None,
                self._nsb.project_id.N_1020401210_CTY_SR_FRIED: None,
                self._nsb.project_id.N_1020401410_CTY_PARKINSO: None,
                self._nsb.project_id.N_1028800310_ANIMAL_CARE: None,
                self._nsb.project_id.N_1028800510_TRANSGENIC_C: None,
                self._nsb.project_id.N_1028800810_LAB_ANIMAL_S: None,
                self._nsb.project_id.N_1060100110_IMMUNOLOGY_D: None,
                self._nsb.project_id.N_1210100110_MSP_DEEP_INT: None,
                self._nsb.project_id.N_1210100210_MSP_BEHAVIOR: None,
                self._nsb.project_id.N_1210100310_MSP_X_AREA_F: None,
                self._nsb.project_id.N_1210100410_MSP_VIP_REGU: None,
                self._nsb.project_id.N_1210100510_MSP_SURROUND: None,
                self._nsb.project_id.N_1210100610_MSP_AUTOMATI: None,
                self._nsb.project_id.N_1210100710_MSP_TASK_TRA: None,
                self._nsb.project_id.N_1210100810_MSP_NEURAL_E: None,
                self._nsb.project_id.N_1210100910_MSP_BIO_REAL: None,
                self._nsb.project_id.N_1210101010_MSP_V1_OM_FI: None,
                self._nsb.project_id.N_1210101110_MSP_DYNAMIC: None,
                self._nsb.project_id.N_1210101210_MSP_LEARNING: None,
                self._nsb.project_id.N_1210101420_MSP_BRAIN_MO: None,
                self._nsb.project_id.N_1210101510_MSP_FALCONWO: None,
                self._nsb.project_id.N_1210101620_MSP_BRAIN_OP: None,
                self._nsb.project_id.N_1210101820_MSP_EPHAPTIC: None,
                self._nsb.project_id.N_1210102320_MSP_TEMPLETO: None,
                self._nsb.project_id.N_1210102520_MSP_U01_BRID: None,
                self._nsb.project_id.N_1210102620_MSP_TEMPLETO: None,
                self._nsb.project_id.N_1210199910_MSP_CROSS_PR: None,
                self._nsb.project_id.N_1210199910_MSP_CROS_001: None,
                self._nsb.project_id.N_1220100110_AIND_SCIENTI: None,
                self._nsb.project_id.N_1220100220_MOLECULAR_CO: None,
                self._nsb.project_id.N_1220100220_PROJECT_1: None,
                self._nsb.project_id.N_1220100220_PROJECT_2: None,
                self._nsb.project_id.N_1220100220_PROJECT_4: None,
                self._nsb.project_id.N_1220100420_AIND_BRAINST: None,
                self._nsb.project_id.N_1229999910_NEURAL_DYNAM: None,
                self._nsb.project_id.AAV_PRODUCTION_1028800410: None,
                self._nsb.project_id.CVS_PRODUCTION_1028800410: None,
                self._nsb.project_id.RD_1028800410: None,
            }.get(self._nsb.project_id, None)
        )

    @property
    def aind_ret_setting0(self) -> Optional[Any]:
        """Maps ret_setting0 to aind model"""
        return (
            None
            if self._nsb.ret_setting0 is None
            else {
                self._nsb.ret_setting0.OFF: None,
                self._nsb.ret_setting0.ON: None,
            }.get(self._nsb.ret_setting0, None)
        )

    @property
    def aind_ret_setting1(self) -> Optional[Any]:
        """Maps ret_setting1 to aind model"""
        return (
            None
            if self._nsb.ret_setting1 is None
            else {
                self._nsb.ret_setting1.OFF: None,
                self._nsb.ret_setting1.ON: None,
            }.get(self._nsb.ret_setting1, None)
        )

    @property
    def aind_round1_inj_isolevel(self) -> Optional[float]:
        """Maps round1_inj_isolevel to aind model"""
        return self._nsb.round1_inj_isolevel

    @property
    def aind_sex(self) -> Optional[Any]:
        """Maps sex to aind model"""
        return (
            None
            if self._nsb.sex is None
            else {
                self._nsb.sex.SELECT: None,
                self._nsb.sex.MALE: Sex.MALE,
                self._nsb.sex.FEMALE: Sex.FEMALE,
            }.get(self._nsb.sex, None)
        )

    @property
    def aind_surgery_status(self) -> Optional[Any]:
        """Maps surgery_status to aind model"""
        return (
            None
            if self._nsb.surgery_status is None
            else {
                self._nsb.surgery_status.NEW: None,
                self._nsb.surgery_status.INJECTION_PENDING: None,
                self._nsb.surgery_status.PHASE_2_PENDING: None,
                self._nsb.surgery_status.READY_FOR_FEEDBACK: None,
                self._nsb.surgery_status.UNPLANNED_ACUTE: None,
                self._nsb.surgery_status.PLANNED_ACUTE: None,
                self._nsb.surgery_status.NO_SURGERY: None,
            }.get(self._nsb.surgery_status, None)
        )

    @property
    def aind_title(self) -> Optional[str]:
        """Maps title to aind model"""
        return self._nsb.title

    @property
    def aind_ui_version_string(self) -> Optional[str]:
        """Maps ui_version_string to aind model"""
        return self._nsb.ui_version_string

    @property
    def aind_virus_a_p(self) -> Optional[float]:
        """Maps virus_a_p to aind model"""
        return self._parse_ap_str(self._nsb.virus_a_p)

    @property
    def aind_virus_d_v(self) -> Optional[float]:
        """Maps virus_d_v to aind model"""
        return self._parse_dv_str(self._nsb.virus_d_v)

    @property
    def aind_virus_hemisphere(self) -> Optional[Side]:
        """Maps virus_hemisphere to aind model"""
        return (
            None
            if self._nsb.virus_hemisphere is None
            else {
                self._nsb.virus_hemisphere.SELECT: None,
                self._nsb.virus_hemisphere.LEFT: Side.LEFT,
                self._nsb.virus_hemisphere.RIGHT: Side.RIGHT,
            }.get(self._nsb.virus_hemisphere, None)
        )

    @property
    def aind_virus_m_l(self) -> Optional[float]:
        """Maps virus_m_l to aind model"""
        return self._parse_ml_str(self._nsb.virus_m_l)

    @property
    def aind_weight_after_surgery(self) -> Optional[float]:
        """Maps weight_after_surgery to aind model"""
        return self._nsb.weight_after_surgery

    @property
    def aind_weight_before_surger(self) -> Optional[float]:
        """Maps weight_before_surger to aind model"""
        return self._nsb.weight_before_surger

    @property
    def aind_work_station1st_injection(self) -> Optional[str]:
        """Maps work_station1st_injection to aind model"""
        return (
            None
            if self._nsb.work_station1st_injection is None
            else {
                self._nsb.work_station1st_injection.SELECT: None,
                self._nsb.work_station1st_injection.SWS_1: (
                    self._nsb.work_station1st_injection.SWS_1.value
                ),
                self._nsb.work_station1st_injection.SWS_2: (
                    self._nsb.work_station1st_injection.SWS_2.value
                ),
                self._nsb.work_station1st_injection.SWS_3: (
                    self._nsb.work_station1st_injection.SWS_3.value
                ),
                self._nsb.work_station1st_injection.SWS_4: (
                    self._nsb.work_station1st_injection.SWS_4.value
                ),
                self._nsb.work_station1st_injection.SWS_5: (
                    self._nsb.work_station1st_injection.SWS_5.value
                ),
                self._nsb.work_station1st_injection.SWS_6: (
                    self._nsb.work_station1st_injection.SWS_6.value
                ),
                self._nsb.work_station1st_injection.SWS_7: (
                    self._nsb.work_station1st_injection.SWS_7.value
                ),
                self._nsb.work_station1st_injection.SWS_8: (
                    self._nsb.work_station1st_injection.SWS_8.value
                ),
                self._nsb.work_station1st_injection.SWS_9: (
                    self._nsb.work_station1st_injection.SWS_9.value
                ),
            }.get(self._nsb.work_station1st_injection, None)
        )

    # Additional properties
    @property
    def aind_experimenter_full_name(self) -> str:
        """Map author id to experimenter name"""
        return (
            "NSB"
            if self.aind_author_id is None
            else f"NSB-{self.aind_author_id}"
        )

    def has_hp_procedure(self) -> bool:
        """Is there a headpost procedure?"""
        return self.aind_procedure in {
            NSBProcedure.HP_ONLY,
            NSBProcedure.HP_TRANSCRANIAL,
            NSBProcedure.FIBER_OPTIC_IMPLANT_WITH,
            NSBProcedure.INJECTION_FIBER_OPTIC_IMP,
            NSBProcedure.ISIGUIDED_INJECTION_WITH,
            NSBProcedure.STEREOTAXIC_INJECTION_WIT,
        }

    def has_cran_procedure(self) -> bool:
        """Is there a craniotomy procedure?"""
        return self.aind_procedure in {
            NSBProcedure.FRONTAL_CTX_2_P,
            NSBProcedure.INJ_MOTOR_CTX,
            NSBProcedure.INJ_VISUAL_CTX_2_P,
            NSBProcedure.INJ_WHC_NP_1_INJECTION_LO,
            NSBProcedure.MOTOR_CTX,
            NSBProcedure.VISUAL_CTX_NP,
            NSBProcedure.VISUAL_CTX_2_P,
            NSBProcedure.WHC_NP,
        }

    def surgery_during_info(
        self, during: During, inj_type: Optional[InjectionType] = None
    ) -> SurgeryDuringInfo:
        """
        Compiles burr hole information from NSB data
        Parameters
        ----------
        during : During
          Initial or Follow up
        inj_type : Optional[InjectionType]
          Injection type during the surgery. Default is None.

        Returns
        -------
        SurgeryDuringInfo

        """
        if during == During.FOLLOW_UP:
            if inj_type == InjectionType.NANOJECT:
                instrument_id = self.aind_nanoject_number_inj2
            elif inj_type == InjectionType.IONTOPHORESIS:
                instrument_id = self.aind_ionto_number_inj2
            else:
                instrument_id = None
            return SurgeryDuringInfo(
                anaesthetic_duration_in_minutes=(
                    self.aind_first_injection_iso_durat
                ),
                anaesthetic_level=self.aind_round1_inj_isolevel,
                start_date=self.aind_date1st_injection,
                workstation_id=self.aind_work_station1st_injection,
                recovery_time=self.aind_first_inj_recovery,
                weight_prior=self.aind_first_injection_weight_be,
                weight_post=self.aind_first_injection_weight_af,
                instrument_id=instrument_id,
            )
        elif during == During.INITIAL:
            if inj_type == InjectionType.NANOJECT:
                instrument_id = self.aind_nanoject_number_inj10
            elif inj_type == InjectionType.IONTOPHORESIS:
                instrument_id = self.aind_ionto_number_inj1
            else:
                instrument_id = None
            return SurgeryDuringInfo(
                anaesthetic_duration_in_minutes=self.aind_iso_on,
                anaesthetic_level=self.aind_hp_iso_level,
                start_date=self.aind_date_of_surgery,
                workstation_id=self.aind_work_station1st_injection,
                recovery_time=self.aind_hp_recovery,
                weight_prior=self.aind_weight_before_surger,
                weight_post=self.aind_weight_after_surgery,
                instrument_id=instrument_id,
            )
        else:
            return SurgeryDuringInfo()

    def burr_hole_info(self, burr_hole_num: int) -> BurrHoleInfo:
        """
        Compiles burr hole information from NSB data
        Parameters
        ----------
        burr_hole_num : int
          Burr hole number

        Returns
        -------
        BurrHoleInfo

        """
        if burr_hole_num == 1:
            return BurrHoleInfo(
                hemisphere=self.aind_virus_hemisphere,
                coordinate_ml=self.aind_virus_m_l,
                coordinate_ap=self.aind_virus_a_p,
                coordinate_depth=self.aind_virus_d_v,
                angle=self.aind_inj1_angle_v2,
                during=self.aind_burr1_perform_during,
                inj_type=self.aind_inj1_type,
                virus_strain=self.aind_inj1_virus_strain_rt,
                inj_current=self.aind_inj1_current,
                alternating_current=self.aind_inj1_alternating_time,
                inj_duration=self.aind_inj1_ionto_time,
                inj_volume=self.aind_inj1volperdepth,
                fiber_implant_depth=self.aind_fiber_implant1_dv,
            )
        elif burr_hole_num == 2:
            return BurrHoleInfo(
                hemisphere=self.aind_hemisphere2nd_inj,
                coordinate_ml=self.aind_ml2nd_inj,
                coordinate_ap=self.aind_ap2nd_inj,
                coordinate_depth=self.aind_dv2nd_inj,
                angle=self.aind_inj2_angle_v2,
                during=self.aind_burr2_perform_during,
                inj_type=self.aind_inj2_type,
                virus_strain=self.aind_inj2_virus_strain_rt,
                inj_current=self.aind_inj2_current,
                alternating_current=self.aind_inj2_alternating_time,
                inj_duration=self.aind_inj2_ionto_time,
                inj_volume=self.aind_inj2volperdepth,
                fiber_implant_depth=self.aind_fiber_implant2_dv,
            )
        elif burr_hole_num == 3:
            return BurrHoleInfo(
                hemisphere=self.aind_burr_3_hemisphere,
                coordinate_ml=self.aind_burr3_m_l,
                coordinate_ap=self.aind_burr3_a_p,
                coordinate_depth=self.aind_burr3_d_v,
                angle=self.aind_burr_3_angle,
                during=self.aind_burr3_perform_during,
                inj_type=self.aind_inj3_type,
                virus_strain=self.aind_inj_virus_strain_rt,
                inj_current=self.aind_inj3_current,
                alternating_current=self.aind_inj3_alternating_time,
                inj_duration=self.aind_inj3_ionto_time,
                inj_volume=self.aind_inj3volperdepth,
                fiber_implant_depth=self.aind_fiber_implant3_d_x00,
            )
        elif burr_hole_num == 4:
            return BurrHoleInfo(
                hemisphere=self.aind_burr_4_hemisphere,
                coordinate_ml=self.aind_burr4_m_l,
                coordinate_ap=self.aind_burr4_a_p,
                coordinate_depth=self.aind_burr4_d_v,
                angle=self.aind_burr_4_angle,
                during=self.aind_burr4_perform_during,
                inj_type=self.aind_inj4_type,
                virus_strain=self.aind_inj4_virus_strain_rt,
                inj_current=self.aind_inj4_current,
                alternating_current=self.aind_inj4_alternating_time,
                inj_duration=self.aind_inj4_ionto_time,
                inj_volume=self.aind_inj4volperdepth,
                fiber_implant_depth=self.aind_fiber_implant4_d_x00,
            )
        else:
            return BurrHoleInfo()

    @staticmethod
    def _map_burr_hole_number_to_probe(
        burr_hole_num: int,
    ) -> Optional[ProbeName]:
        """Maps NSB Burr hole number into AIND ProbeName"""
        if burr_hole_num == 1:
            return ProbeName.PROBE_A
        elif burr_hole_num == 2:
            return ProbeName.PROBE_B
        elif burr_hole_num == 3:
            return ProbeName.PROBE_C
        elif burr_hole_num == 4:
            return ProbeName.PROBE_D
        else:
            return None

    def get_procedures(self) -> List[SubjectProcedure]:
        """Get a list of subject procedures"""
        procedures = []
        experimenter_full_name = self.aind_experimenter_full_name
        iacuc_protocol = self.aind_iacuc_protocol

        # Check if any headframe procedures
        if self.has_hp_procedure():
            hp_during = self.aind_headpost_perform_dur
            hf_surgery_during_info = self.surgery_during_info(hp_during)
            anaesthetic = Anaesthetic.construct(
                type="isoflurane",
                duration=(
                    hf_surgery_during_info.anaesthetic_duration_in_minutes
                ),
                level=hf_surgery_during_info.anaesthetic_level,
            )
            headpost_info = HeadPostInfo.from_hp_and_hp_type(
                hp=self.aind_headpost, hp_type=self.aind_headpost_type
            )

            headframe_procedure = Headframe.construct(
                start_date=hf_surgery_during_info.start_date,
                end_date=hf_surgery_during_info.start_date,
                experimenter_full_name=experimenter_full_name,
                iacuc_protocol=iacuc_protocol,
                animal_weight_prior=hf_surgery_during_info.weight_prior,
                animal_weight_post=hf_surgery_during_info.weight_post,
                headframe_type=headpost_info.headframe_type,
                headframe_part_number=headpost_info.headframe_part_number,
                well_type=headpost_info.well_type,
                well_part_number=headpost_info.well_part_number,
                anaesthesia=anaesthetic,
            )
            procedures.append(headframe_procedure)

        # Check for craniotomy procedures
        if self.has_cran_procedure():
            craniotomy_type = self.aind_craniotomy_type
            cran_during = self.aind_craniotomy_perform_d
            cran_during_info = self.surgery_during_info(cran_during)
            anaesthetic = Anaesthetic.construct(
                type="isoflurane",
                duration=cran_during_info.anaesthetic_duration_in_minutes,
                level=cran_during_info.anaesthetic_level,
            )
            bregma_to_lambda_distance = self.aind_breg2_lamb
            if craniotomy_type == CraniotomyType.FIVE_MM:
                craniotomy_coordinates_reference = (
                    CoordinateReferenceLocation.LAMBDA
                )
                craniotomy_size = 5
            elif craniotomy_type == CraniotomyType.THREE_MM:
                craniotomy_coordinates_reference = None
                craniotomy_size = 3
            else:
                craniotomy_coordinates_reference = None
                craniotomy_size = None

            cran_procedure = Craniotomy.construct(
                start_date=cran_during_info.start_date,
                end_date=cran_during_info.start_date,
                experimenter_full_name=experimenter_full_name,
                iacuc_protocol=iacuc_protocol,
                animal_weight_prior=cran_during_info.weight_prior,
                animal_weight_post=cran_during_info.weight_post,
                craniotomy_type=craniotomy_type,
                craniotomy_size=craniotomy_size,
                anaesthesia=anaesthetic,
                workstation_id=cran_during_info.workstation_id,
                recovery_time=cran_during_info.recovery_time,
                bregma_to_lambda_distance=bregma_to_lambda_distance,
                craniotomy_coordinates_reference=(
                    craniotomy_coordinates_reference
                ),
            )
            procedures.append(cran_procedure)

        # Check if there are any procedures for burr holes 1 through 4
        for burr_hole_num in range(1, 5):
            if getattr(self, f"aind_burr_hole_{burr_hole_num}") in {
                BurrHoleProcedure.INJECTION,
                BurrHoleProcedure.INJECTION_FIBER_IMPLANT,
            }:
                burr_hole_info = self.burr_hole_info(
                    burr_hole_num=burr_hole_num
                )
                burr_during_info = self.surgery_during_info(
                    during=burr_hole_info.during,
                    inj_type=burr_hole_info.inj_type,
                )
                anaesthetic = Anaesthetic.construct(
                    type="isoflurane",
                    duration=burr_during_info.anaesthetic_duration_in_minutes,
                    level=burr_during_info.anaesthetic_level,
                )
                injection_materials = (
                    None
                    if burr_hole_info.virus_strain is None
                    else InjectionMaterial.construct(
                        full_genome_name=burr_hole_info.virus_strain
                    )
                )
                if burr_hole_info.inj_type == InjectionType.IONTOPHORESIS:
                    injection_proc = IontophoresisInjection.construct(
                        start_date=burr_during_info.start_date,
                        end_date=burr_during_info.start_date,
                        experimenter_full_name=experimenter_full_name,
                        iacuc_protocol=iacuc_protocol,
                        animal_weight_prior=burr_during_info.weight_prior,
                        animal_weight_post=burr_during_info.weight_post,
                        workstation_id=burr_during_info.workstation_id,
                        injection_hemisphere=burr_hole_info.hemisphere,
                        injection_coordinate_ml=burr_hole_info.coordinate_ml,
                        injection_coordinate_ap=burr_hole_info.coordinate_ap,
                        injection_coordinate_depth=(
                            burr_hole_info.coordinate_depth
                        ),
                        injection_angle=burr_hole_info.angle,
                        injection_current=burr_hole_info.inj_current,
                        injection_duration=burr_hole_info.inj_duration,
                        alternating_current=burr_hole_info.alternating_current,
                        recovery_time=burr_during_info.recovery_time,
                        instrument_id=burr_during_info.instrument_id,
                        anaesthesia=anaesthetic,
                        bregma_to_lambda_distance=self.aind_breg2_lamb,
                        injection_coordinate_reference=(
                            CoordinateReferenceLocation.BREGMA
                        ),
                        injection_materials=injection_materials,
                    )
                elif burr_hole_info.inj_type == InjectionType.NANOJECT:
                    injection_proc = NanojectInjection.construct(
                        start_date=burr_during_info.start_date,
                        end_date=burr_during_info.start_date,
                        experimenter_full_name=experimenter_full_name,
                        iacuc_protocol=iacuc_protocol,
                        animal_weight_prior=burr_during_info.weight_prior,
                        animal_weight_post=burr_during_info.weight_post,
                        workstation_id=burr_during_info.workstation_id,
                        injection_hemisphere=burr_hole_info.hemisphere,
                        injection_coordinate_ml=burr_hole_info.coordinate_ml,
                        injection_coordinate_ap=burr_hole_info.coordinate_ap,
                        injection_coordinate_depth=(
                            burr_hole_info.coordinate_depth
                        ),
                        injection_angle=burr_hole_info.angle,
                        injection_current=burr_hole_info.inj_current,
                        injection_duration=burr_hole_info.inj_duration,
                        injection_volume=burr_hole_info.inj_volume,
                        alternating_current=burr_hole_info.alternating_current,
                        recovery_time=burr_during_info.recovery_time,
                        instrument_id=burr_during_info.instrument_id,
                        anaesthesia=anaesthetic,
                        bregma_to_lambda_distance=self.aind_breg2_lamb,
                        injection_coordinate_reference=(
                            CoordinateReferenceLocation.BREGMA
                        ),
                        injection_materials=injection_materials,
                    )
                else:
                    injection_proc = BrainInjection.construct(
                        start_date=burr_during_info.start_date,
                        end_date=burr_during_info.start_date,
                        experimenter_full_name=experimenter_full_name,
                        iacuc_protocol=iacuc_protocol,
                        animal_weight_prior=burr_during_info.weight_prior,
                        animal_weight_post=burr_during_info.weight_post,
                        workstation_id=burr_during_info.workstation_id,
                        injection_hemisphere=burr_hole_info.hemisphere,
                        injection_coordinate_ml=burr_hole_info.coordinate_ml,
                        injection_coordinate_ap=burr_hole_info.coordinate_ap,
                        injection_coordinate_depth=(
                            burr_hole_info.coordinate_depth
                        ),
                        injection_angle=burr_hole_info.angle,
                        injection_duration=burr_hole_info.inj_duration,
                        recovery_time=burr_during_info.recovery_time,
                        instrument_id=burr_during_info.instrument_id,
                        anaesthesia=anaesthetic,
                        bregma_to_lambda_distance=self.aind_breg2_lamb,
                        injection_coordinate_reference=(
                            CoordinateReferenceLocation.BREGMA
                        ),
                        injection_materials=injection_materials,
                    )
                procedures.append(injection_proc)
            if getattr(self, f"aind_burr_hole_{burr_hole_num}") in {
                BurrHoleProcedure.FIBER_IMPLANT,
                BurrHoleProcedure.INJECTION_FIBER_IMPLANT,
            }:
                probe_name = self._map_burr_hole_number_to_probe(burr_hole_num)
                burr_hole_info = self.burr_hole_info(
                    burr_hole_num=burr_hole_num
                )
                burr_during_info = self.surgery_during_info(
                    during=burr_hole_info.during,
                    inj_type=burr_hole_info.inj_type,
                )
                bregma_to_lambda_distance = self.aind_breg2_lamb
                anaesthetic = Anaesthetic.construct(
                    type="isoflurane",
                    duration=burr_during_info.anaesthetic_duration_in_minutes,
                    level=burr_during_info.anaesthetic_level,
                )
                ophys_probe = OphysProbe.construct(
                    name=probe_name,
                    stereotactic_coordinate_ml=burr_hole_info.coordinate_ml,
                    stereotactic_coordinate_ap=burr_hole_info.coordinate_ap,
                    stereotactic_coordinate_dv=(
                        burr_hole_info.fiber_implant_depth
                    ),
                    angle=burr_hole_info.angle,
                    bregma_to_lambda_distance=bregma_to_lambda_distance,
                    stereotactic_coordinate_reference=(
                        CoordinateReferenceLocation.BREGMA
                    ),
                )
                fiber_implant_proc = FiberImplant.construct(
                    start_date=burr_during_info.start_date,
                    end_date=burr_during_info.start_date,
                    experimenter_full_name=experimenter_full_name,
                    iacuc_protocol=iacuc_protocol,
                    animal_weight_prior=burr_during_info.weight_prior,
                    animal_weight_post=burr_during_info.weight_post,
                    probes=ophys_probe,
                    anaesthesia=anaesthetic,
                )
                procedures.append(fiber_implant_proc)

        # Create generic procedure model if no specific procedures found
        if len(procedures) == 0:
            subject_procedure = SubjectProcedure.construct(
                start_date=self.aind_date_of_surgery,
                end_date=self.aind_date_of_surgery,
                experimenter_full_name=experimenter_full_name,
                iacuc_protocol=iacuc_protocol,
                animal_weight_prior=self.aind_weight_before_surger,
                animal_weight_post=self.aind_weight_after_surgery,
            )
            procedures.append(subject_procedure)

        return procedures
