# \<Node> Object Doc.

## 1. Attributes

The `Node` class forms the fundamental building block of the `Graph` and `NodeSet` structures. It's designed to represent individual words or expressions, holding various intrinsic properties and types of connections to other nodes.

```python
def __init__(self, lang: str, type_: str, name: str, lemma: str,
                 synset0: list = None, synset1: list = None, synset2: list = None,
                 semset0: list = None, semset1: list = None, semset2: list = None,
                 favorite: bool = False,
                 examples: list = None) -> None:
        
        self.graph = None

        # 1. Hash

        self.lang, self.type, self.name = lang, type_, name # str
        self.lemma = lemma if lemma is not None else "NA" # str ("NA" by default)
        
        # 2. Connections

        self.synset0 = synset0 if synset0 else [] # list
        self.synset1 = synset1 if synset1 else [] # list
        self.synset2 = synset2 if synset2 else [] # list
        self.semset0 = semset0 if semset0 else [] # list
        self.semset1 = semset1 if semset1 else [] # list
        self.semset2 = semset2 if semset2 else [] # list
        
        # 3. Additional   
            
        self.favorite = favorite == True # bool (False by default)
        self.examples = examples if examples is not None else [] # list
```

{% tabs %}
{% tab title="Hash" %}
When nodes are initially generated, they possess a set of four essential core string hash attributes. These attributes have been carefully crafted with the primary purpose of aiding in the differentiation of each node from the extensive array of other nodes within the system.

* `lang` : language for the `name` , either `es` (spanish), `en` (englis), `fr` (french), etc.
* `type` : type of linguistic ressource
  * `n` : noun
  * `w` : wiki
  * `j` : adjective
  * `v` : verb
  * `b` : adverb
  * `c` : textual connector
  * `r` : replica
  * `q` : quote or great sentence
  * ...
* `name` : the Node entity itself.
* `lemma` : little explanation about the meaning or interpretation the `name` can have.&#x20;

Be mindful that "lemma," despite its inclusion in the hash, is not classified as a core attribute. This terminology will hold relevance in later discussions. Core attributes are the ones responsible for defining homologous words, whereas the meaning or interpretations, denoted by the lemma, are disregarded in this context.
{% endtab %}

{% tab title="Connections" %}
Connections are compilations of attached nodes with which the Node forms connections, encompassing both linguistic relations through synonyms and semantic associations.

* Synset
  * `synset0` : this category encompasses synonyms that have a broader sense, allowing them to encompass a wider range of meanings. These synonyms may be used interchangeably in certain contexts where a more general term is appropriate. For instance, in the context of the word "_car_," `synset0` may include "_vehicle_," which captures the broader concept of various modes of transport.
  * `synset1` : within this category, we find synonyms that are exactly interchangeable. These synonyms can be seamlessly substituted for one another without any significant change in meaning. For example, "_car_" and "_automobile_" are synonyms within `synset1`, as they represent the same concept with no nuanced distinctions.
  * `synset2` : the opposite of `synset0`.
* Semset
  * `semset0` : encompasses words that serve as either the causal agents or the contextual environments, whether spatial or thematic, for the word they accompany. These words lay the groundwork, either by directly influencing or by providing the thematic backdrop within which related concepts find their place, even when they are not synonyms.
  * `semset1` : includes concepts that have a deep and natural connection with the node they are linked to. This connection is strong and comes naturally, not because of a cause-and-effect relationship or a specific sequence of events. These concepts are closely tied together, and their bond goes beyond simple categorization.
  * `semset2` : the opposite of `semset0`.
{% endtab %}

{% tab title="Additional" %}
In addition to the core attributes, there are two supplementary attributes that contribute to the comprehensive characterization of nodes.

* `favorite` : this attribute provides insight into the personal preference or significance of the entry within the broader context, reflecting the subjective importance assigned to it by the system administrator.
* `examples` : enriches the entry by offering a curated list of real-world use cases or instances where the concept or word associated with the node is employed, shedding light on the practical utility and contextual relevance of the entry.
{% endtab %}
{% endtabs %}

## 2. Retrieving Neighbors

### 2.1. The 'get\_neighbors' method

The `get_neighbors(*fielding)` method retrieves a set of neighboring nodes.

```python
>> n.get_neighbors() # -> <NodeSet>
NodeSet(size=491) # all neighbors
```

We can also ask only for a specific subset of edges. Thanks to the `parse_field` auxiliar function, the forms for this argument are very versatile.&#x20;

The `get_neighbors()` function supports a variety of arguments to specify neighbors of an object `n`. Without arguments, it retrieves all neighbors. String arguments like 'synset' or 'y' define global scopes, either long or short, while 'synset0' or 'y0' target single entities. A list allows mixing types for granular control. Binary strings like '110000' enable precise selection through bit patterns, indicating specific neighbor categories to include.

```
>> ndst = n.get_neighbors() # all

# As string
>> ndst = n.get_neighbors('synset') # global-long
>> ndst = n.get_neighbors('y') # global-short
>> ndst = n.get_neighbors('synset0') # single-long
>> ndst = n.get_neighbors('y0') # single-short

# As list (supports mixed)
>> ndst = n.get_neighbors(['y0', 'synset0', 'semset', ...]) # mixed

# As binary string
>> ndst = n.get_neighbors('110000')
>> ndst = n.get_neighbors('11')
```

For enhanced flexibility, the method accommodates parameter input versatility through its utilization of \*args under the hood, enabling adaptable argument processing, provided they adhere to valid string formats or lists thereof.

{% code title="Theoretical Example " %}
```
>> ndst = n.get_neighbors('e',['y0, 'y1'])
```
{% endcode %}

If a binary string were to be inserted, it is preferential over other kinds of args.

<details>

<summary>Weights Inspection</summary>

To quickly retrieve the field sizes, use `get_sizes()`.

```
>> node.get_sizes()
(0, 24, 0, 0, 31, 0)
```

</details>

### 2.2. Equivalent functions&#x20;

The `Node` class provides the methods  `get_synset(*i)`, `get_semset(*i)` to retrieve connected nodes based on different relationship types. This methods do not provide any functionality beyond `get_neighbors` , and their existance is purely suplementary (although they are used within `get_neighbors` algorithm).

They generate a <mark style="color:blue;">single united</mark> `NodeSet` object as output.

```
n.get_synset() # (selects all idxs (0,1,2)) -> <NodeSet>
n.get_semset() # (selects all idxs (0,1,2)) -> <NodeSet>
```

And any arrange of arguments is permitted.

```
n.get_synset(0),     n.get_semset(0)
n.get_synset(2,0),   n.get_semset(2,0)
n.get_synset(0,1,2), n.get_semset(0,1,2)
```

## 3. Editing Properties

The `edit` method allows for the modification of node attributes after initialization. This method accepts keyword arguments corresponding to the node's attributes.

```python
n.edit(lang='new_lang')
n.edit(type='new_type')
n.edit(name='new_name')
n.edit(lemma='new_lemma')
```

## 4. Other functions

The functions listed below serve as valuable tools for various aspects of the codebase, including other components within the SKComponents module, prototyping tasks, the Command-Line Interface (CLI), or the implementation of Graph Search Algorithms.

They have been grouped together in this section due to their straightforward nature and ease of use, making them versatile and suitable for a wide range of purposes.

<details>

<summary>.identify(only_core=False)</summary>

Shortcut to generate a tuple containing hash attributes, this enhancing their accessibility.

```python
>> print(node.identify())
(lang, type_, name, lemma)

>> print(node.identify(only_core=True))
(lang, type_, name)
```

</details>

<details>

<summary>.is_connected(node)</summary>

Checks if the node is connected in any way to another one (that is, in any of its fields).

```python
>> print(n1.is_connected(n2))
True
```

</details>

<details>

<summary>.is_homologous(node)</summary>

Checks if two nodes are homologous (that is, they share hash attributes besides lemma).

```python
>> print(n1.is_homologue(n2))
True
```

</details>

<details>

<summary>.assess_similarity(node)</summary>

Checks the syntactic similarity between names (basing on the "difflib" library).

```
>> print(n1.assess_similarity(n2))
0.05155
```

</details>

## 5. \_\_repr\_\_

The `__repr__` method is designed to generate a string representation of the node object, and its output is dynamically influenced by the current representation flags stored at `_FLAGS`. To enhance flexibility, several methods have been implemented to configure these flags: `compress`, `expand`, and `toggle`.

However, it's important to note that these configurational options primarily cater to developers and are most useful when directly working with the components of the system. This level of object visualization is not intended for end-users, as the Command-Line Interface (CLI) serves as the final layer for interaction with the database. Therefore, these configuration methods are best suited for developer-centric tasks, aiding in debugging, testing, and fine-tuning the system's behavior.

```
n = G.random()
```

Created a node, there's different ways to represent it in the terminal.

```python
# Expansion & Compression
Node.expand(); n  # Displaying the number of connections and all properties
>>> Node(es-n:Apoyo())[synset0=0, semset0=0, synset1=81, semset1=78, synset2=0, semset2=0, examples=1]
Node.compress(); n  # Hiding connections
>>> Node(es-n:Apoyo()) 
```

We can also hide properties of the node.

```python
# Focalised Operations
Node.compress('lang', 'lemma'); n
>>> Node(n:Apoyo)
```

Work with batches of connections.

```python
# Focalised Operations on Edges
Node.expand('synset'); n
>>> Node(es-v:Irritar())[synset0=0, synset1=47, synset2=0]
Node.compress('synset0'); n
>>> Node(es-v:Irritar())[synset1=47, synset2=0]
```

And even simplify the connections visuals.

{% code fullWidth="false" %}
```python
# Toggling labels
Node.toggle_labels() # or Node.toggle_labels(0) / Node.toggle_labels(1)
n
>>> Node(es-v:Irritar())[47, 0]
```
{% endcode %}

And everything can be nested.

```python
Node.compress().expand('synset').compress('synset2', 'synset0').toggle_labels()
```

The data about configuration representation is stored in a binary variable called `_repr_flags`.

***
