Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update spatial data schema #655

Merged
merged 13 commits into from
Dec 2, 2021
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ documentation
ASDF
====

- update weldx extension and manifest version to ``0.1.1`` [:pull:`655`]

- removed legacy ``weldx`` tag and schema support [:pull:`600`]

- update `core/geometry/spatial_data` to version `0.1.1` with support for multidimensional data [:pull:`655`]

- add ``wx_shape`` validation support for ``core/data_array`` [:pull:`655`]

deprecations
============

Expand Down
10 changes: 9 additions & 1 deletion devtools/scripts/update_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

import yaml

from weldx.asdf.constants import (
WELDX_EXTENSION_URI,
WELDX_EXTENSION_VERSION,
WELDX_MANIFEST_URI,
)
from weldx.asdf.util import get_converter_for_tag


def update_manifest(
search_dir: str = "../../weldx/schemas",
out: str = "../../weldx/manifests/weldx-0.1.0.yaml",
out: str = f"../../weldx/manifests/weldx-{WELDX_EXTENSION_VERSION}.yaml",
):
"""Create manifest file from existing schemas."""
# read existing manifest
Expand All @@ -16,6 +21,9 @@ def update_manifest(
Loader=yaml.SafeLoader,
)

manifest["id"] = WELDX_MANIFEST_URI
manifest["extension_uri"] = WELDX_EXTENSION_URI

# keep only ASDF schema mappings
manifest["tags"] = [
mapping
Expand Down
4 changes: 3 additions & 1 deletion weldx/asdf/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
WELDX_SCHEMA_URI_BASE = "asdf://weldx.bam.de/weldx/schemas/"
WELDX_EXTENSION_URI_BASE = "asdf://weldx.bam.de/weldx/extensions/"

WELDX_EXTENSION_VERSION = "0.1.0"
WELDX_EXTENSION_VERSION = "0.1.1"
WELDX_EXTENSION_URI = f"{WELDX_EXTENSION_URI_BASE}weldx-{WELDX_EXTENSION_VERSION}"

WELDX_MANIFEST_URI = WELDX_URI_BASE + "manifests/weldx-" + WELDX_EXTENSION_VERSION
2 changes: 1 addition & 1 deletion weldx/asdf/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ def get_converter_for_tag(tag: str) -> Union[WeldxConverter, None]:


def get_highest_tag_version(
pattern: str, ctx: Union[SerializationContext, AsdfConfig] = None
pattern: Union[str, List[str]], ctx: Union[SerializationContext, AsdfConfig] = None
) -> Union[str, None]:
"""Get the highest available weldx extension tag version matching a pattern.

Expand Down
128 changes: 128 additions & 0 deletions weldx/manifests/weldx-0.1.1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
%YAML 1.1
---
id: asdf://weldx.bam.de/weldx/manifests/weldx-0.1.1
extension_uri: asdf://weldx.bam.de/weldx/extensions/weldx-0.1.1
title: weldx extension manifest for tag mapping
description: Manifest listing all tag URIs with schema URIs supported by weldx
tags:
- tag_uri: tag:stsci.edu:asdf/unit/quantity-1.1.0
schema_uri: http://stsci.edu/schemas/asdf/unit/quantity-1.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/uuid-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/uuid-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/design/base_metal-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/design/base_metal-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/design/connection-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/design/connection-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/design/joint_penetration-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/design/joint_penetration-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/design/sub_assembly-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/design/sub_assembly-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/design/weldment-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/design/weldment-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/design/weld_details-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/design/weld_details-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/design/workpiece-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/design/workpiece-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/process/arc_welding_process-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/process/arc_welding_process-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/process/gas_component-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/process/gas_component-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/process/shielding_gas_for_procedure-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/process/shielding_gas_for_procedure-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/aws/process/shielding_gas_type-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/aws/process/shielding_gas_type-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/dataset-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/dataset-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/data_array-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/data_array-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/dimension-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/dimension-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/file-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/file-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/mathematical_expression-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/mathematical_expression-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/time_series-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/time_series-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/variable-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/variable-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/geometry/spatial_data-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/geometry/spatial_data-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/geometry/spatial_data-0.1.1
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/geometry/spatial_data-0.1.1
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/graph/di_edge-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/graph/di_edge-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/graph/di_graph-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/graph/di_graph-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/graph/di_node-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/graph/di_node-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/transformations/coordinate_system_hierarchy-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/transformations/coordinate_system_hierarchy-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/transformations/local_coordinate_system-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/transformations/local_coordinate_system-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/core/transformations/rotation-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/core/transformations/rotation-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/debug/test_property_tag-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/debug/test_property_tag-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/debug/test_shape_validator-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/debug/test_shape_validator-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/debug/test_unit_validator-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/debug/test_unit_validator-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/equipment/measurement_equipment-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/equipment/measurement_equipment-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/DHUGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/DHUGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/DHVGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/DHVGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/DUGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/DUGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/DVGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/DVGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/FFGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/FFGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/HUGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/HUGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/HVGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/HVGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/IGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/IGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/UGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/UGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/UVGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/UVGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/VGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/VGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/groove/iso_9692_1_2013_12/VVGroove-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/groove/iso_9692_1_2013_12/VVGroove-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/measurement/error-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/measurement/error-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/measurement/measurement-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/measurement/measurement-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/measurement/measurement_chain-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/measurement/measurement_chain-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/measurement/signal-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/measurement/signal-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/measurement/signal_transformation-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/measurement/signal_transformation-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/measurement/source-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/measurement/source-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/process/GMAW-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/process/GMAW-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/process/CLOOS/pulse-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/process/CLOOS/pulse-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/process/CLOOS/spray_arc-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/process/CLOOS/spray_arc-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/time/datetimeindex-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/time/datetimeindex-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/time/time-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/time/time-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/time/timedelta-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/time/timedelta-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/time/timedeltaindex-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/time/timedeltaindex-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/time/timestamp-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/time/timestamp-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/units/quantity-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/units/quantity-0.1.0
- tag_uri: asdf://weldx.bam.de/weldx/tags/units/units-0.1.0
schema_uri: asdf://weldx.bam.de/weldx/schemas/units/units-0.1.0
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
%YAML 1.1
---
$schema: "http://stsci.edu/schemas/yaml-schema/draft-01"
id: "asdf://weldx.bam.de/weldx/schemas/core/geometry/spatial_data-0.1.1"

title: |
Schema for a point cloud.
description: |
This schema describes a collection of data points in 3d space.
CagtayFabry marked this conversation as resolved.
Show resolved Hide resolved

examples:
-
- A simple `SpatialData` with triangulation
- |
!<asdf://weldx.bam.de/weldx/tags/core/geometry/spatial_data-0.1.1>
coordinates: !core/ndarray-1.0.0
data:
- [0.0, 0.0, 0.0]
- [1.0, 0.0, 0.0]
- [1.0, 1.0, 0.0]
- [0.0, 1.0, 0.0]
datatype: float64
shape: [4, 3]
triangles: !core/ndarray-1.0.0
data:
- [0, 1, 2]
- [2, 3, 0]
datatype: uint32
shape: [2, 3]
-
- A `SpatialData` object with data in three dimensions
- |
!<asdf://weldx.bam.de/weldx/tags/core/geometry/spatial_data-0.1.1>
coordinates: !<asdf://weldx.bam.de/weldx/tags/core/data_array-0.1.0>
attributes: {}
coordinates:
- !<asdf://weldx.bam.de/weldx/tags/core/variable-0.1.0>
name: c
dimensions: [c]
dtype: <U1
data: !core/ndarray-1.0.0
data: [x, y, z]
datatype: [ucs4, 1]
shape: [3]
data: !<asdf://weldx.bam.de/weldx/tags/core/variable-0.1.0>
name: data
dimensions: [p, n, c]
dtype: <f8
data: !core/ndarray-1.0.0
data:
- - [0.0, 0.0, 0.0]
- [0.0, 1.0, 0.0]
- - [1.0, 0.0, 1.0]
- [0.0, 1.0, 1.0]
datatype: float64
shape: [2, 2, 3]

type: object
properties:
coordinates:
description: |
The coordinates of the data points.
oneOf:
- tag: "tag:stsci.edu:asdf/core/ndarray-1.*"
properties:
datatype:
type: string
enum: [float32, float64]
wx_shape: [(~), 3]
- tag: "asdf://weldx.bam.de/weldx/tags/core/data_array-0.1.*"
wx_shape: [..., 3]
Comment on lines +64 to +72
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing this gets me thinking (also in the context of the GerericSeries) that the wx_shape validator should probably be able to deal with dimension names when used in conjunction with a data_array schema. For example, instead of [..., 3] we could write [..., c=3]. The latter case would express "any number of dimensions with arbitrary shape, but c must have shape (3,)" I think this would simplify things a bit since we do not need to define a coordinate order to fulfill the requirement. Maybe we should give this a different name (wx_coordinate_shape?) to avoid confusions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, in general I think it would be a good addition to have a powerful validator for xarray structures

the overall structure and implementation probably needs some planning

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I create a new issue as reminder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes that never hurts 😉

attributes:
description: |
An arbitrary set of attributes. For example, normals, colors or measured point data can be stored using this
field. Each added attribute is an array with a number of data points equal to the number of points.
type: object
CagtayFabry marked this conversation as resolved.
Show resolved Hide resolved
triangles:
description: |
An array of index triplets that specify which points form a triangle
tag: "tag:stsci.edu:asdf/core/ndarray-1.*"
properties:
datatype:
type: string
enum: [uint32, uint64]
wx_shape: [(~), 3]

propertyOrder: [coordinates, attributes, triangles]
required: [coordinates]
flowStyle: block
...
9 changes: 9 additions & 0 deletions weldx/tags/core/data_array.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
"""Serialization for xarray.DataArray."""
from typing import List

from asdf.tagged import TaggedDict
from xarray import DataArray

import weldx.tags.core.common_types as ct
from weldx.asdf.types import WeldxConverter
from weldx.asdf.util import _get_instance_shape


class XarrayDataArrayConverter(WeldxConverter):
Expand Down Expand Up @@ -41,3 +45,8 @@ def from_yaml_tree(self, node: dict, tag: str, ctx):
# (but since it gets automatically derived if not set, we define it now.

return da

@staticmethod
def shape_from_tagged(node: TaggedDict) -> List[int]:
"""Calculate the shape from static tagged tree instance."""
return _get_instance_shape(node["data"]["data"])
CagtayFabry marked this conversation as resolved.
Show resolved Hide resolved
40 changes: 21 additions & 19 deletions weldx/tags/core/geometry/spatial_data.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
from copy import deepcopy
from copy import copy

import numpy as np

from weldx.asdf.util import dataclass_serialization_class
from weldx.asdf.types import WeldxConverter
from weldx.asdf.util import get_highest_tag_version
from weldx.geometry import SpatialData

__all__ = ["SpatialDataConverter"]


def _to_yaml_tree_mod(tree):
tree = deepcopy(tree)
tree["coordinates"] = tree["coordinates"].data
return tree
class SpatialDataConverter(WeldxConverter):
"""Converter for SpatialData."""

tags = ["asdf://weldx.bam.de/weldx/tags/core/geometry/spatial_data-0.1.*"]
types = [SpatialData]

def _from_yaml_tree_mod(tree):
if "coordinates" in tree:
tree["coordinates"] = np.asarray(tree["coordinates"])
return tree
def to_yaml_tree(self, obj: SpatialData, tag: str, ctx) -> dict:
"""Serialize into tree."""
tree = copy(obj.__dict__) # shallow copy so we dont change original object
if tree["coordinates"].ndim <= 2:
tree["coordinates"] = tree["coordinates"].values
return tree

def from_yaml_tree(self, node: dict, tag: str, ctx) -> SpatialData:
"""Reconstruct from yaml node."""
return SpatialData(**node)

SpatialDataConverter = dataclass_serialization_class(
class_type=SpatialData,
class_name="core/geometry/spatial_data",
version="0.1.0",
to_yaml_tree_mod=_to_yaml_tree_mod,
from_yaml_tree_mod=_from_yaml_tree_mod,
)
def select_tag(self, obj, tags, ctx) -> str:
"""Determine the output tag for serialization."""
return get_highest_tag_version(self.tags)
13 changes: 9 additions & 4 deletions weldx/tests/asdf_tests/test_asdf_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -720,23 +720,28 @@ class TestPointCloud:
@staticmethod
@pytest.mark.parametrize("copy_arrays", [True, False])
@pytest.mark.parametrize("lazy_load", [True, False])
def test_asdf_serialization(copy_arrays, lazy_load):
@pytest.mark.parametrize("reshape", [True, False])
def test_asdf_serialization(copy_arrays, lazy_load, reshape):
time = None
coordinates = [
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[1.0, 1.0, 0.0],
[0.0, 1.0, 0.0],
]

triangles = [[0, 1, 2], [2, 3, 0]]

pc = SpatialData(coordinates=coordinates, triangles=triangles)
if reshape:
coordinates = np.array(coordinates).reshape((2, 2, 3))
time = ["0s", "1s"]

pc = SpatialData(coordinates=coordinates, triangles=triangles, time=time)
tree = {"point_cloud": pc}
pc_file = write_read_buffer(
tree, open_kwargs={"copy_arrays": copy_arrays, "lazy_load": lazy_load}
)["point_cloud"]

assert np.all(pc_file.coordinates == pc.coordinates)
assert pc_file == pc


# --------------------------------------------------------------------------------------
Expand Down