diff --git a/geomagio/residual/Calculation.py b/geomagio/residual/Calculation.py
index dbce845d062a71634dea7b06e53e73a81a13d3c3..72708859b8382b38829db4c34d3cc926417ac739 100644
--- a/geomagio/residual/Calculation.py
+++ b/geomagio/residual/Calculation.py
@@ -37,24 +37,44 @@ def calculate(reading: Reading, adjust_reference: bool = True) -> Reading:
         hemisphere=reading.hemisphere, measurements=reading.measurements
     )
     corrected_f = f + reading.pier_correction
-    # calculate absolutes
-    absoluteH, absoluteZ = calculate_HZ_absolutes(
+
+    # calculate absolutes,
+    (absoluteH, absoluteZ) = calculate_HZ_absolutes(
         corrected_f=corrected_f,
         inclination=inclination,
         mean=i_mean,
         reference=reference,
     )
+
+    horizontal_component = calculate_horizontal_component(
+        inclination=inclination, corrected_f=corrected_f
+    )
+
+    vertical_component = calculate_vertical_component(
+        inclination=inclination, corrected_f=corrected_f
+    )
+
     absoluteD, meridian = calculate_D_absolute(
         azimuth=reading.azimuth,
         h_baseline=absoluteH.baseline,
         measurements=reading.measurements,
         reference=reference,
     )
-    # populate diagnostics object with averaged measurements
-    diagnostics = Diagnostics(
-        inclination=inclination,
-        meridian=meridian,
+
+    d_computed = calculate_D_computed(
+        measurements=reading.measurements,
+        h_baseline=absoluteH.baseline,
     )
+
+    r_computed = calculate_R_computed(
+        measurements=reading.measurements,
+        h_baseline=absoluteH.baseline,
+    )
+
+    magnetic_south_meridian = calculate_magnetic_south_meridian(
+        measurements=reading.measurements,
+    )
+
     # calculate scale
     scale_value = None
     scale_measurements = reading[mt.NORTH_DOWN_SCALE]
@@ -64,14 +84,59 @@ def calculate(reading: Reading, adjust_reference: bool = True) -> Reading:
             inclination=inclination,
             measurements=scale_measurements,
         )
+
+    mean_mark = calculate_mean_mark(
+        measurements=reading.measurements,
+    )
+
+    magnetic_azimuth_of_mark = calculate_magnetic_azimuth_of_mark(
+        mean_mark=mean_mark, magnetic_south_meridian=magnetic_south_meridian
+    )
+
+    ordinate_f = f
+
+    ordinate_d = calculate_ordinate_d(
+        absoluteD_absolute=absoluteD.absolute,
+        absoluteD_baseline=absoluteD.baseline,
+    )
+
+    ordinate_h = calculate_ordinate_h(
+        absoluteH_absolute=absoluteH.absolute,
+        absoluteH_baseline=absoluteH.baseline,
+        ordinate_d=ordinate_d,
+    )
+
+    ordinate_z = calculate_ordinate_z(
+        absoluteZ_absolute=absoluteZ.absolute,
+        absoluteZ_baseline=absoluteZ.baseline,
+    )
+
+    # populate diagnostics object with averaged measurements
+    diagnostics = Diagnostics(
+        corrected_f=corrected_f,
+        d_computed=d_computed,
+        horizontal_component=horizontal_component,
+        inclination=inclination,
+        magnetic_azimuth_of_mark=magnetic_azimuth_of_mark,
+        magnetic_south_meridian=magnetic_south_meridian,
+        mean_mark=mean_mark,
+        ordinate_d=ordinate_d,
+        ordinate_f=ordinate_f,
+        ordinate_h=ordinate_h,
+        ordinate_z=ordinate_z,
+        r_computed=r_computed,
+        vertical_component=vertical_component,
+    )
+
     # create new reading object
     calculated = Reading(
         absolutes=[absoluteD, absoluteH, absoluteZ],
-        scale_value=scale_value,
         diagnostics=diagnostics,
+        scale_value=scale_value,
         # copy other attributes
-        **reading.dict(exclude={"absolutes", "scale_value", "diagnostics"}),
+        **reading.dict(exclude={"absolutes", "diagnostics", "scale_value"}),
     )
+
     return calculated
 
 
@@ -154,8 +219,8 @@ def calculate_HZ_absolutes(
     corrected_f: float,
     mean: AverageMeasurement,
     reference: Measurement,
-) -> Tuple[Absolute, Absolute]:
-    """Calculate H and Z absolutes.
+) -> Tuple[Absolute, Absolute, float, float]:
+    """Calculate H and Z absolutes
 
     Parameters
     ----------
@@ -292,3 +357,235 @@ def calculate_scale_value(
     residual_change = m2.residual - m1.residual
     scale_value = corrected_f * field_change / np.abs(residual_change)
     return scale_value
+
+
+def calculate_magnetic_south_meridian(measurements: List[Measurement]) -> float:
+    """Calculate magnetic_south_meridian.
+
+    Parameters
+    ----------
+    measurements: measurements, should have type WEST_DOWN, EAST_DOWN, WEST_UP, EAST_UP.
+
+    Returns
+    -------
+    Calculated magnetic_south_meridian.
+    """
+    # declination measurements
+    declination_measurements = [
+        average_measurement(measurements, [t]) for t in DECLINATION_TYPES
+    ]
+
+    magnetic_south_meridian = np.average([m.angle for m in declination_measurements])
+    return magnetic_south_meridian
+
+
+def calculate_D_computed(
+    measurements: List[Measurement],
+    h_baseline: float,
+) -> float:
+    """Calculate d_computed.
+
+    Parameters
+    ----------
+    measurements: measurements,
+    h_baseline
+
+    Returns
+    -------
+    Calculated d_computed.
+    """
+    # declination measurements
+    declination_measurements = [
+        average_measurement(measurements, [t]) for t in DECLINATION_TYPES
+    ]
+
+    d_computed = np.average(
+        [
+            -1 * np.degrees(np.arctan(m.e / (m.h + h_baseline)))
+            for m in declination_measurements
+        ]
+    )
+
+    return d_computed
+
+
+def calculate_R_computed(
+    measurements: List[Measurement],
+    h_baseline: float,
+) -> float:
+    """Calculate r_computed.
+
+    Parameters
+    ----------
+    measurements: measurements,
+    h_baseline
+
+    Returns
+    -------
+    Calculated r_computed.
+    """
+    # declination measurements
+    declination_measurements = [
+        average_measurement(measurements, [t]) for t in DECLINATION_TYPES
+    ]
+
+    r_computed = np.average(
+        [
+            np.degrees(
+                m.measurement_type.meridian
+                * (np.arcsin(m.residual / np.sqrt((m.h + h_baseline) ** 2 + m.e**2)))
+            )
+            for m in declination_measurements
+        ]
+    )
+
+    return r_computed
+
+
+def calculate_mean_mark(
+    measurements: List[Measurement],
+) -> float:
+    """Calculate mean_mark.
+
+    Parameters
+    ----------
+    measurements: measurements,
+
+
+    Returns
+    -------
+    Calculated mean_mark angle.
+    """
+
+    # average mark
+    average_mark = average_measurement(measurements, MARK_TYPES)
+
+    return average_mark.angle
+
+
+def calculate_magnetic_azimuth_of_mark(
+    mean_mark: float,
+    magnetic_south_meridian: float,
+) -> float:
+    """Calculate magnetic_azimuth_of_mark.
+
+    Parameters
+    ----------
+    mean_mark: float,
+    magnetic_south_meridian:float,
+
+
+    Returns
+    -------
+    Calculated magnetic_azimuth_of_mark
+    """
+
+    magnetic_azimuth_of_mark = mean_mark - magnetic_south_meridian
+
+    return magnetic_azimuth_of_mark
+
+
+def calculate_ordinate_d(
+    absoluteD_absolute: float,
+    absoluteD_baseline: float,
+) -> float:
+    """Calculate ordinate_d.
+
+    Parameters
+    ----------
+    absoluteD_absolute: float,
+    absoluteD_baseline:float,
+
+
+    Returns
+    -------
+    Calculated ordinate_d
+    """
+
+    ordinate_d = absoluteD_absolute - absoluteD_baseline
+
+    return ordinate_d
+
+
+def calculate_ordinate_z(
+    absoluteZ_absolute: float,
+    absoluteZ_baseline: float,
+) -> float:
+    """Calculate ordinate_z.
+
+    Parameters
+    ----------
+    absoluteZ_absolute: float,
+    absoluteZ_baseline:float,
+
+
+    Returns
+    -------
+    Calculated ordinate_z
+    """
+
+    ordinate_z = absoluteZ_absolute - absoluteZ_baseline
+
+    return ordinate_z
+
+
+def calculate_ordinate_h(
+    absoluteH_absolute: float,
+    absoluteH_baseline: float,
+    ordinate_d: float,
+) -> float:
+    """Calculate ordinate_z.
+
+    Parameters
+    ----------
+    absoluteH_absolute: float,
+    absoluteH_baseline:float,
+    ordinate_d:float,
+
+    Returns
+    -------
+    Calculated ordinate_h
+    """
+    ordinate_e = absoluteH_absolute * np.sin(np.radians(ordinate_d))
+
+    ordinate_h = np.sqrt(absoluteH_absolute**2 - ordinate_e**2) - absoluteH_baseline
+
+    return ordinate_h
+
+
+def calculate_horizontal_component(inclination: float, corrected_f: float) -> float:
+    """Calculate horizontal_component.
+
+    Parameters
+    ----------
+    inclination: calculated inclination.
+    corrected_f: calculated f with pier correction.
+
+    Returns
+    -------
+    Calculated horizontal_component
+    """
+
+    inclination_radians = np.radians(inclination)
+    horizontal_component = corrected_f * np.cos(inclination_radians)
+
+    return horizontal_component
+
+
+def calculate_vertical_component(inclination: float, corrected_f: float) -> float:
+    """Calculate vertical_component.
+
+    Parameters
+    ----------
+    inclination: calculated inclination.
+    corrected_f: calculated f with pier correction.
+
+    Returns
+    -------
+    Calculated vertical_component
+    """
+
+    inclination_radians = np.radians(inclination)
+    vertical_component = corrected_f * np.sin(inclination_radians)
+
+    return vertical_component
diff --git a/geomagio/residual/Diagnostics.py b/geomagio/residual/Diagnostics.py
index 42f8572a7372b9c03d8b90406db5d9235509ebd3..7c75de63106022b30bead8ffea2653549d916c3a 100644
--- a/geomagio/residual/Diagnostics.py
+++ b/geomagio/residual/Diagnostics.py
@@ -8,9 +8,32 @@ class Diagnostics(BaseModel):
 
     Attributes
     ----------
-    inclination: Average of inclination measurements
-    meridian: Calculated meridian value
+    corrected_f: Optional[float] = None
+    d_computed: Optional[float] = None
+    horizontal_component: Optional[float] = None
+    inclination: Optional[float] = None
+    magnetic_azimuth_of_mark: Optional[float] = None
+    magnetic_south_meridian: Optional[float] = None
+    mean_mark: Optional[float] = None
+    meridian: Optional[float] = None
+    ordinate_d: Optional[float] = None
+    ordinate_f: Optional[float] = None
+    ordinate_h: Optional[float] = None
+    ordinate_z: Optional[float] = None
+    r_computed: Optional[float] = None
+    vertical_component: Optional[float] = None
     """
 
-    inclination: float
-    meridian: Optional[float] = None
+    corrected_f: Optional[float] = None
+    d_computed: Optional[float] = None
+    horizontal_component: Optional[float] = None
+    inclination: Optional[float] = None
+    magnetic_azimuth_of_mark: Optional[float] = None
+    magnetic_south_meridian: Optional[float] = None
+    mean_mark: Optional[float] = None
+    ordinate_d: Optional[float] = None
+    ordinate_f: Optional[float] = None
+    ordinate_h: Optional[float] = None
+    ordinate_z: Optional[float] = None
+    r_computed: Optional[float] = None
+    vertical_component: Optional[float] = None
diff --git a/geomagio/residual/Reading.py b/geomagio/residual/Reading.py
index 101ba4b4b7ed3c7e36024e6c8234b03cb1aea55c..752ffc4b0c4d778072584b2de468785444f61f52 100644
--- a/geomagio/residual/Reading.py
+++ b/geomagio/residual/Reading.py
@@ -33,12 +33,12 @@ class Reading(BaseModel):
 
     absolutes: List[Absolute] = []
     azimuth: float = 0
+    diagnostics: Diagnostics = None
     hemisphere: Literal[-1, 1] = 1
     measurements: List[Measurement] = []
     metadata: Dict = {}
     pier_correction: float = 0
     scale_value: float = None
-    diagnostics: Diagnostics = None
 
     def __getitem__(self, measurement_type: MeasurementType):
         """Provide access to measurements by type.