diff --git a/libs/shared/lib/components/DesignGuides/styleGuide.mdx b/libs/shared/lib/components/DesignGuides/styleGuide.mdx
index 00c29bc5a1683ad01e93e52e651dae0bb23971bb..a7e82a621d89cdcbff0378515b42343a5d69e227 100644
--- a/libs/shared/lib/components/DesignGuides/styleGuide.mdx
+++ b/libs/shared/lib/components/DesignGuides/styleGuide.mdx
@@ -645,7 +645,7 @@ GraphPolaris uses [Material UI](https://mui.com/material-ui/material-icons/) thr
 </div>
 
 ```jsx
-import Icon from '@graphpolaris/shared/lib/components/icon';
+import { Icon } from '@graphpolaris/shared/lib/components/icon';
 <Icon name="ArrowBack" size={32} />;
 ```
 
diff --git a/libs/shared/lib/components/buttons/Button.tsx b/libs/shared/lib/components/buttons/Button.tsx
index f4e5c04dd148f17fc07899461b50a14f150a2d88..f607db885c5faf598e0fcfc20f3f0922440ada1b 100644
--- a/libs/shared/lib/components/buttons/Button.tsx
+++ b/libs/shared/lib/components/buttons/Button.tsx
@@ -1,6 +1,6 @@
 import React, { ReactElement, ReactPropTypes, useMemo } from 'react';
 import styles from './buttons.module.scss';
-import Icon, { Sizes } from '../icon';
+import { Icon, Sizes } from '../icon';
 import { forwardRef } from 'react';
 
 type ButtonProps = {
diff --git a/libs/shared/lib/components/dropdowns/index.tsx b/libs/shared/lib/components/dropdowns/index.tsx
index be780115dfe688aaa70531a18a15341176fb18a6..8fb237c6e7ff776987d8b56aaa33b89243d44cf4 100644
--- a/libs/shared/lib/components/dropdowns/index.tsx
+++ b/libs/shared/lib/components/dropdowns/index.tsx
@@ -1,6 +1,6 @@
 import React, { useState, useEffect, useRef, ReactNode } from 'react';
 import styles from './dropdowns.module.scss';
-import Icon from '../icon';
+import { Icon } from '../icon';
 import { ArrowDropDown } from '@mui/icons-material';
 import { PopoverContent, PopoverTrigger, Popover, PopoverOptions } from '../layout/Popover';
 
@@ -45,7 +45,7 @@ export function DropdownTrigger({
 
   const inner = children || (
     <div
-      className={`inline-flex w-full truncate justify-between items-center gap-x-1.5 ${variantClass} ${textSizeClass} ${paddingClass} text-secondary-900 shadow-sm hover:bg-secondary-50 disabled:bg-secondary-100 disabled:cursor-not-allowed disabled:text-secondary-400 pl-1 truncate${className ? ` ${className}` : ''}`}
+      className={`inline-flex w-full truncate justify-between items-center gap-x-1.5 ${variantClass} ${textSizeClass} ${paddingClass} text-secondary-900 shadow-sm hover:bg-secondary-50 disabled:bg-secondary-100 disabled:cursor-not-allowed disabled:text-secondary-400 pl-1 truncate cursor-pointer${className ? ` ${className}` : ''}`}
     >
       <span className={`text-${size}`}>{title}</span>
       <Icon component={<ArrowDropDown />} size={16} />
@@ -70,6 +70,7 @@ type DropdownItemContainerProps = {
 };
 
 export const DropdownItemContainer = React.forwardRef<HTMLDivElement, DropdownItemContainerProps>(({ children, className }, ref) => {
+  if (!children || !React.Children.count(children)) return null;
   return (
     <PopoverContent
       ref={ref}
@@ -91,9 +92,10 @@ type DropdownItemProps = {
   onClick?: (value: string) => void;
   submenu?: React.ReactNode;
   selected?: boolean;
+  children?: ReactNode;
 };
 
-export function DropdownItem({ value, disabled, className, onClick, submenu, selected }: DropdownItemProps) {
+export function DropdownItem({ value, disabled, className, onClick, submenu, selected, children }: DropdownItemProps) {
   const itemRef = useRef(null);
   const submenuRef = useRef(null);
   const [isSubmenuOpen, setIsSubmenuOpen] = useState(false);
@@ -109,7 +111,7 @@ export function DropdownItem({ value, disabled, className, onClick, submenu, sel
       onMouseEnter={() => setIsSubmenuOpen(true)}
       onMouseLeave={() => setIsSubmenuOpen(false)}
     >
-      { value }
+      {value}
       {submenu && isSubmenuOpen && <DropdownSubmenuContainer ref={submenuRef}>{submenu}</DropdownSubmenuContainer>}
     </li>
   );
diff --git a/libs/shared/lib/components/icon/icon.stories.tsx b/libs/shared/lib/components/icon/icon.stories.tsx
index b57f7c09eb64b72801e5339ffbe0a3227294fe79..cad42fd6e227cbf69997acff02fb34b11bad6f57 100644
--- a/libs/shared/lib/components/icon/icon.stories.tsx
+++ b/libs/shared/lib/components/icon/icon.stories.tsx
@@ -1,5 +1,5 @@
 import { StoryObj, Meta } from '@storybook/react';
-import Icon from '../icon';
+import { Icon } from '../icon';
 import { ArrowBack, DeleteOutline, KeyboardArrowLeft, Settings } from '@mui/icons-material';
 
 const Component: Meta<typeof Icon> = {
diff --git a/libs/shared/lib/components/icon/index.tsx b/libs/shared/lib/components/icon/index.tsx
index 6ea37b5712c9645c01f2ef9c982f5a1b6e8fd93c..4f2695cb556abfa1d7749e39146bcd663e1e8563 100644
--- a/libs/shared/lib/components/icon/index.tsx
+++ b/libs/shared/lib/components/icon/index.tsx
@@ -5,9 +5,10 @@ export type Sizes = 12 | 14 | 16 | 20 | 24 | 28 | 32 | 40;
 export type IconProps = SVGProps<SVGSVGElement> & {
   component: ReactElement<any>;
   size?: Sizes;
+  color?: string;
 };
 
-export const Icon: React.FC<IconProps> = ({ component, size = 24, ...props }) => {
+export const Icon: React.FC<IconProps> = ({ component, size = 24, color, ...props }) => {
   if (!component) {
     console.error(`No icon found`);
     return <div></div>;
@@ -15,5 +16,3 @@ export const Icon: React.FC<IconProps> = ({ component, size = 24, ...props }) =>
 
   return React.cloneElement(component, { style: { fontSize: size }, width: size, height: size, ...props });
 };
-
-export default Icon;
diff --git a/libs/shared/lib/components/icon/overview.mdx b/libs/shared/lib/components/icon/overview.mdx
index dc7299e9e2fd0769da3a27e3f6f5bdac33a22adc..d03354ff28ea7465d3ffb386b366ca3f3f2cbf4f 100644
--- a/libs/shared/lib/components/icon/overview.mdx
+++ b/libs/shared/lib/components/icon/overview.mdx
@@ -1,6 +1,6 @@
 import { Canvas, Meta, Story } from '@storybook/blocks';
 import * as IconStories from './icon.stories';
-import Icon from '.';
+import { Icon } from '.';
 
 <Meta title="Components/Icon" component={Icon} />
 
diff --git a/libs/shared/lib/components/info/index.tsx b/libs/shared/lib/components/info/index.tsx
index 6bb08d1234fbf3a2b9b37cb6b976903daf62dc45..20b158aae418700b04bc87421f476538fa52af16 100644
--- a/libs/shared/lib/components/info/index.tsx
+++ b/libs/shared/lib/components/info/index.tsx
@@ -1,5 +1,5 @@
 import React from 'react';
-import Icon from '../icon';
+import { Icon } from '../icon';
 import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';
 import { InfoOutlined } from '@mui/icons-material';
 
diff --git a/libs/shared/lib/components/selectors/entityPillSelector.stories.tsx b/libs/shared/lib/components/selectors/entityPillSelector.stories.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..931e1410a4c92ffc837e465792add76bb58ac05d
--- /dev/null
+++ b/libs/shared/lib/components/selectors/entityPillSelector.stories.tsx
@@ -0,0 +1,19 @@
+import React, { useState } from 'react';
+import type { Meta, StoryObj } from '@storybook/react';
+import EntityPillSelector, { EntityPillSelectorProps } from './entityPillSelector';
+
+const metaPillDropdown: Meta<typeof EntityPillSelector> = {
+  component: EntityPillSelector,
+  title: 'Components/Selectors/Entity',
+  decorators: [(story) => <div className="flex items-center justify-center m-11 p-11">{story()}</div>],
+};
+
+export default metaPillDropdown;
+
+type Story = StoryObj<typeof EntityPillSelector>;
+
+export const entity: Story = {
+  args: {
+    dropdownNodes: ['kamerleden', 'commissies'],
+  },
+};
diff --git a/libs/shared/lib/components/selectors/entityPillSelector.tsx b/libs/shared/lib/components/selectors/entityPillSelector.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..998294d8837c8421200919d810ee826c11876580
--- /dev/null
+++ b/libs/shared/lib/components/selectors/entityPillSelector.tsx
@@ -0,0 +1,56 @@
+import React, { useRef, useState } from 'react';
+import { Button } from '../buttons';
+import { ArrowDropDown } from '@mui/icons-material';
+import { EntityPill } from '@graphpolaris/shared/lib/components/pills/Pill';
+import { DropdownContainer, DropdownItemContainer, DropdownTrigger, DropdownItem } from '../dropdowns';
+
+export type EntityPillSelectorProps = {
+  selectedNode?: string;
+  dropdownNodes: string[];
+  onSelectOption: (option: string) => void;
+};
+
+export function EntityPillSelector({ dropdownNodes, onSelectOption, selectedNode }: EntityPillSelectorProps) {
+  const [isCollapsed, setIsCollapsed] = useState(true);
+  // const [initialNamePill, setInitialNamePill] = useState('Choose a node:');
+
+  const handleButtonClick = () => {
+    setIsCollapsed(!isCollapsed);
+  };
+
+  const handleOptionClick = (option: string) => {
+    setIsCollapsed(true);
+    onSelectOption(option);
+  };
+
+  return (
+    <DropdownContainer placement="bottom">
+      <DropdownTrigger title={selectedNode || 'Choose a node:'} size="sm">
+        <EntityPill
+          className="cursor-pointer"
+          title={
+            <div className="flex flex-row items-center justify-between pointer-events-none">
+              <span>{selectedNode || 'Choose a node:'}</span>
+              <Button variantType="secondary" variant="ghost" size="xs" iconComponent={<ArrowDropDown />} onClick={handleButtonClick} />
+            </div>
+          }
+        />
+      </DropdownTrigger>
+      <DropdownItemContainer>
+        {dropdownNodes
+          .map((node, index) => (
+            <DropdownItem
+              className="my-0 cursor-pointer"
+              selected={selectedNode === node}
+              onClick={() => handleOptionClick(node)}
+              key={'entity_' + index + '-' + node}
+              value={node}
+            >
+              <EntityPill title={node} />
+            </DropdownItem>
+          ))
+          .filter((node) => node.props.value !== selectedNode)}
+      </DropdownItemContainer>
+    </DropdownContainer>
+  );
+}
diff --git a/libs/shared/lib/components/selectors/index.ts b/libs/shared/lib/components/selectors/index.ts
index 14964560cc76dc9467199fcebe6dd68fa21064b0..04c48ea22477b6d7a78bf5124d1bd01c69f1037a 100644
--- a/libs/shared/lib/components/selectors/index.ts
+++ b/libs/shared/lib/components/selectors/index.ts
@@ -3,6 +3,7 @@ import Shape from './shape';
 import Size from './size';
 import Axis from './axis';
 import Opacity from './opacity';
+import EntityPill from './entityPillSelector';
 
 export const EncodingSelector = {
   Color: Color,
@@ -10,6 +11,7 @@ export const EncodingSelector = {
   Size: Size,
   Axis: Axis,
   Opacity: Opacity,
+  EntityPill: EntityPill,
 };
 
 // Inspiration: https://uwdata.github.io/visualization-curriculum/altair_marks_encoding.html
diff --git a/libs/shared/lib/data-access/store/graphQueryResultSlice.ts b/libs/shared/lib/data-access/store/graphQueryResultSlice.ts
index 48968c579985a1812012773a260111f91961f944..95e2f6bb2afe89609e0f5ab1a9f1ef93aec5eae1 100755
--- a/libs/shared/lib/data-access/store/graphQueryResultSlice.ts
+++ b/libs/shared/lib/data-access/store/graphQueryResultSlice.ts
@@ -49,7 +49,7 @@ export type Edge = {
 
 // Define a type for the slice state
 export type GraphQueryResult = {
-  metaData: GraphMetadata;
+  metaData?: GraphMetadata;
   nodes: Node[];
   edges: Edge[];
   queryingBackend: boolean;
@@ -57,7 +57,7 @@ export type GraphQueryResult = {
 
 // Define the initial state using that type
 export const initialState: GraphQueryResult = {
-  metaData: { nodes: { labels: [], types: {} }, edges: { labels: [], types: {} } },
+  metaData: undefined,
   nodes: [],
   edges: [],
   queryingBackend: false,
@@ -139,14 +139,14 @@ export const graphQueryResultSlice = createSlice({
       const { metaData, nodes, edges } = graphQueryBackend2graphQuery(payload);
 
       // Assign new state
-      state.metaData = extractStatistics(metaData);
+      state.metaData = metaData;
       state.nodes = nodes;
       state.edges = edges;
       state.queryingBackend = false;
     },
     resetGraphQueryResults: (state) => {
       // Assign new state
-      state.metaData = { nodes: { labels: [], types: {} }, edges: { labels: [], types: {} } };
+      state.metaData = undefined;
       state.nodes = [];
       state.edges = [];
       state.queryingBackend = false;
diff --git a/libs/shared/lib/data-access/store/hooks.ts b/libs/shared/lib/data-access/store/hooks.ts
index 8e52b38f41aa88622b10f0b62be23cffabccee24..9f1ab6ce9a0d0cb1ad0b4e1019d41c6c1633022d 100644
--- a/libs/shared/lib/data-access/store/hooks.ts
+++ b/libs/shared/lib/data-access/store/hooks.ts
@@ -39,7 +39,7 @@ export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
 
 /** Gives the graphQueryResult from the store */
 export const useGraphQueryResult: () => GraphQueryResult = () => useAppSelector(selectGraphQueryResult);
-export const useGraphQueryResultMeta: () => GraphMetadata = () => useAppSelector(selectGraphQueryResultMetaData);
+export const useGraphQueryResultMeta: () => GraphMetadata | undefined = () => useAppSelector(selectGraphQueryResultMetaData);
 
 // Gives the schema
 export const useSchemaGraph: () => SchemaGraph = () => useAppSelector(schemaGraph);
diff --git a/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx b/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx
index 85c84843a5cfcf552dda97d5bd8d713dbaebd8ef..07caaabbf76bed3384b3992afe6a4a15f0102242 100644
--- a/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx
+++ b/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx
@@ -2,7 +2,7 @@ import { useMemo, ReactElement, useState, useContext } from 'react';
 import { NodeAttribute, QueryGraphEdges, SchemaReactflowEntityNode, handleDataFromReactflowToDataId, toHandleId } from '../../model';
 import { Handle, Position, useUpdateNodeInternals } from 'reactflow';
 import { Abc, CalendarToday, Map, Numbers, Place, QuestionMarkOutlined } from '@mui/icons-material';
-import Icon from '@graphpolaris/shared/lib/components/icon';
+import { Icon } from '@graphpolaris/shared/lib/components/icon';
 import { PillHandle } from '@graphpolaris/shared/lib/components/pills/PillHandle';
 import { pillDropdownPadding } from '@graphpolaris/shared/lib/components/pills/pill.const';
 import { Button, TextInput, useAppDispatch, useQuerybuilderAttributesShown } from '../../..';
diff --git a/libs/shared/lib/vis/components/VisualizationPanel.tsx b/libs/shared/lib/vis/components/VisualizationPanel.tsx
index c7446a261d91974ff5c412ad92eb9a04314716cc..881dafbb61a549b4a030e4bd5cb4e624670ef15c 100644
--- a/libs/shared/lib/vis/components/VisualizationPanel.tsx
+++ b/libs/shared/lib/vis/components/VisualizationPanel.tsx
@@ -108,7 +108,8 @@ export const VisualizationPanel = ({ fullSize }: { fullSize: () => void }) => {
               {!!viz &&
                 activeVisualizationIndex !== -1 &&
                 openVisualizationArray?.[activeVisualizationIndex] &&
-                viz.id === openVisualizationArray[activeVisualizationIndex].id && (
+                viz.id === openVisualizationArray[activeVisualizationIndex].id &&
+                graphMetadata && (
                   <viz.component
                     data={graphQueryResult}
                     schema={schema}
diff --git a/libs/shared/lib/vis/components/config/VisualizationSettings.tsx b/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
index ddfe63d150694b40601cb23bf78dc63240cee40b..ad46863543ba051af8d2e042d47059c3e4ce0ab7 100644
--- a/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
+++ b/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
@@ -102,7 +102,7 @@ export function VisualizationSettings({}: Props) {
           label="Name"
           inline
         />
-        {activeVisualization && (
+        {activeVisualization && graphMetadata && (
           <>
             <SettingsHeader name="Visualization Settings" />
             <Suspense fallback={<div>Loading...</div>}>
diff --git a/libs/shared/lib/vis/components/config/panel.tsx b/libs/shared/lib/vis/components/config/panel.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/libs/shared/lib/vis/visualizations/paohvis/components/RowLabels.tsx b/libs/shared/lib/vis/visualizations/paohvis/components/RowLabels.tsx
index 425472216e37bd60ab2cb374ef403cb21898f595..096883c8feba637bff53064ae29f5f314f7129e0 100644
--- a/libs/shared/lib/vis/visualizations/paohvis/components/RowLabels.tsx
+++ b/libs/shared/lib/vis/visualizations/paohvis/components/RowLabels.tsx
@@ -23,7 +23,7 @@ export const RowLabels = ({
   rowHeight,
   yOffset,
   rowLabelColumnWidth,
-  classTopTextColumns: classTopTextColums,
+  classTopTextColumns,
   marginText,
   sortState,
   headerState,
@@ -100,7 +100,7 @@ export const RowLabels = ({
                       fill={indexRows % 2 === 0 ? 'hsl(var(--clr-sec--50))' : 'hsl(var(--clr-sec--0))'}
                       strokeWidth={0}
                     ></rect>
-                    <text x={row.width * marginText} y={rowHeight / 2} dy="0" dominantBaseline="middle" className={classTopTextColums}>
+                    <text x={row.width * marginText} y={rowHeight / 2} dy="0" dominantBaseline="middle" className={classTopTextColumns}>
                       {row.data[indexRows]}
                     </text>
                   </g>
@@ -153,7 +153,7 @@ export const RowLabels = ({
                 }}
               >
                 <rect width={row.width} height={rowHeight} fill={'hsl(var(--clr-sec--200))'} opacity={1.0} strokeWidth={0}></rect>
-                <text x={marginText * row.width} y={0.5 * rowHeight} dy="0" dominantBaseline="middle" className={classTopTextColums}>
+                <text x={marginText * row.width} y={0.5 * rowHeight} dy="0" dominantBaseline="middle" className={classTopTextColumns}>
                   {row.header}
                 </text>
                 {iconComponents[indexRows] && isHovered && (
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/Overview.mdx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/Overview.mdx
new file mode 100644
index 0000000000000000000000000000000000000000..2ae6f0b46d5422844979a533227b488a67442585
--- /dev/null
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/Overview.mdx
@@ -0,0 +1,21 @@
+import { Meta, Unstyled } from '@storybook/blocks';
+
+<Meta title="Visualizations/Implementation" />
+
+# Variables
+
+## Related to Scatterplots
+
+- appState: used to render the scatterplots. Contains dataRegions: data that builds the scatterplots, and scatterplot: what renders the scatterplot
+
+- idBrush: used to keep track of the brush idBrush
+
+- computedData: build when the scatterplot finish the jitter. Only two positions:
+  --region1 for R0, only the first scatterplot
+  --region2 for RX, when a scatterplot finish the jitter process it saves the result here
+
+## Related to Edges
+
+- edgeState: used to render the scatterplots. Eg. contains positions of the data points in the scatterplot
+- informationEdges contains edge labels and IDs from the edges.
+- arrayConnections contains IDs from the edges.
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/ConfigPanel.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/ConfigPanel.tsx
deleted file mode 100644
index 3aadfdeeef1292248c889e421d1043888a1de9e1..0000000000000000000000000000000000000000
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/ConfigPanel.tsx
+++ /dev/null
@@ -1,242 +0,0 @@
-import React, { useState, useEffect } from 'react';
-import { Node, DataConfig, AugmentedNodeAttributes } from './types';
-import { Button } from '../../../../components/buttons';
-
-function getUniqueValues(arr: any[]): any[] {
-  return [...new Set(arr)];
-}
-
-interface ConfigPanelProps {
-  data: AugmentedNodeAttributes[];
-  onUpdateData: (data: DataConfig) => void;
-}
-
-const ConfigPanel: React.FC<ConfigPanelProps> = ({ data, onUpdateData }) => {
-  const [state, setState] = useState<{
-    entityVertical: string;
-    attributeEntity: string;
-    attributeValueSelected: string;
-    orderNameXaxis: string;
-    orderNameYaxis: string;
-    isButtonEnabled: boolean;
-  }>({
-    entityVertical: '',
-    attributeEntity: '',
-    attributeValueSelected: '',
-    orderNameXaxis: '',
-    orderNameYaxis: '',
-    isButtonEnabled: true,
-  });
-
-  const nodeLabels: string[] = data.map((node: any) => node.label);
-
-  const uniqueNodeLabels = getUniqueValues(nodeLabels);
-
-  const entityOptions = [...uniqueNodeLabels].map((value, index) => (
-    <option key={`option${index}`} value={value}>
-      {value}
-    </option>
-  ));
-
-  // Extract unique attributeEntity values from the entire data array
-  const [attributeEntityMenuItems, setattributeEntityMenuItems] = useState<string[]>([]);
-  // Filter the data based on the selected entity (label)
-  const [filteredData, setFilteredData] = useState<AugmentedNodeAttributes[]>([]);
-  const [attributeOptions, setAttributeOptions] = useState<any[]>([]);
-
-  useEffect(() => {
-    if (state.entityVertical) {
-      const selectedEntity = state.entityVertical;
-      // Filter the data based on the selected entity (label)
-      const filteredData: AugmentedNodeAttributes[] = data.filter((item) => item.label === selectedEntity);
-
-      setFilteredData(filteredData);
-    } else {
-      setFilteredData([]);
-    }
-  }, [state.entityVertical, data]);
-
-  useEffect(() => {
-    if (filteredData.length > 0) {
-      const attributes: object = filteredData[0].attributes;
-
-      if (attributes) {
-        const keys = Object.keys(attributes);
-        setattributeEntityMenuItems(keys);
-      }
-    } else {
-      setattributeEntityMenuItems([]); // Clear the attributeEntityMenuItems when there's no filtered data
-    }
-  }, [filteredData]);
-
-  useEffect(() => {
-    // Update attributeOptions when attributeEntity changes
-    if (filteredData.length > 0) {
-      const filteredAAttributes: any[] = (filteredData as AugmentedNodeAttributes[]).map((item: AugmentedNodeAttributes) => {
-        const attributeValueSelected = item.attributes[state.attributeEntity];
-
-        if (Array.isArray(attributeValueSelected)) {
-          if (attributeValueSelected.length === 1) {
-            return attributeValueSelected[0];
-          } else {
-            return attributeValueSelected.join('-');
-          }
-        } else if (typeof attributeValueSelected === 'string' || typeof attributeValueSelected === 'number') {
-          return attributeValueSelected;
-        } else {
-          return null; // Return null for other types
-        }
-      });
-
-      if (filteredAAttributes) {
-        // Extract unique values from the relation's attributes
-        const uniqueValues = Array.from(new Set(filteredAAttributes));
-        const firstElement = uniqueValues[0];
-
-        if (typeof firstElement === 'number') {
-          // Sort numbers in descending order
-          const sortedValues = uniqueValues.slice().sort((a, b) => a - b);
-
-          setAttributeOptions(sortedValues);
-        } else if (typeof firstElement === 'string') {
-          // Sort strings in descending order
-          // localCompare is useful to take into account local language consideration.
-          // but breaks for comparing an URL
-          const sortedValues = uniqueValues.slice().sort((a, b) => a - b);
-          setAttributeOptions(sortedValues);
-        } else {
-          // Handle other data types as needed
-          setAttributeOptions(uniqueValues); // Clear attributeOptions for unsupported data types
-        }
-      }
-    } else {
-      setAttributeOptions([]); // Clear attributeOptions when there's no filtered data
-    }
-  }, [state.attributeEntity, filteredData]);
-
-  const onClickMakeButton = () => {
-    // Retrieve the selected values
-
-    const { entityVertical, attributeEntity, attributeValueSelected, orderNameXaxis, orderNameYaxis, isButtonEnabled } = state;
-    const isAxisSelected = orderNameXaxis !== '' || orderNameYaxis !== '';
-
-    // Call the callback to send the data to the parent component (VisSemanticSubstrates)
-    if (isAxisSelected) {
-      onUpdateData({
-        entityVertical,
-        attributeEntity,
-        attributeValueSelected,
-        orderNameXAxis: orderNameXaxis,
-        orderNameYAxis: orderNameYaxis,
-        isButtonEnabled,
-      });
-    }
-  };
-
-  return (
-    <div className="nav card w-full">
-      <div className="card-body flex flex-row overflow-y-auto max-w-[60vw] self-center items-center">
-        <div className="select-container">
-          <label className="select-label">Entity:</label>
-          <select
-            className="select"
-            id="standard-select-entity"
-            value={state.entityVertical}
-            onChange={(e) => setState({ ...state, entityVertical: e.target.value })}
-          >
-            <option value="" disabled>
-              Select an entity
-            </option>
-            {entityOptions}
-          </select>
-        </div>
-
-        <div className="select-container">
-          <label className="select-label">Attribute:</label>
-          <select
-            className={`select ${attributeEntityMenuItems.length === 0 ? 'select-disabled' : ''}`}
-            id="standard-select-relation"
-            value={state.attributeEntity}
-            onChange={(e) => setState({ ...state, attributeEntity: e.target.value, attributeValueSelected: '', orderNameXaxis: '' })}
-          >
-            <option value="" disabled>
-              Select a relation
-            </option>
-            {attributeEntityMenuItems.map((value, index) => (
-              <option key={`option${index}`} value={value}>
-                {value}
-              </option>
-            ))}
-          </select>
-        </div>
-
-        <div className="select-container">
-          <label className="select-label">Selected Attribute:</label>
-          <select
-            className={`select ${attributeOptions.length === 0 ? 'select-disabled' : ''}`}
-            id="standard-select-attribute"
-            value={state.attributeValueSelected}
-            onChange={(e) => setState({ ...state, attributeValueSelected: e.target.value, orderNameXaxis: '', orderNameYaxis: '' })}
-          >
-            <option value="" disabled>
-              Select an attribute
-            </option>
-            {attributeOptions.map((value, index) => (
-              <option key={`option${index}`} value={value}>
-                {value}
-              </option>
-            ))}
-          </select>
-        </div>
-
-        <div className="select-container">
-          <label className="select-label">X-axis:</label>
-          <select
-            className={`select ${attributeEntityMenuItems.length === 0 ? 'select-disabled' : ''}`}
-            id="standard-select-relation"
-            value={state.orderNameXaxis}
-            onChange={(e) => setState({ ...state, orderNameXaxis: e.target.value })}
-          >
-            <option value="" disabled>
-              Select a x axis
-            </option>
-            {attributeEntityMenuItems.map((value, index) => (
-              <option key={`option${index}`} value={value}>
-                {value}
-              </option>
-            ))}
-          </select>
-        </div>
-
-        <div className="select-container">
-          <label className="select-label">Y-axis:</label>
-          <select
-            className={`select ${attributeEntityMenuItems.length === 0 ? 'select-disabled' : ''}`}
-            id="standard-select-relation"
-            value={state.orderNameYaxis}
-            onChange={(e) => setState({ ...state, orderNameYaxis: e.target.value })}
-          >
-            <option value="" disabled>
-              Select a y axis
-            </option>
-            {attributeEntityMenuItems.map((value, index) => (
-              <option key={`option${index}`} value={value}>
-                {value}
-              </option>
-            ))}
-          </select>
-        </div>
-
-        <Button
-          label="Make"
-          variantType="secondary"
-          variant="solid"
-          disabled={!state.isButtonEnabled || (!state.orderNameXaxis && !state.orderNameYaxis)}
-          onClick={onClickMakeButton}
-        />
-      </div>
-    </div>
-  );
-};
-
-export default ConfigPanel;
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/EdgesLayer.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/EdgesLayer.tsx
index 5adafe3499e91f1deadd9d6a5152364e86e82808..bea37982d5a3ea3383f2372ba82eb238eb57bc06 100644
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/EdgesLayer.tsx
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/EdgesLayer.tsx
@@ -1,17 +1,14 @@
-import React, { useEffect, useRef } from 'react';
+import React, { useEffect, useRef, useMemo } from 'react';
 import { DataConnection, VisualRegionConfig, RegionData, VisualEdgesConfig, DataPoint } from './types';
-import { select } from 'd3';
-
-import { isNumeric } from './utils';
+import { index, select } from 'd3';
 
 export type EdgesLayerProps = {
   dataConnections: DataConnection[];
   visualConfig: React.MutableRefObject<VisualEdgesConfig>;
+  visualScatterplot: VisualRegionConfig;
   data1: DataPoint[];
   data2: DataPoint[];
   nameEdges: string;
-  nameRegions: string[];
-  width: number;
 };
 
 export type KeyedEdgesLayerProps = EdgesLayerProps & {
@@ -68,10 +65,10 @@ function edgeGenerator(dataPoint: dataPointEdge): string {
   return path;
 }
 
-const EdgesLayer: React.FC<EdgesLayerProps> = ({ dataConnections, visualConfig, data1, data2, nameEdges, width }) => {
+const EdgesLayer: React.FC<EdgesLayerProps> = ({ dataConnections, visualConfig, data1, data2, nameEdges, visualScatterplot }) => {
   const svgRef = useRef(null);
 
-  useEffect(() => {
+  const [dataVis, dataEdgeIds] = useMemo(() => {
     const data1_id = data1.map((item) => item.id);
     const data1_x = data1.map((item) => item.x);
     const data1_y = data1.map((item) => item.y);
@@ -80,64 +77,61 @@ const EdgesLayer: React.FC<EdgesLayerProps> = ({ dataConnections, visualConfig,
     const data2_x = data2.map((item) => item.x);
     const data2_y = data2.map((item) => item.y);
 
-    const svg = select(svgRef.current);
     const heightRegion = visualConfig.current.configRegion.height;
 
-    const svgToRegion1 = [visualConfig.current.configRegion.margin.left, visualConfig.current.configRegion.margin.top + 0 * heightRegion];
-    const svgToRegion2 = [visualConfig.current.configRegion.margin.left, visualConfig.current.configRegion.margin.top + 1 * heightRegion];
+    const svgToRegion1 = [visualScatterplot.margin.left, visualConfig.current.configRegion.margin.top + 0 * heightRegion];
+    const svgToRegion2 = [visualScatterplot.margin.left, visualConfig.current.configRegion.margin.top + 1 * heightRegion];
 
     const dataVis: dataPointEdge[] = [];
     const dataEdgeIds: string[] = [];
-    dataConnections.forEach(function (value: DataConnection) {
-      // Get FROM
-      //  ID
-      // what happens if indexID_region1 is not found
-      const indexID_region1 = data1_id.findIndex((idInstance) => {
-        return idInstance == value.from;
-      });
+
+    dataConnections.forEach((value: DataConnection) => {
+      const indexID_region1 = data1_id.findIndex((idInstance) => idInstance === value.from);
 
       const startX_region1 = data1_x[indexID_region1] + svgToRegion1[0];
       const startY_region1 = data1_y[indexID_region1] + svgToRegion1[1];
-      // GET TO
-      const indexID_region2 = data2_id.findIndex((idInstance) => {
-        return idInstance == value.to;
-      });
 
+      const indexID_region2 = data2_id.findIndex((idInstance) => idInstance === value.to);
       const startX_region2 = data2_x[indexID_region2] + svgToRegion2[0];
       const startY_region2 = data2_y[indexID_region2] + svgToRegion2[1] + visualConfig.current.offsetY;
+
       dataVis.push({ start: [startX_region1, startY_region1], end: [startX_region2, startY_region2] });
 
-      let from_stringModified = value.from.replace('/', '_'); // / is not css valid
-      const to_stringModified = value.to.replace('/', '_'); // / is not css valid
+      let from_stringModified = value.from.replace('/', '_');
+      const to_stringModified = value.to.replace('/', '_');
 
-      if (isNumeric(from_stringModified)) {
+      if (!isNaN(parseInt(from_stringModified))) {
         from_stringModified = 'idAdd_' + from_stringModified;
       }
 
       dataEdgeIds.push(`${from_stringModified}_fromto_${to_stringModified}`);
     });
-
-    const groupEdges = svg.append('g').attr('class', nameEdges);
-
-    groupEdges
-      .selectAll('edgesInside')
-      .data(dataVis)
-      .enter()
-      .append('path')
-      .attr('d', (d) => edgeGenerator(d))
-      .attr('class', (d, i) => dataEdgeIds[i])
-      /*
-      .attr('stroke', 'bg-secondary-600')
-      .attr('stroke-width', 2)
-      .style('stroke-opacity', 0.7)
-      */
-      .attr('stroke', visualConfig.current.stroke)
-      .attr('stroke-width', visualConfig.current.strokeWidth)
-      .style('stroke-opacity', visualConfig.current.strokeOpacity)
-      .attr('fill', 'none');
+    return [dataVis, dataEdgeIds];
   }, [dataConnections, visualConfig, data1, data2, nameEdges]);
 
-  return <svg ref={svgRef} width={600} height={visualConfig.current.height} />;
+  return (
+    <svg
+      ref={svgRef}
+      width={visualScatterplot.width}
+      height={visualConfig.current.height}
+      //preserveAspectRatio="xMidYMid meet"
+      //viewBox={`0 0 ${visualScatterplot.width} ${visualConfig.current.height}`}
+    >
+      <g className={nameEdges}>
+        {dataVis.map((edgeData, index) => (
+          <path
+            key={dataEdgeIds[index]}
+            d={edgeGenerator(edgeData)}
+            className={dataEdgeIds[index]}
+            fill="none"
+            stroke={visualConfig.current.stroke}
+            strokeWidth={visualConfig.current.strokeWidth}
+            strokeOpacity={visualConfig.current.strokeOpacity}
+          />
+        ))}
+      </g>
+    </svg>
+  );
 };
 
 export default EdgesLayer;
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/Scatterplot.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/Scatterplot.tsx
index cb1016e219a01b4df68dd7557ab09e131cec54b2..2f1b415031785b3b15854f82d8b99955257906ce 100644
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/Scatterplot.tsx
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/Scatterplot.tsx
@@ -1,33 +1,51 @@
-import React, { useEffect, useRef, useState } from 'react';
-import { select, scaleBand, axisBottom, scaleLinear, forceX, forceY, brush, forceCollide, format, axisLeft, forceSimulation } from 'd3';
+import React, { useEffect, useRef, useState, useMemo } from 'react';
+import {
+  select,
+  scaleBand,
+  axisBottom,
+  scaleLinear,
+  forceX,
+  forceY,
+  brush,
+  forceCollide,
+  format,
+  axisLeft,
+  forceSimulation,
+  Axis,
+  NumberValue,
+  Selection,
+  ScaleBand,
+  ScaleLinear,
+} from 'd3';
 
 import { VisualRegionConfig, RegionData, DataPoint, DataPointXY } from './types';
-import { calcTextWidth, calcTextWidthCanvas } from './utils';
-import { ArrowRightAlt } from '@mui/icons-material';
-import Icon from '@graphpolaris/shared/lib/components/icon';
+import { calcTextWidth } from './utils';
+import { ArrowForward } from '@mui/icons-material';
+import { Icon } from '@graphpolaris/shared/lib/components/icon';
+import { EntityPill } from '@graphpolaris/shared/lib/components/pills/Pill';
+import { noDataRange } from '../utils';
 
-export type ScatterPlotProps = {
+export type ScatterplotProps = {
   data: RegionData;
   visualConfig: VisualRegionConfig;
   xScaleRange: string[] | number[];
   yScaleRange: string[] | number[];
-  width: number;
   onBrushUpdate: (idElements: string[], selectedElement: string) => void;
-  onBrushClear: (selectedElement: string, idData: string[]) => void;
-  onResultJitter: (data: DataPoint[]) => void;
+  onBrushClear: (selectedElement: string) => void;
+  onResultJitter: (data: DataPoint[], idScatterplot: number) => void;
 };
 
-export type KeyedScatterplotProps = ScatterPlotProps & {
+export type KeyedScatterplotProps = ScatterplotProps & {
   key: number;
 };
 
 function computeRadiusPoints(width: number, numPoints: number): number {
-  const radius: number = numPoints >= 170 ? width * 0.0042 : width * 0.007;
+  const radius: number = numPoints >= 170 ? width * 0.0032 : width * 0.004;
 
   return radius;
 }
 
-export const ScatterPlot = ({
+export const Scatterplot: React.FC<ScatterplotProps> = ({
   data,
   visualConfig,
   xScaleRange,
@@ -35,24 +53,41 @@ export const ScatterPlot = ({
   onBrushUpdate,
   onBrushClear,
   onResultJitter,
-  width,
-}: ScatterPlotProps) => {
+}) => {
   const svgRef = useRef(null);
   const groupMarginRef = useRef<SVGGElement>(null as any);
-
   const brushRef = useRef<SVGGElement>(null as any);
 
-  useEffect(() => {
-    const maxLengthAllowedAxisY: number = 85;
-    const maxLengthAllowedAxisX: number = 50;
-    const styleTextXAxisLabel = {
+  const [textXLabel, setTextXLabel] = useState('');
+  const [textYLabel, setTextYLabel] = useState('');
+
+  const idScatterplot = useMemo((): number => {
+    return parseInt(data.name.split('_')[1], 10);
+  }, [data.name]);
+
+  const configStyle = useMemo(() => {
+    return {
+      colorText: 'hsl(var(--clr-sec--800))',
+      colorTextUnselect: 'hsl(var(--clr-sec--400))',
+      colorLinesHyperEdge: 'hsl(var(--clr-black))',
+    };
+  }, []);
+
+  const styleTextXaxisLabel = useMemo(
+    () => ({
       classTextXAxis: 'font-inter font-secondary font-semibold text-right capitalize text-xs',
       x: 1.01 * visualConfig.widthMargin + visualConfig.margin.right,
       y: visualConfig.heightMargin + 1.25 * visualConfig.margin.bottom,
       textAnchor: 'start',
       dominantBaseline: 'middle',
       maxLengthText: 90,
-    };
+    }),
+    [visualConfig.widthMargin, visualConfig.margin.right, visualConfig.heightMargin, visualConfig.margin.bottom],
+  );
+
+  useEffect(() => {
+    const maxLengthAllowedAxisY: number = 85;
+    const maxLengthAllowedAxisX: number = 50;
 
     const svg = select(svgRef.current);
 
@@ -65,35 +100,124 @@ export const ScatterPlot = ({
     let tickCount = 0;
     let dataCircles: DataPointXY[] = [];
 
-    let dataCirclesXTemp: number[] = [];
-    let dataCirclesYTemp: number[] = [];
-    let xOffset: number;
+    let dataCirclesXtemp: number[] = [];
+    let dataCirclesYtemp: number[] = [];
+    let xOffset: number = 0;
+    let yOffset: number = 0;
+
+    let xAxis: Axis<string> | ((selection: Selection<SVGGElement, unknown, null, undefined>) => void) | Axis<NumberValue>;
+    let yAxis;
+
+    let xAxisType: string = 'none'; //'linear', 'band','none'
+    let yAxisType: string = 'none'; //'linear', 'band','none'
+
+    let xScaleTemp: ScaleBand<string> | ScaleLinear<number, number>;
+    let yScaleTemp: ScaleBand<string> | ScaleLinear<number, number>;
+
+    // for updating axis.
+    let yAxisGroup = groupMargin.select<SVGGElement>(`.${data.name}yAxis`);
+    if (yAxisGroup.empty()) {
+      yAxisGroup = groupMargin.append('g').attr('class', `${data.name}yAxis`);
+    }
+
+    let xAxisGroup = groupMargin.select<SVGGElement>(`.${data.name}xAxis`);
+    if (xAxisGroup.empty()) {
+      xAxisGroup = groupMargin
+        .append('g')
+        .attr('class', `${data.name}xAxis`)
+        .attr('transform', `translate(0, ${visualConfig.heightMargin})`);
+    }
+
+    if (!data.xAxisName && !data.yAxisName) {
+      //console.log('case1 ', data.xAxisName, data.yAxisName);
+
+      dataCirclesXtemp = Array(data.xData.length).fill(visualConfig.widthMargin * 0.5); // place dots at the center of the svg
+      dataCirclesYtemp = Array(data.yData.length).fill(visualConfig.heightMargin * 0.5);
+      dataCircles = data.xData.map((value, index) => ({ x: dataCirclesXtemp[index], y: dataCirclesYtemp[index] }));
+
+      const radius = computeRadiusPoints(visualConfig.width, data.xData.length);
+
+      const simulation = forceSimulation<DataPointXY>(dataCircles)
+        .force('x', forceX<DataPointXY>((d) => d.x).strength(0.1))
+        .force('y', forceY<DataPointXY>((d) => d.y).strength(4))
+        .force('collide', forceCollide(radius * 1.25).strength(2));
+
+      const circles = groupMargin.selectAll('circle').data(dataCircles);
+
+      circles
+        .enter()
+        .append('circle')
+        .attr('class', (d, i) => `${data.idData[i]}`)
+        .attr('cx', (d) => d.x)
+        .attr('cy', (d) => d.y)
+        .attr('r', radius)
+        .attr('stroke', data.colorNodesStroke)
+        .attr('fill', data.colorNodes);
+
+      circles.exit().remove();
+
+      simulation.on('tick', function () {
+        groupMargin
+          .selectAll<SVGCircleElement, DataPointXY>('circle')
+          .attr('cx', (d: DataPointXY) => d.x)
+          .attr('cy', (d: DataPointXY) => d.y);
+
+        tickCount++;
+        if (tickCount > maxComputations) {
+          const dataSimulation: DataPoint[] = dataCircles.map(({ x, y }, i) => ({
+            x,
+            y,
+            id: data.idData[i],
+          }));
+          onResultJitter(dataSimulation, idScatterplot);
+
+          simulation.stop();
+        }
+      });
+
+      xScaleTemp = scaleBand<string>()
+        .domain(xScaleRange as string[])
+        .range([0, visualConfig.widthMargin])
+        .paddingOuter(0);
+
+      yScaleTemp = scaleBand<string>()
+        .domain(yScaleRange as string[])
+        .range([visualConfig.heightMargin, 0])
+        .paddingOuter(0);
+
+      xAxisType = 'none';
+      yAxisType = 'none';
+      yAxis = axisLeft(yScaleTemp).tickValues([]);
+      xAxis = axisBottom(xScaleTemp).tickValues([]);
+      yAxisGroup.call(yAxis);
+      xAxisGroup.attr('transform', 'translate(0,' + visualConfig.heightMargin + ')').call(xAxis);
+    } else if (!!data.xAxisName && !!data.yAxisName) {
+      //console.log('case2 ', data.xAxisName, data.yAxisName);
 
-    if (data.xData.length != 0 && data.yData.length != 0) {
       if (typeof data.xData[0] != 'number') {
-        let xScaleTemp = scaleBand<string>()
+        xScaleTemp = scaleBand<string>()
           .domain(xScaleRange as string[])
           .range([0, visualConfig.widthMargin])
           .paddingOuter(0);
+        xAxisType = 'band';
 
         xOffset = 0.5 * xScaleTemp.bandwidth();
 
-        dataCirclesXTemp = data.xData.map((value, index) => {
-          const scaledValue = typeof value === 'number' ? xScaleTemp(value.toString()) : xScaleTemp(value);
+        dataCirclesXtemp = data.xData.map((value, index) => {
+          const scaledValue = xScaleTemp(value);
           if (scaledValue !== undefined) {
             return scaledValue + xOffset;
           } else {
             return 0;
           }
         });
+        const TextTicks = calcTextWidth(xScaleRange as string[], maxLengthAllowedAxisX, styleTextXaxisLabel.classTextXAxis);
 
-        const textTicks = calcTextWidth(xScaleRange as string[], maxLengthAllowedAxisX, styleTextXAxisLabel.classTextXAxis);
-
-        let xAxis = axisBottom(xScaleTemp)
-          .tickFormat((d, i) => textTicks[i])
+        xAxis = axisBottom(xScaleTemp)
+          .tickFormat((d, i) => TextTicks[i])
           .tickSizeOuter(0);
-        groupMargin
-          .append('g')
+
+        xAxisGroup
           .attr('transform', 'translate(0,' + visualConfig.heightMargin + ')')
           .call(xAxis)
           .selectAll('text')
@@ -101,80 +225,95 @@ export const ScatterPlot = ({
           .attr('x', '10')
           .attr('y', '0')
           .attr('dy', '0')
-          .style('dominant-baseline', styleTextXAxisLabel.dominantBaseline)
+          .style('dominant-baseline', styleTextXaxisLabel.dominantBaseline)
           .attr('transform', 'rotate(90)');
       } else {
-        let xScaleTemp = scaleLinear<number>()
+        xScaleTemp = scaleLinear<number>()
           .domain(xScaleRange as number[])
           .range([0, visualConfig.widthMargin]);
+        xAxisType = 'linear';
+        dataCirclesXtemp = data.xData.map((value, index) => {
+          const scaledValue = xScaleTemp(value);
 
-        dataCirclesXTemp = data.xData.map((value, index) => {
-          const numericValue = typeof value === 'string' ? parseFloat(value) : value;
-          return xScaleTemp(numericValue);
+          if (scaledValue !== undefined) {
+            return scaledValue;
+          } else {
+            return 0;
+          }
         });
 
         const [minValueX, maxValueX]: number[] = xScaleTemp.domain();
         const averageMinMaxX: number = Math.round((minValueX + maxValueX) / 2.0);
 
-        const xAxis = axisBottom(xScaleTemp)
+        xAxis = axisBottom(xScaleTemp)
           .tickValues([minValueX, 0.5 * (minValueX + averageMinMaxX), averageMinMaxX, 0.5 * (maxValueX + averageMinMaxX), maxValueX])
           .tickFormat(format('.2s'));
 
-        groupMargin
-          .append('g')
-          .attr('transform', 'translate(0,' + visualConfig.heightMargin + ')')
-          .call(xAxis);
+        xAxisGroup.attr('transform', 'translate(0,' + visualConfig.heightMargin + ')').call(xAxis);
       }
 
       if (typeof data.yData[0] != 'number') {
-        let yScaleTemp = scaleBand<string>()
+        yScaleTemp = scaleBand<string>()
           .domain(yScaleRange as string[])
           .range([visualConfig.heightMargin, 0])
           .paddingOuter(0);
+        yAxisType = 'band';
+        yOffset = 0.5 * yScaleTemp.bandwidth();
 
-        xOffset = 0.5 * yScaleTemp.bandwidth();
+        dataCirclesYtemp = data.yData.map((value, index) => {
+          //const scaledValue = typeof value === 'number' ? yScaleTemp(value.toString()) : yScaleTemp(value);
+          const scaledValue = yScaleTemp(value);
 
-        dataCirclesYTemp = data.yData.map((value, index) => {
-          const scaledValue = typeof value === 'number' ? yScaleTemp(value.toString()) : yScaleTemp(value);
           if (scaledValue !== undefined) {
-            return scaledValue + xOffset;
+            return scaledValue + yOffset;
           } else {
             return 0;
           }
         });
 
-        const textTicks = calcTextWidth(yScaleRange as string[], maxLengthAllowedAxisY, styleTextXAxisLabel.classTextXAxis);
+        const textTicks = calcTextWidth(yScaleRange as string[], maxLengthAllowedAxisY, styleTextXaxisLabel.classTextXAxis);
 
-        let yAxis = axisLeft(yScaleTemp)
+        yAxis = axisLeft(yScaleTemp)
           .tickFormat((d, i) => textTicks[i])
           .tickSizeOuter(0);
-        groupMargin.append('g').call(yAxis).selectAll('text');
+        yAxisGroup.call(yAxis).selectAll('text');
       } else {
-        let yScaleTemp = scaleLinear<number>()
+        yScaleTemp = scaleLinear<number>()
           .domain(yScaleRange as number[])
           .range([visualConfig.heightMargin, 0]);
+        yAxisType = 'linear';
+        dataCirclesYtemp = data.yData.map((value, index) => {
+          const scaledValue = yScaleTemp(value);
 
-        dataCirclesYTemp = data.yData.map((value, index) => {
-          const numericValue = typeof value === 'string' ? parseFloat(value) : value;
-          return yScaleTemp(numericValue);
+          if (scaledValue !== undefined) {
+            return scaledValue;
+          } else {
+            return 0;
+          }
         });
 
         const [minValueX, maxValueX]: number[] = yScaleTemp.domain();
         const averageMinMaxX: number = Math.round((minValueX + maxValueX) / 2.0);
 
-        const yAxis = axisLeft(yScaleTemp)
+        yAxis = axisLeft(yScaleTemp)
           .tickValues([minValueX, 0.5 * (minValueX + averageMinMaxX), averageMinMaxX, 0.5 * (maxValueX + averageMinMaxX), maxValueX])
           .tickFormat(format('.2s'));
 
-        groupMargin.append('g').call(yAxis);
+        yAxisGroup.call(yAxis);
       }
 
-      dataCircles = data.xData.map((value, index) => ({ x: dataCirclesXTemp[index], y: dataCirclesYTemp[index] }));
-
+      dataCircles = data.xData.map((value, index) => ({ x: dataCirclesXtemp[index], y: dataCirclesYtemp[index] }));
       const radius = computeRadiusPoints(visualConfig.width, data.xData.length);
-      groupMargin
-        .selectAll('circle')
-        .data(dataCircles)
+
+      const circles = groupMargin.selectAll('circle').data(dataCircles);
+      circles
+        .attr('cx', (d) => d.x)
+        .attr('cy', (d) => d.y)
+        .attr('r', radius)
+        .attr('stroke', data.colorNodesStroke)
+        .attr('fill', data.colorNodes);
+
+      circles
         .enter()
         .append('circle')
         .attr('class', (d, i) => `${data.idData[i]}`)
@@ -184,73 +323,74 @@ export const ScatterPlot = ({
         .attr('stroke', data.colorNodesStroke)
         .attr('fill', data.colorNodes);
 
+      circles.exit().remove();
+
       const dataSimulation: DataPoint[] = dataCircles.map(({ x, y }, i) => ({
         x: x,
         y: y,
         id: data.idData[i],
       }));
 
-      onResultJitter(dataSimulation);
+      onResultJitter(dataSimulation, idScatterplot);
+    } else if (!!data.yAxisName) {
+      //console.log('case3 ', data.xAxisName, data.yAxisName);
 
-      const textLabelAxis = calcTextWidth(data.xAxisName, styleTextXAxisLabel.maxLengthText, styleTextXAxisLabel.classTextXAxis);
-
-      svg
-        .append('text')
-        .attr('x', styleTextXAxisLabel.x)
-        .attr('y', styleTextXAxisLabel.y)
-        .text(textLabelAxis[0])
-        .style('text-anchor', styleTextXAxisLabel.textAnchor)
-        .style('dominant-baseline', styleTextXAxisLabel.dominantBaseline)
-        .attr('class', styleTextXAxisLabel.classTextXAxis);
-    } else if (data.yData.length != 0) {
       if (typeof data.yData[0] != 'number') {
-        let yScaleTemp = scaleBand<string>()
+        yScaleTemp = scaleBand<string>()
           .domain(yScaleRange as string[])
           .range([visualConfig.heightMargin, 0])
           .paddingOuter(0);
 
-        xOffset = 0.5 * yScaleTemp.bandwidth();
+        yOffset = 0.5 * yScaleTemp.bandwidth();
+        yAxisType = 'band';
+        dataCirclesYtemp = data.yData.map((value, index) => {
+          //const scaledValue = typeof value === 'number' ? yScaleTemp(value.toString()) : yScaleTemp(value);
+          const scaledValue = yScaleTemp(value);
 
-        dataCirclesYTemp = data.yData.map((value, index) => {
-          const scaledValue = typeof value === 'number' ? yScaleTemp(value.toString()) : yScaleTemp(value);
           if (scaledValue !== undefined) {
-            return scaledValue + xOffset;
+            return scaledValue + yOffset;
           } else {
             return 0;
           }
         });
 
-        const textTicks = calcTextWidth(yScaleRange as string[], maxLengthAllowedAxisY, styleTextXAxisLabel.classTextXAxis);
+        const textTicks = calcTextWidth(yScaleRange as string[], maxLengthAllowedAxisY, styleTextXaxisLabel.classTextXAxis);
 
-        let yAxis = axisLeft(yScaleTemp)
+        yAxis = axisLeft(yScaleTemp)
           .tickFormat((d, i) => textTicks[i])
           .tickSizeOuter(0);
-        groupMargin.append('g').call(yAxis).selectAll('text');
+        yAxisGroup.call(yAxis).selectAll('text');
       } else {
-        let yScaleTemp = scaleLinear<number>()
+        yScaleTemp = scaleLinear<number>()
           .domain(yScaleRange as number[])
           .range([visualConfig.heightMargin, 0]);
+        yAxisType = 'linear';
+        dataCirclesYtemp = data.yData.map((value, index) => {
+          const scaledValue = yScaleTemp(value);
 
-        dataCirclesYTemp = data.yData.map((value, index) => {
-          const numericValue = typeof value === 'string' ? parseFloat(value) : value;
-          return yScaleTemp(numericValue);
+          if (scaledValue !== undefined) {
+            return scaledValue;
+          } else {
+            return 0;
+          }
         });
 
         const [minValueX, maxValueX]: number[] = yScaleTemp.domain();
         const averageMinMaxX: number = Math.round((minValueX + maxValueX) / 2.0);
 
-        const xAxis = axisLeft(yScaleTemp)
+        yAxis = axisLeft(yScaleTemp)
           .tickValues([minValueX, 0.5 * (minValueX + averageMinMaxX), averageMinMaxX, 0.5 * (maxValueX + averageMinMaxX), maxValueX])
           .tickFormat(format('.2s'));
 
-        groupMargin.append('g').call(xAxis);
+        yAxisGroup.call(yAxis);
       }
 
-      let xScaleTemp = scaleLinear<number>()
-        .domain(xScaleRange as number[])
+      xScaleTemp = scaleLinear<number, number>()
+        .domain(noDataRange as number[])
         .range([0, visualConfig.widthMargin]);
 
-      dataCircles = data.yData.map((value, index) => ({ x: xScaleTemp(0.0), y: dataCirclesYTemp[index] }));
+      const valueXMiddle = visualConfig.widthMargin / 2;
+      dataCircles = data.yData.map((value, index) => ({ x: valueXMiddle, y: dataCirclesYtemp[index] }));
 
       const radius = computeRadiusPoints(visualConfig.width, data.yData.length);
       const simulation = forceSimulation<DataPointXY>(dataCircles)
@@ -258,9 +398,14 @@ export const ScatterPlot = ({
         .force('y', forceY<DataPointXY>((d) => d.y).strength(4))
         .force('collide', forceCollide(radius * 1.25).strength(0.5));
 
-      const circles = groupMargin
-        .selectAll('circle')
-        .data(dataCircles)
+      const circles = groupMargin.selectAll('circle').data(dataCircles);
+      circles
+        .attr('cx', (d) => d.x)
+        .attr('cy', (d) => d.y)
+        .attr('r', radius)
+        .attr('stroke', data.colorNodesStroke)
+        .attr('fill', data.colorNodes);
+      circles
         .enter()
         .append('circle')
         .attr('class', (d, i) => `${data.idData[i]}`)
@@ -269,9 +414,13 @@ export const ScatterPlot = ({
         .attr('r', radius)
         .attr('stroke', data.colorNodesStroke)
         .attr('fill', data.colorNodes);
+      circles.exit().remove();
 
       simulation.on('tick', function () {
-        circles.attr('cx', (d, i) => d.x as number).attr('cy', (d) => d.y as number);
+        groupMargin
+          .selectAll<SVGCircleElement, DataPointXY>('circle')
+          .attr('cx', (d: DataPointXY) => d.x)
+          .attr('cy', (d: DataPointXY) => d.y);
 
         tickCount++;
         if (tickCount > maxComputations) {
@@ -280,22 +429,27 @@ export const ScatterPlot = ({
             y,
             id: data.idData[i],
           }));
-          onResultJitter(dataSimulation);
+          onResultJitter(dataSimulation, idScatterplot);
 
           simulation.stop();
         }
       });
-    } else if (data.xData.length != 0) {
+
+      xAxis = axisBottom(xScaleTemp).tickValues([]);
+      xAxisGroup.attr('transform', 'translate(0,' + visualConfig.heightMargin + ')').call(xAxis);
+    } else if (!!data.xAxisName) {
+      //console.log('case4 ', data.xAxisName, data.yAxisName);
       if (typeof data.xData[0] != 'number') {
-        let xScaleTemp = scaleBand<string>()
+        xScaleTemp = scaleBand<string>()
           .domain(xScaleRange as string[])
           .range([0, visualConfig.widthMargin])
           .paddingOuter(0);
 
         xOffset = 0.5 * xScaleTemp.bandwidth();
+        xAxisType = 'band';
+        dataCirclesXtemp = data.xData.map((value, index) => {
+          const scaledValue = xScaleTemp(value);
 
-        dataCirclesXTemp = data.xData.map((value, index) => {
-          const scaledValue = typeof value === 'number' ? xScaleTemp(value.toString()) : xScaleTemp(value);
           if (scaledValue !== undefined) {
             return scaledValue + xOffset;
           } else {
@@ -303,13 +457,12 @@ export const ScatterPlot = ({
           }
         });
 
-        const textTicks = calcTextWidth(xScaleRange as string[], maxLengthAllowedAxisX, styleTextXAxisLabel.classTextXAxis);
+        const textTicks = calcTextWidth(xScaleRange as string[], maxLengthAllowedAxisX, styleTextXaxisLabel.classTextXAxis);
 
-        let xAxis = axisBottom(xScaleTemp)
+        xAxis = axisBottom(xScaleTemp)
           .tickFormat((d, i) => textTicks[i])
           .tickSizeOuter(0);
-        groupMargin
-          .append('g')
+        xAxisGroup
           .attr('transform', 'translate(0,' + visualConfig.heightMargin + ')')
           .call(xAxis)
           .selectAll('text')
@@ -317,57 +470,68 @@ export const ScatterPlot = ({
           .attr('x', '10')
           .attr('y', '0')
           .attr('dy', '0')
-          .style('dominant-baseline', styleTextXAxisLabel.dominantBaseline)
+          .style('dominant-baseline', styleTextXaxisLabel.dominantBaseline)
           .attr('transform', 'rotate(90)');
       } else {
-        let xScaleTemp = scaleLinear<number>()
+        xScaleTemp = scaleLinear<number>()
           .domain(xScaleRange as number[])
           .range([0, visualConfig.widthMargin]);
-
-        dataCirclesXTemp = data.xData.map((value, index) => {
-          const numericValue = typeof value === 'string' ? parseFloat(value) : value;
-          return xScaleTemp(numericValue);
+        xAxisType = 'linear';
+        dataCirclesXtemp = data.xData.map((value, index) => {
+          const scaledValue = xScaleTemp(value);
+          if (scaledValue !== undefined) {
+            return scaledValue;
+          } else {
+            return 0;
+          }
         });
 
         const [minValueX, maxValueX]: number[] = xScaleTemp.domain();
         const averageMinMaxX: number = Math.round((minValueX + maxValueX) / 2.0);
 
-        const xAxis = axisBottom(xScaleTemp)
+        xAxis = axisBottom(xScaleTemp)
           .tickValues([minValueX, 0.5 * (minValueX + averageMinMaxX), averageMinMaxX, 0.5 * (maxValueX + averageMinMaxX), maxValueX])
           .tickFormat(format('.2s'));
-
-        groupMargin
-          .append('g')
-          .attr('transform', 'translate(0,' + visualConfig.heightMargin + ')')
-          .call(xAxis);
+        xAxisGroup.attr('transform', 'translate(0,' + visualConfig.heightMargin + ')').call(xAxis);
       }
 
-      let yScaleTemp = scaleLinear<number>()
-        .domain(yScaleRange as number[])
+      yScaleTemp = scaleLinear<number>()
+        .domain(noDataRange as number[])
         .range([visualConfig.heightMargin, 0]);
 
-      dataCircles = data.xData.map((value, index) => ({ x: dataCirclesXTemp[index], y: yScaleTemp(0) }));
+      const valueYMiddle = visualConfig.heightMargin / 2;
+      dataCircles = data.xData.map((value, index) => ({ x: dataCirclesXtemp[index], y: valueYMiddle }));
 
       const radius = computeRadiusPoints(visualConfig.width, data.xData.length);
+
       const simulation = forceSimulation<DataPointXY>(dataCircles)
         .force('x', forceX<DataPointXY>((d) => d.x).strength(4))
         .force('y', forceY<DataPointXY>((d) => d.y).strength(0.1))
         .force('collide', forceCollide(radius * 1.25).strength(0.5));
 
-      const circles = groupMargin
-        .selectAll('circle')
-        .data(dataCircles)
+      const circles = groupMargin.selectAll('circle').data(dataCircles);
+      circles
+        .attr('cx', (d) => d.x)
+        .attr('cy', (d) => d.y)
+        .attr('r', radius)
+        .attr('stroke', data.colorNodesStroke)
+        .attr('fill', data.colorNodes);
+      circles
         .enter()
         .append('circle')
         .attr('class', (d, i) => `${data.idData[i]}`)
-        .attr('cx', (d) => d.x || 0)
-        .attr('cy', (d) => d.y || 0)
+        .attr('cx', (d) => d.x)
+        .attr('cy', (d) => d.y)
         .attr('r', radius)
         .attr('stroke', data.colorNodesStroke)
         .attr('fill', data.colorNodes);
+      circles.exit().remove();
 
       simulation.on('tick', function () {
-        circles.attr('cx', (d, i) => d.x as number).attr('cy', (d) => d.y as number);
+        groupMargin
+          .selectAll<SVGCircleElement, DataPointXY>('circle')
+          .attr('cx', (d: DataPointXY) => d.x)
+          .attr('cy', (d: DataPointXY) => d.y);
 
         tickCount++;
         if (tickCount > maxComputations) {
@@ -377,35 +541,24 @@ export const ScatterPlot = ({
             id: data.idData[i],
           }));
 
-          onResultJitter(dataSimulation);
+          onResultJitter(dataSimulation, idScatterplot);
 
           simulation.stop();
         }
       });
-      const textLabelAxis = calcTextWidth(data.xAxisName, styleTextXAxisLabel.maxLengthText, styleTextXAxisLabel.classTextXAxis);
-
-      svg
-        .append('text')
-        .attr('x', styleTextXAxisLabel.x)
-        .attr('y', styleTextXAxisLabel.y)
-        .text(textLabelAxis[0])
-        .style('text-anchor', styleTextXAxisLabel.textAnchor)
-        .style('dominant-baseline', styleTextXAxisLabel.dominantBaseline)
-        .attr('class', styleTextXAxisLabel.classTextXAxis);
+
+      yAxis = axisLeft(yScaleTemp).tickValues([]);
+      yAxisGroup.call(yAxis).selectAll('text');
     }
 
-    svg
-      .append('rect')
-      .attr('x', 0)
-      .attr('y', 0)
-      .attr('width', visualConfig.width)
-      .attr('height', visualConfig.height)
-      .attr('fill', 'none')
-      .attr('stroke', 'gray');
+    const textLabelAxis = calcTextWidth(data.xAxisName, styleTextXaxisLabel.maxLengthText, styleTextXaxisLabel.classTextXAxis);
+    setTextXLabel(textLabelAxis[0]);
 
-    svg.selectAll('.domain').style('stroke', 'hsl(var(--clr-sec--400))');
-    svg.selectAll('.tick line').style('stroke', 'hsl(var(--clr-sec--400))');
-    svg.selectAll('.tick text').attr('class', 'font-mono').style('stroke', 'none').style('fill', 'hsl(var(--clr-sec--500))');
+    const textLabelYAxis = calcTextWidth(data.yAxisName, styleTextXaxisLabel.maxLengthText, styleTextXaxisLabel.classTextXAxis);
+    setTextYLabel(textLabelYAxis[0]);
+
+    // axis style
+    svg.selectAll('.tick text').attr('class', 'font-inter').style('stroke', 'none').style('fill', configStyle.colorText);
 
     // BRUSH LOGIC
     const myBrush: any = brush()
@@ -416,7 +569,9 @@ export const ScatterPlot = ({
       .on('brush', brushed)
       .on('end', function (event: any) {
         if (event.selection === null) {
-          onBrushClear(data.name, data.idData);
+          onBrushClear(data.name);
+          xAxisGroup.selectAll('.tick text').style('fill', configStyle.colorText);
+          yAxisGroup.selectAll('.tick text').style('fill', configStyle.colorText);
         }
       });
 
@@ -426,6 +581,7 @@ export const ScatterPlot = ({
       if (!event.selection) {
       } else {
         const [[x0, y0], [x1, y1]] = event.selection;
+
         dataCircles.forEach((d, i) => {
           if (d.x >= x0 && d.x <= x1 && d.y >= y0 && d.y <= y1) {
             selectedDataIds.push(data.idData[i]);
@@ -434,14 +590,46 @@ export const ScatterPlot = ({
 
         onBrushUpdate(selectedDataIds, data.name);
         selectedDataIds = [];
+
+        // new stuff
+
+        xAxisGroup.selectAll('.tick text').style('fill', configStyle.colorTextUnselect);
+        xAxisGroup.selectAll('.tick text').each(function (d: any) {
+          if (xAxisType != 'none') {
+            const xValueFromD = xScaleTemp(d);
+
+            if (xValueFromD != undefined) {
+              select(this).style(
+                'fill',
+                xValueFromD >= x0 - xOffset && xValueFromD <= x1 - xOffset ? configStyle.colorText : configStyle.colorTextUnselect,
+              );
+            }
+          }
+        });
+
+        yAxisGroup.selectAll('.tick text').style('fill', configStyle.colorTextUnselect);
+
+        yAxisGroup.selectAll('.tick text').each(function (d: any) {
+          if (yAxisType != 'none') {
+            const yValueFromD = yScaleTemp(d);
+
+            if (yValueFromD != undefined) {
+              select(this).style(
+                'fill',
+                yValueFromD >= y0 - yOffset && yValueFromD <= y1 - yOffset ? configStyle.colorText : configStyle.colorTextUnselect,
+              );
+            }
+          }
+        });
       }
     }
 
     const brushGroup = select(brushRef.current);
-    brushGroup.attr('transform', `translate(${visualConfig.margin.left},${visualConfig.margin.top})`).attr('class', 'brushingElem');
+    brushGroup
+      .attr('transform', `translate(${visualConfig.margin.left},${visualConfig.margin.top})`)
+      .attr('class', 'brushingElem_' + data.name);
 
     brushGroup.call(myBrush);
-
     brushGroup
       .select('.selection')
       .style('fill', data.colorBrush)
@@ -449,20 +637,51 @@ export const ScatterPlot = ({
       .style('stroke', data.colorBrushStroke)
       .style('stroke-width', 2);
 
+    brushGroup.call(myBrush.move, null);
+
     brushGroup.selectAll('.handle').style('stroke', 'none');
-  }, [data, visualConfig, xScaleRange, yScaleRange, width]);
+    brushGroup.selectAll('.overlay').style('stroke', 'none');
+  }, [data, visualConfig, xScaleRange, yScaleRange]);
 
   return (
-    <div className="w-full border border-secondary-200">
-      <div className="w-full border-light font-secondary group bg-secondary-200 truncate text-left absolute">
-        <div className="mx-1 w-full flex items-center">
-          <span>{data.nodeName}</span> <Icon component={<ArrowRightAlt />} size={32} />
-          <span>{data.attributeName}</span> <span> : </span>
-          <span>{data.attributeSelected}</span>
+    <div className="w-full">
+      <div className="flex absolute mx-20 my-2 w-22 items-center gap-1">
+        <EntityPill title={data.nodeName} />
+        <div>
+          {data.attributeName && (
+            <div className="flex items-center gap-1">
+              <Icon component={<ArrowForward />} size={16} color="text-secondary-300" />
+              <span className="text-secondary-700 text-sm m-0.5">{data.attributeName}</span>
+              {data.attributeSelected && (
+                <div className="flex items-center gap-1">
+                  <Icon component={<ArrowForward />} size={16} color="text-secondary-300" />
+                  <span className="text-secondary-700 text-sm m-0.5">{data.attributeSelected}</span>
+                </div>
+              )}
+            </div>
+          )}
         </div>
       </div>
       <div className="w-full flex flex-row justify-center">
-        <svg ref={svgRef} width={600} height={visualConfig.height}>
+        <svg ref={svgRef} width={visualConfig.width} height={visualConfig.height}>
+          <text
+            x={styleTextXaxisLabel.x}
+            y={styleTextXaxisLabel.y}
+            dominantBaseline={styleTextXaxisLabel.dominantBaseline}
+            className={styleTextXaxisLabel.classTextXAxis}
+          >
+            {textXLabel}
+          </text>
+
+          <text
+            x={styleTextXaxisLabel.x * 0.05}
+            y={styleTextXaxisLabel.y * 0.5}
+            textAnchor={styleTextXaxisLabel.textAnchor}
+            dominantBaseline={styleTextXaxisLabel.dominantBaseline}
+            className={styleTextXaxisLabel.classTextXAxis}
+          >
+            {textYLabel}
+          </text>
           <g ref={groupMarginRef} />
           <g ref={brushRef} />
         </svg>
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/SelectionEdges.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/SelectionEdges.tsx
deleted file mode 100644
index 1d387b9dd55fe228d7f8b615180919f58def6bea..0000000000000000000000000000000000000000
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/SelectionEdges.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import React, { useState, useEffect } from 'react';
-import Icon from '@graphpolaris/shared/lib/components/icon';
-import * as d3 from 'd3';
-import { ArrowRightAlt } from '@mui/icons-material';
-
-type EdgeArrayItem = {
-  nameRegions: string[];
-};
-
-export type SelectionEdgesProps = EdgeArrayItem[];
-
-function handleCheckbox(index: number, checkboxStates: boolean[]) {
-  const visibility = !checkboxStates[index] ? 'block' : 'none';
-  d3.selectAll(`.edge_region0_to_region${index + 1}`).style('display', visibility);
-}
-
-const SelectionEdges: React.FC<SelectionEdgesProps> = (props) => {
-  const edgesArray = Array.isArray(props) ? props : (Object.values(props) as EdgeArrayItem[]);
-
-  const [checkboxStates, setCheckboxStates] = useState<boolean[]>([]);
-
-  useEffect(() => {
-    // To initialize states
-    setCheckboxStates((prevStates) => {
-      const newStates = [...prevStates];
-      edgesArray.forEach((_, index) => {
-        if (newStates[index] === undefined) {
-          newStates[index] = true;
-        }
-      });
-      return newStates;
-    });
-  }, [props]);
-
-  const handleCheckboxChange = (index: number) => {
-    setCheckboxStates((prevStates) => {
-      const newStates = [...prevStates];
-      newStates[index] = !prevStates[index];
-      return newStates;
-    });
-    handleCheckbox(index, checkboxStates);
-  };
-  return (
-    <div className="border border-gray p-4 bg-white rounded flex items-center">
-      <ul>
-        {edgesArray.map((element: EdgeArrayItem, index: number) => (
-          <li key={index}>
-            <div className="flex items-center space-x-2">
-              <input
-                type="checkbox"
-                checked={checkboxStates[index]}
-                className="checkbox checkbox-sm"
-                onChange={() => handleCheckboxChange(index)}
-              ></input>
-              <div>
-                <span>{element.nameRegions[0]}</span>
-                <Icon component={<ArrowRightAlt />} size={32} />
-                <span>{element.nameRegions[1]}</span>
-              </div>
-            </div>
-          </li>
-        ))}
-      </ul>
-    </div>
-  );
-};
-
-export default SelectionEdges;
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/types.ts b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/types.ts
index 07c8ecc37e9ea4a720861b6c07eb47cb1cb80fe6..10a4ebb740501e714f14b55b0e05741ba98524a2 100644
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/types.ts
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/types.ts
@@ -5,6 +5,12 @@ export interface NodesGraphology {
   attributes: object[];
 }
 
+export interface DataFromPanel {
+  id: number;
+  settingsOpen: boolean;
+  data: DataPanelConfig;
+}
+
 export interface EdgesGraphology {
   key: string;
   attributes: object[];
@@ -18,12 +24,12 @@ export interface GraphData {
 
 export interface UserSelection {
   name: string;
-  nodeName: string;
-  attributeAsRegion: string;
-  attributeAsRegionSelection: string;
+  nodeName?: string;
+  attributeAsRegion?: string;
+  attributeAsRegionSelection?: string;
   placement: {
-    xAxis: string;
-    yAxis: string;
+    xAxis?: string;
+    yAxis?: string;
     colorNodes: string;
     colorNodesStroke: string;
     colorFillBrush: string;
@@ -42,19 +48,19 @@ export interface DataPointXY {
   y: number;
 }
 
-export interface ConnectionFromTo {
+export interface connectionFromTo {
   to: string;
   from: string;
 }
 
-export interface EdgeVisibility {
+export interface edgeVisibility {
   _id: string;
   to: boolean;
   from: boolean;
   visibility: boolean;
 }
 
-export interface IdConnectionsObjects {
+export interface idConnectionsObjects {
   from: IdConnections;
   to: IdConnections;
 }
@@ -86,22 +92,21 @@ export interface AugmentedEdgeAttributes {
   attributes: NodeAttributes;
   from: string;
   to: string;
-  _id: string;
+  id: string;
   label: string;
 }
 
-export interface DataConfig {
-  entityVertical: string;
-  attributeEntity: string;
-  attributeValueSelected: string;
-  orderNameXAxis: string;
-  orderNameYAxis: string;
-  isButtonEnabled: boolean;
+export interface DataPanelConfig {
+  entitySelected?: string;
+  attributeSelected?: string;
+  attributeValueSelected?: string;
+  xAxisSelected?: string;
+  yAxisSelected?: string;
 }
 
 export interface Edge {
   from: string;
-  _id: string;
+  id: string;
   attributes: object[];
   label: string;
   _key: string;
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/utils.ts b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/utils.ts
index 639634acac330f2e4c51d7f421497fa5d27c9fe1..88ea1a75e45357e5d803066403a7b705207a52df 100644
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/utils.ts
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/components/utils.ts
@@ -1,6 +1,7 @@
-import { UserSelection, RegionData, AugmentedNodeAttributes, ConnectionFromTo, IdConnections, EdgeVisibility } from './types';
-import * as d3 from 'd3';
+import { UserSelection, RegionData, AugmentedNodeAttributes, connectionFromTo, IdConnections, edgeVisibility } from './types';
+import { ScaleBand, ScaleLinear, extent } from 'd3';
 import { RefObject } from 'react';
+import { visualizationColors } from 'config';
 
 import Graph, { MultiGraph } from 'graphology';
 
@@ -9,7 +10,8 @@ export function findConnectionsNodes(
   originIDs: string[],
   graphStructure: MultiGraph,
   labelNode: string,
-): [ConnectionFromTo[], string[]] {
+  invert: boolean = false,
+): [connectionFromTo[], string[]] {
   const neighborMap: IdConnections = {};
 
   originIDs.forEach((nodeId) => {
@@ -30,8 +32,8 @@ export function findConnectionsNodes(
     neighborMap[nodeId] = Array.from(tempSet);
   });
 
-  const edgeStrings = wrapperForEdge(neighborMap);
-  const edgeStrings2 = wrapperForEdgeString(neighborMap);
+  const edgeStrings = wrapperForEdge(neighborMap, invert);
+  const edgeStrings2 = wrapperForEdgeString(neighborMap, invert);
 
   return [edgeStrings, edgeStrings2];
 }
@@ -61,15 +63,26 @@ export function getRegionData(nodes: AugmentedNodeAttributes[], regionUserSelect
   // then regionUserSelection.attributeAsRegionSelection will be a string of the elements joined by "-"
   // that is why item.attributes[regionUserSelection.attributeAsRegion] is join with ("-")
 
-  let filteredData: AugmentedNodeAttributes[] = nodes.filter((item: AugmentedNodeAttributes) => {
-    return (
-      item.label === regionUserSelection.nodeName &&
-      item.attributes &&
-      (Array.isArray(item.attributes[regionUserSelection.attributeAsRegion])
-        ? (item.attributes[regionUserSelection.attributeAsRegion] as string[]).join('-') === regionUserSelection.attributeAsRegionSelection
-        : item.attributes[regionUserSelection.attributeAsRegion] === regionUserSelection.attributeAsRegionSelection)
-    );
-  });
+  let filteredData: AugmentedNodeAttributes[] = [];
+
+  if (!regionUserSelection.attributeAsRegion) {
+    filteredData = nodes.filter((item: AugmentedNodeAttributes) => {
+      return item.label === regionUserSelection.nodeName;
+    });
+  } else {
+    filteredData = nodes.filter((item: AugmentedNodeAttributes) => {
+      return (
+        item.label === regionUserSelection.nodeName &&
+        item.attributes &&
+        regionUserSelection.attributeAsRegion &&
+        (Array.isArray(item.attributes[regionUserSelection.attributeAsRegion])
+          ? (item.attributes[regionUserSelection.attributeAsRegion] as string[]).join('-') ===
+            regionUserSelection.attributeAsRegionSelection
+          : item.attributes[regionUserSelection.attributeAsRegion] === regionUserSelection.attributeAsRegionSelection)
+      );
+    });
+  }
+
   if (filteredData.length === 0) filteredData = [];
 
   const idData: string[] = filteredData.map((item) => item._id);
@@ -98,11 +111,11 @@ export function getRegionData(nodes: AugmentedNodeAttributes[], regionUserSelect
     colorNodesStroke: regionUserSelection.placement.colorNodesStroke,
     colorBrush: regionUserSelection.placement.colorFillBrush,
     colorBrushStroke: regionUserSelection.placement.colorStrokeBrush,
-    nodeName: regionUserSelection.nodeName,
-    attributeName: regionUserSelection.attributeAsRegion,
-    attributeSelected: regionUserSelection.attributeAsRegionSelection,
-    xAxisName: regionUserSelection.placement.xAxis,
-    yAxisName: regionUserSelection.placement.yAxis,
+    nodeName: regionUserSelection.nodeName as string,
+    attributeName: regionUserSelection.attributeAsRegion as string,
+    attributeSelected: regionUserSelection.attributeAsRegionSelection as string,
+    xAxisName: regionUserSelection.placement.xAxis as string,
+    yAxisName: regionUserSelection.placement.yAxis as string,
     label: filteredData?.[0]?.label || nodes[0].label,
   };
 
@@ -110,7 +123,7 @@ export function getRegionData(nodes: AugmentedNodeAttributes[], regionUserSelect
 }
 
 export function setExtension(margin: number, data: number[]): [number, number] {
-  const extentData: [number, number] = d3.extent(data) as [number, number];
+  const extentData: [number, number] = extent(data) as [number, number];
 
   if (extentData[0] >= 0.0 && extentData[1] > 0.0) {
     return [extentData[0] * (1.0 - margin), extentData[1] * (1.0 + margin)];
@@ -129,30 +142,38 @@ export function findSimilarElements(array1: string[], array2: string[]): string[
   return array1.filter((element) => array2.includes(element));
 }
 
-export function wrapperForEdge(data: IdConnections): ConnectionFromTo[] {
+export function wrapperForEdge(data: IdConnections, invert: boolean = false): connectionFromTo[] {
   const keysData = Object.keys(data);
-  const resultsDas: ConnectionFromTo[] = [];
+  const resultsDas: connectionFromTo[] = [];
   const results = keysData.forEach((item) => {
     const r = data[item].forEach((itemConnected) => {
-      resultsDas.push({ from: item, to: itemConnected });
+      if (!invert) {
+        resultsDas.push({ from: item, to: itemConnected });
+      } else {
+        resultsDas.push({ from: itemConnected, to: item });
+      }
     });
   });
   return resultsDas;
 }
 
-export function wrapperForEdgeString(data: IdConnections): string[] {
+export function wrapperForEdgeString(data: IdConnections, invert: boolean = false): string[] {
   const keysData = Object.keys(data);
   const resultsDas: string[] = [];
   const results = keysData.forEach((item) => {
     const r = data[item].forEach((itemConnected) => {
-      resultsDas.push(item + '_fromto_' + itemConnected);
+      if (!invert) {
+        resultsDas.push(item + '_fromto_' + itemConnected);
+      } else {
+        resultsDas.push(itemConnected + '_fromto_' + item);
+      }
     });
   });
   return resultsDas;
 }
 
-export function wrapperEdgeVisibility(data: ConnectionFromTo[]): EdgeVisibility[] {
-  let transformedArray: EdgeVisibility[] = data.map(function (item) {
+export function wrapperEdgeVisibility(data: connectionFromTo[]): edgeVisibility[] {
+  let transformedArray: edgeVisibility[] = data.map(function (item) {
     const from_stringModified = item.from.replace('/', '_');
     const to_stringModified = item.to.replace('/', '_');
     const elementString = `${from_stringModified}_fromto_${to_stringModified}`;
@@ -271,3 +292,9 @@ export function calcTextWidthCanvas(rowLabels: string[], maxLengthAllowed: numbe
 
   return rowLabels;
 }
+
+export function nodeColorHex(num: number) {
+  //let entityColors = Object.values(visualizationColors.GPSeq.colors[9]);
+  const col = visualizationColors.GPCat.colors[14][num % visualizationColors.GPCat.colors[14].length];
+  return col;
+}
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/SemSubsConfigPanel.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/SemSubsConfigPanel.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a6df7b0f335c83a01c7618dd114a9677e256220c
--- /dev/null
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/SemSubsConfigPanel.tsx
@@ -0,0 +1,243 @@
+import React, { useState, useMemo, useEffect } from 'react';
+import { DeleteOutline, ArrowDropDown, SubdirectoryArrowRight, ArrowRight } from '@mui/icons-material';
+import { Button } from '@graphpolaris/shared/lib/components/buttons';
+import { Icon } from '@graphpolaris/shared/lib/components/icon';
+import { DataFromPanel, DataPanelConfig } from '../components/types';
+import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
+
+import { EntityPillSelector } from '@graphpolaris/shared/lib/components/selectors/entityPillSelector';
+import { Input } from '@graphpolaris/shared/lib/components';
+
+export type SemSubsConfigPanelProps = {
+  dataFromPanel: DataFromPanel;
+  graphMetaData: GraphMetadata;
+  colorNode: string;
+  onUpdateData: (data: Partial<DataPanelConfig>) => void;
+  onCollapse: (isOpen: boolean) => void;
+  onDelete: () => void;
+  isFirstPanel: boolean;
+};
+
+export const SemSubsConfigPanel: React.FC<SemSubsConfigPanelProps> = ({
+  dataFromPanel,
+  graphMetaData,
+  colorNode,
+  isFirstPanel,
+  onCollapse,
+  onUpdateData,
+  onDelete,
+}) => {
+  const [stateConfigPanelOptions, setStateConfigPanelOptions] = useState<{
+    entitySelectedOptions: string[];
+    attributeSelectedOptions: (undefined | string)[];
+    attributeValueSelectedOptions: any[];
+    xAxisSelectedOptions: (undefined | string)[];
+    yAxisSelectedOptions: (undefined | string)[];
+  }>({
+    entitySelectedOptions: [],
+    attributeSelectedOptions: [],
+    attributeValueSelectedOptions: [],
+    xAxisSelectedOptions: [],
+    yAxisSelectedOptions: [],
+  });
+
+  const [allowToSelectEntity, setAllowToSelectEntity] = useState(false);
+  const data = dataFromPanel.data;
+  const [isNotCollapsed, setIsNotCollapsed] = useState(true);
+
+  const handleButtonCollapseSubsratedPanel = () => {
+    //onCollapse(!dataFromPanel.settingsOpen);
+    //setAllowToSelectEntity(!allowToSelectEntity);
+    setIsNotCollapsed(!isNotCollapsed);
+  };
+
+  // data processing
+
+  useEffect(() => {
+    if (graphMetaData) {
+      setStateConfigPanelOptions((prevState) => ({
+        ...prevState,
+        entitySelectedOptions: graphMetaData.nodes.labels,
+      }));
+    }
+  }, [graphMetaData]);
+
+  useEffect(() => {
+    if (!data.entitySelected) return;
+    if (!graphMetaData.nodes.types[data.entitySelected]) return;
+
+    onCollapse(true);
+
+    // field values of nummerical data are empty. Need to have access to raw data. For now just use categorical
+    const categoricalKeys: (undefined | string)[] = [];
+
+    categoricalKeys.push(undefined);
+
+    for (const key in graphMetaData.nodes.types[data.entitySelected].attributes) {
+      const values = graphMetaData.nodes.types[data.entitySelected].attributes[key].values;
+      if (values && values.length > 0 && values[0].toString() !== '[object Object]') {
+        if (
+          graphMetaData.nodes.types[data.entitySelected].attributes.hasOwnProperty(key) &&
+          graphMetaData.nodes.types[data.entitySelected].attributes[key].dimension === 'categorical'
+        ) {
+          categoricalKeys.push(key as string);
+        }
+      }
+    }
+
+    setStateConfigPanelOptions((prevState) => ({
+      ...prevState,
+      attributeSelectedOptions: categoricalKeys,
+    }));
+
+    onUpdateData({
+      attributeSelected: undefined,
+      attributeValueSelected: undefined,
+      xAxisSelected: undefined,
+      yAxisSelected: undefined,
+    });
+  }, [data.entitySelected]);
+
+  useEffect(() => {
+    if (!data.entitySelected || !data.attributeSelected) return;
+
+    if (data.attributeSelected && graphMetaData.nodes.types[data.entitySelected].attributes[data.attributeSelected]) {
+      let arrayAttributeValues = graphMetaData.nodes.types[data.entitySelected].attributes[data.attributeSelected].values;
+      if (arrayAttributeValues !== undefined) {
+        if (arrayAttributeValues[0].toString() != '[object Object]') {
+          setStateConfigPanelOptions((prevState) => ({
+            ...prevState,
+            attributeValueSelectedOptions: arrayAttributeValues,
+          }));
+
+          onUpdateData({
+            attributeValueSelected: undefined,
+          });
+        }
+      }
+    }
+  }, [data.attributeSelected]);
+
+  useEffect(() => {
+    if (!!data.entitySelected && graphMetaData.nodes.types[data.entitySelected]) {
+      const attributes = Object.keys(graphMetaData.nodes.types[data.entitySelected].attributes);
+
+      const attributesForAxis: (string | undefined)[] = [];
+
+      attributesForAxis.push(undefined);
+      attributesForAxis.push(...attributes);
+
+      setStateConfigPanelOptions((prevState) => ({
+        ...prevState,
+        xAxisSelectedOptions: attributesForAxis,
+        yAxisSelectedOptions: attributesForAxis,
+      }));
+    }
+  }, [data.entitySelected]);
+
+  useEffect(() => {
+    if (!data.attributeSelected) {
+      onUpdateData({ attributeValueSelected: undefined });
+    }
+  }, [data.attributeSelected]);
+
+  return (
+    <div className="flex flex-col w-full">
+      <div className="flex my-2 items-center">
+        <Button
+          onClick={handleButtonCollapseSubsratedPanel}
+          variantType="secondary"
+          variant="ghost"
+          size="xs"
+          iconComponent={dataFromPanel.settingsOpen ? <ArrowDropDown /> : <ArrowRight />}
+        />
+
+        <EntityPillSelector
+          selectedNode={data.entitySelected}
+          dropdownNodes={stateConfigPanelOptions.entitySelectedOptions}
+          onSelectOption={function (option: string): void {
+            onUpdateData({ entitySelected: option });
+          }}
+        />
+
+        <div className="flex justify-center items-center ml-auto">
+          <div className="grow-0 shrink-0 w-6 h-6 flex justify-center items-center">
+            <div className={`h-4 w-4 border border-secondary-150 rounded-sm`} style={{ backgroundColor: colorNode }}></div>
+            {/* TODO: change this to color selector */}
+          </div>
+          <Button
+            variantType="secondary"
+            variant="ghost"
+            size="xs"
+            disabled={isFirstPanel}
+            iconComponent={<DeleteOutline />}
+            onClick={onDelete}
+          />
+        </div>
+      </div>
+      {isNotCollapsed && (
+        <div className="ml-4 gap-2 flex flex-col">
+          <div className="flex justify-between items-center gap-1">
+            <Icon component={<SubdirectoryArrowRight />} size={16} color="text-secondary-300" />
+            <Input
+              size="xs"
+              type="dropdown"
+              label="X-axis"
+              value={data.xAxisSelected || 'None'}
+              disabled={!data.entitySelected}
+              options={stateConfigPanelOptions.xAxisSelectedOptions.map((option) => option || 'None')}
+              onChange={(option: string | number) => {
+                onUpdateData({ xAxisSelected: String(option) });
+              }}
+            />
+          </div>
+
+          <div className="flex justify-between items-center gap-1">
+            <Icon component={<SubdirectoryArrowRight />} size={16} color="text-secondary-300" />
+            <Input
+              size="xs"
+              type="dropdown"
+              inline
+              label="Y-axis"
+              disabled={!data.entitySelected}
+              value={data.yAxisSelected || 'None'}
+              options={stateConfigPanelOptions.yAxisSelectedOptions.map((option) => option || 'None')}
+              onChange={(option: string | number) => {
+                onUpdateData({ yAxisSelected: String(option) });
+              }}
+            />
+          </div>
+          <div className="flex justify-between items-center gap-1">
+            <Icon component={<SubdirectoryArrowRight />} size={16} color="text-secondary-300" />
+            <Input
+              size="xs"
+              type="dropdown"
+              label="Attribute"
+              disabled={!data.entitySelected}
+              value={data.attributeSelected || 'None'}
+              options={stateConfigPanelOptions.attributeSelectedOptions.map((option) => option || 'None')}
+              onChange={(option: string | number) => {
+                onUpdateData({ attributeSelected: String(option) });
+              }}
+            />
+          </div>
+
+          <div className="flex justify-between items-center ml-3 gap-1">
+            <Icon component={<SubdirectoryArrowRight />} size={16} color="text-secondary-300" />
+            <Input
+              size="xs"
+              type="dropdown"
+              disabled={!data.attributeSelected}
+              label="Value"
+              value={data.attributeValueSelected || 'None'}
+              options={stateConfigPanelOptions.attributeValueSelectedOptions.map((option) => option || 'None')}
+              onChange={(option: string | number) => {
+                onUpdateData({ attributeValueSelected: String(option) });
+              }}
+            />
+          </div>
+        </div>
+      )}
+    </div>
+  );
+};
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/index.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bcc2b4d70d280536724213642dd2e7088efeb5fc
--- /dev/null
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/index.tsx
@@ -0,0 +1 @@
+export { SemSubsConfigPanel } from './SemSubsConfigPanel';
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/semSubsConfigPanel.stories.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/semSubsConfigPanel.stories.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..dbc8e86aa6ed36ad43e56299a38ac5509c3af4bf
--- /dev/null
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/configPanel/semSubsConfigPanel.stories.tsx
@@ -0,0 +1,24 @@
+import React, { useState } from 'react';
+import type { Meta, StoryObj } from '@storybook/react';
+import SemSubsConfigPanel, { SemSubsConfigPanelProps } from '.';
+
+const metaPillDropdown: Meta<typeof SemSubsConfigPanel> = {
+  component: SemSubsConfigPanel,
+  title: 'Visualizations/SemanticSubstrates/configpanel',
+  decorators: [(story) => <div className="flex items-center justify-center w-20 m-11">{story()}</div>],
+};
+
+export default metaPillDropdown;
+
+type Story = StoryObj<typeof SemSubsConfigPanel>;
+
+export const userAddsData: Story = {
+  args: {
+    entitySelectedOptions: ['kamerleden', 'commissies'],
+    attributeSelectedOptions: ['Partij', 'Leeftijd', 'Woonplaats'],
+    valueAttributeSelectedOptions: ['D66', 'VVD', 'PVV', 'DierenPartij'],
+    xAxisSelectedOptions: ['Partij', 'Leeftijd', 'Woonplaats'],
+    yAxisSelectedOptions: ['Partij', 'Leeftijd', 'Woonplaats'],
+    colorNode: '#FFA500',
+  },
+};
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx
index 40e03c4eea3553a5c2ef8483ca2110a098f13b14..b542d9847b675d76396d09f2b9f5840571bf81e8 100644
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/semanticsubstratesvis.tsx
@@ -1,118 +1,183 @@
 import React, { useRef, useState, useMemo, useEffect } from 'react';
-import { ScatterPlot, KeyedScatterplotProps as KeyedScatterPlotProps } from './components/Scatterplot';
-import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
+import { Scatterplot, KeyedScatterplotProps } from './components/Scatterplot';
 import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
-
-import { visualizationColors } from 'config/src/colors';
+import { Button } from '@graphpolaris/shared/lib/components/buttons';
+import { Add } from '@mui/icons-material';
+import { select, selectAll } from 'd3';
 import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 import { findConnectionsNodes, getRegionData, setExtension, filterArray, getUniqueValues } from './components/utils';
-
+import { cloneDeep, isEqual } from 'lodash-es';
 import { Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
 import {
   UserSelection,
   RegionData,
-  DataConfig,
+  DataPanelConfig,
   AugmentedNodeAttributes,
   VisualEdgesConfig,
-  ConnectionFromTo,
+  connectionFromTo,
   AugmentedEdgeAttributes,
   DataPoint,
+  DataFromPanel,
+  VisualRegionConfig,
 } from './components/types';
-import ConfigPanel from './components/ConfigPanel';
-import EdgesLayer, { KeyedEdgesLayerProps } from './components/EdgesLayer';
 
+import EdgesLayer, { KeyedEdgesLayerProps } from './components/EdgesLayer';
 import { MultiGraph } from 'graphology';
-import { select, selectAll } from 'd3';
-
-import { buildGraphology, configVisualRegion, config, numColorsCategorical, marginAxis, isColorCircleFix } from './utils';
-import { Input } from '../../..';
+import { buildGraphology, config, numColorsCategorical, marginAxis, isColorCircleFix, noDataRange, noSelection } from './utils';
+import { SemSubsConfigPanel } from './configPanel';
+import { nodeColorHex } from './components/utils';
 
 export type SemSubstrProps = {
   showColor: boolean;
+  dataPanels: DataFromPanel[];
 };
 
 const settings: SemSubstrProps = {
   showColor: true,
+  dataPanels: [],
 };
 
 const displayName = 'SemSubstrVis';
 
-export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstrProps>) => {
-  const nodes = data.nodes;
-  const edges = data.edges;
-
+export const VisSemanticSubstrates = ({ data, graphMetadata, settings, updateSettings }: VisualizationPropTypes<SemSubstrProps>) => {
+  // for sizing the vis
   const divRef = useRef<HTMLDivElement>(null);
-  const idEdges = useRef<string[][]>([]);
-  const nameEdges = useRef<string[]>([]);
-  const idBrushed = useRef<string[][]>([]);
-
   const [divSize, setDivSize] = useState({ width: 0, height: 0 });
+
+  // avoid mount iteration
+  const isMounted = useRef(false);
+
+  // to render scatterplots
   const [appState, setAppState] = useState({
-    isButtonClicked: false,
-    scatterPlots: [] as KeyedScatterPlotProps[],
+    scatterplots: [] as KeyedScatterplotProps[],
     dataRegions: [] as RegionData[],
   });
+  // to render edges layer
   const [stateEdges, setStateEdges] = useState({
     edgePlotted: [] as KeyedEdgesLayerProps[],
   });
-  const [arrayConnections, setarrayConnections] = useState<ConnectionFromTo[][]>([]);
+
+  // for connecting with config panel
+  const idScatterplotsFromConfig = useRef<number[]>([]);
+  const prevDataPanelsRef = useRef<DataFromPanel[]>([]);
+
+  // for preserve brush information
+  //const idBrushed = useRef<string[][]>([]);
+  const idBrushed = useRef<{ idScatterplot: number; data: string[] }[]>([]);
+
+  // keep track what is the new scatterplot
+  const newScatterplotIs = useRef<string>('');
+
+  // To know the correspondence between scatterplot IDs and edge IDs
+  const IDScatterplot2IDEdge = useRef<number[]>([]);
+  const indexNewEdge = useRef<number>(0);
+  const IDEdgeUpdating = useRef<number>(0);
+  const IDScatterplotR0 = useRef<number>(0);
+  const arrayIDScatterplotR0 = useRef<string[]>([]);
+
+  const IDScatterplotUpdating = useRef<number>(0);
+  // information about edges, useful for brushing
+  const informationEdges = useRef<{ nameEdges: string[]; idEdges: string[][] }>({
+    nameEdges: [],
+    idEdges: [],
+  });
+
+  // information about edges
+  const arrayConnections = useRef<connectionFromTo[][]>([]);
+
+  // to syncronized the data from scatterplots simulation and create the edges
   const [computedData, setComputedData] = useState({
-    region1: [] as DataPoint[],
-    region2: [] as DataPoint[],
+    region1: [] as DataPoint[], // always R0
+    region2: [] as DataPoint[], // last scatterplot added
   });
 
+  // data structure to handle node/edge information
   const augmentedNodes: AugmentedNodeAttributes[] = useMemo(() => {
-    return nodes.map((node: Node) => ({
+    return data.nodes.map((node: Node) => ({
       _id: node._id,
       attributes: node.attributes,
       label: node.label,
     }));
-  }, [nodes]);
+  }, [data]);
 
   const augmentedEdges: AugmentedEdgeAttributes[] = useMemo(() => {
-    return edges.map((edge: any) => ({
-      _id: edge.id,
+    return data.edges.map((edge: any) => ({
+      id: edge.id,
       to: edge.to,
       from: edge.from,
       attributes: edge.attributes,
       label: edge.label,
     }));
-  }, [edges]);
-
-  const attributesArray = nodes.map((node) => node.attributes);
+  }, [data]);
 
   const graphologyGraph: MultiGraph = useMemo(
     () => buildGraphology({ nodes: Object.values(augmentedNodes), edges: Object.values(augmentedEdges) }),
     [augmentedNodes, augmentedEdges],
   );
 
-  const pushElement = (newElement: ConnectionFromTo[]) => {
-    setarrayConnections((prevArray) => [...prevArray, newElement]);
-  };
+  const configVisualRegion = useMemo<VisualRegionConfig>(() => {
+    const baseConfig = {
+      marginPercentage: { top: 0.14, right: 0.15, bottom: 0.2, left: 0.15 },
+      width: divSize.width,
+      widthPercentage: 0.4,
+      height: 300,
+    };
+
+    const margin = {
+      top: baseConfig.marginPercentage.top * baseConfig.height,
+      right: baseConfig.marginPercentage.right * baseConfig.width,
+      bottom: baseConfig.marginPercentage.bottom * baseConfig.height,
+      left: baseConfig.marginPercentage.left * baseConfig.width,
+    };
+
+    const widthMargin = baseConfig.width - margin.right - margin.left;
+    const heightMargin = baseConfig.height - margin.top - margin.bottom;
+
+    return {
+      ...baseConfig,
+      margin,
+      widthMargin,
+      heightMargin,
+    };
+  }, [divSize]);
 
   const configVisualEdges = useRef<VisualEdgesConfig>({
-    width: configVisualRegion.width,
-    height: 2 * configVisualRegion.height,
+    width: divSize.width,
+    height: configVisualRegion.height,
     configRegion: configVisualRegion,
     offsetY: 0,
-    stroke: 'TBD',
+    stroke: config.edges.stroke,
     strokeWidth: config.edges.strokeWidth,
     strokeOpacity: config.edges.strokeOpacity,
   });
 
   const handleBrushClear = useMemo(() => {
-    return (selectedElement: string, idData: string[]): void => {
-      let modifiedString: number = +selectedElement.replace('region', '');
-      idBrushed.current[modifiedString] = [];
-
-      idEdges.current.forEach((edgesR0RN, index) => {
-        if (edgesR0RN.length != 0) {
-          if (idBrushed.current[0].length == 0 && idBrushed.current[index + 1].length == 0) {
-            select(`.edge_region0_to_region${index + 1}`)
+    return (selectedElement: string): void => {
+      let modifiedString: number = +selectedElement.replace('region_', '');
+      //idBrushed.current[modifiedString] = [];
+
+      const indexBrushedR0 = idBrushed.current.findIndex((obj) => obj.idScatterplot === modifiedString);
+      idBrushed.current[indexBrushedR0].data = [];
+
+      informationEdges.current.idEdges.forEach((edgesR0RN, index) => {
+        if (edgesR0RN.length !== 0) {
+          //if (idBrushed.current[0]?.length === 0 && idBrushed.current[index + 1]?.length === 0) {
+          if (
+            idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data.length === 0 &&
+            idBrushed.current.find((obj) => obj.idScatterplot === index + 1)?.data.length === 0
+          ) {
+            select(`.edge_region0_to_region_${index + 1}`)
               .selectAll('path')
               .style('stroke-opacity', 1);
           } else {
-            const edgesVisible = filterArray(idBrushed.current[0], idBrushed.current[index + 1], edgesR0RN, '_fromto_');
+            //const edgesVisible = filterArray(idBrushed.current[0], idBrushed.current[index + 1], edgesR0RN, '_fromto_');
+
+            const edgesVisible = filterArray(
+              idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data ?? [],
+              idBrushed.current.find((obj) => obj.idScatterplot === index + 1)?.data ?? [],
+              edgesR0RN,
+              '_fromto_',
+            );
 
             const edgesVisibleSlash = edgesVisible.map((element) => element.replace(/\//g, '_'));
 
@@ -125,7 +190,7 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
             });
 
             const edgesVisibleSlashDot: string = edgesVisibleSlashNotNum.map((edgeClass) => `.${edgeClass}`).join(',');
-            select(`.edge_region0_to_region${index + 1}`)
+            select(`.edge_region0_to_region_${index + 1}`)
               .selectAll('path')
               .style('stroke-opacity', 0);
             selectAll(edgesVisibleSlashDot).style('stroke-opacity', 1);
@@ -137,18 +202,33 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
 
   const handleBrushUpdate = useMemo(() => {
     return (idElements: string[], selectedElement: string): void => {
-      let modifiedString: number = +selectedElement.replace('region', '');
-      idBrushed.current[modifiedString] = idElements;
+      let modifiedString: number = +selectedElement.replace('region_', '');
+
+      //idBrushed.current[modifiedString] = idElements;
+      const indexBrushedR0 = idBrushed.current.findIndex((obj) => obj.idScatterplot === modifiedString);
+      idBrushed.current[indexBrushedR0].data = idElements;
 
       // iterate over the region pairs: r0-r1, r0-r2, and update visibility of edges based on registered brushed ids
-      idEdges.current.forEach((edgesR0RN, index) => {
+      informationEdges.current.idEdges.forEach((edgesR0RN, index) => {
         if (modifiedString == 0) {
-          if (idBrushed.current[0].length == 0 && idBrushed.current[index + 1].length == 0) {
-            select(`.edge_region0_to_region${index + 1}`)
+          //if (idBrushed.current[0].length == 0 && idBrushed.current[index + 1].length == 0) {
+
+          if (
+            idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data.length === 0 &&
+            idBrushed.current.find((obj) => obj.idScatterplot === index + 1)?.data.length === 0
+          ) {
+            select(`.edge_region0_to_region_${index + 1}`)
               .selectAll('path')
               .style('stroke-opacity', 0);
           } else {
-            const edgesVisible = filterArray(idBrushed.current[0], idBrushed.current[index + 1], edgesR0RN, '_fromto_');
+            //const edgesVisible = filterArray(idBrushed.current[0], idBrushed.current[index + 1], edgesR0RN, '_fromto_');
+
+            const edgesVisible = filterArray(
+              idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data ?? [],
+              idBrushed.current.find((obj) => obj.idScatterplot === index + 1)?.data ?? [],
+              edgesR0RN,
+              '_fromto_',
+            );
 
             if (edgesVisible.length != 0) {
               const edgesVisibleSlash = edgesVisible.map((element) => element.replace(/\//g, '_'));
@@ -161,25 +241,34 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
               });
 
               const edgesVisibleSlashDot: string = edgesVisibleSlashNotNum.map((edgeClass) => `.${edgeClass}`).join(',');
-
-              select(`.edge_region0_to_region${index + 1}`)
+              select(`.edge_region0_to_region_${index + 1}`)
                 .selectAll('path')
                 .style('stroke-opacity', 0);
               selectAll(edgesVisibleSlashDot).style('stroke-opacity', 1);
             } else {
-              select(`.edge_region0_to_region${index + 1}`)
+              select(`.edge_region0_to_region_${index + 1}`)
                 .selectAll('path')
                 .style('stroke-opacity', 0);
             }
           }
         } else if (modifiedString == index + 1) {
-          if (idBrushed.current[0].length == 0 && idBrushed.current[index + 1].length == 0) {
-            select(`.edge_region0_to_region${index + 1}`)
+          //if (idBrushed.current[0].length == 0 && idBrushed.current[index + 1].length == 0) {
+
+          if (
+            idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data.length === 0 &&
+            idBrushed.current.find((obj) => obj.idScatterplot === index + 1)?.data.length === 0
+          ) {
+            select(`.edge_region0_to_region_${index + 1}`)
               .selectAll('path')
               .style('stroke-opacity', 0);
           } else {
-            const edgesVisible = filterArray(idBrushed.current[0], idBrushed.current[index + 1], edgesR0RN, '_fromto_');
-
+            //const edgesVisible = filterArray(idBrushed.current[0], idBrushed.current[index + 1], edgesR0RN, '_fromto_');
+            const edgesVisible = filterArray(
+              idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data ?? [],
+              idBrushed.current.find((obj) => obj.idScatterplot === index + 1)?.data ?? [],
+              edgesR0RN,
+              '_fromto_',
+            );
             if (edgesVisible.length != 0) {
               const edgesVisibleSlash = edgesVisible.map((element) => element.replace(/\//g, '_'));
               const edgesVisibleSlashNotNum = edgesVisibleSlash.map((item) => {
@@ -192,12 +281,12 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
 
               const edgesVisibleSlashDot: string = edgesVisibleSlashNotNum.map((edgeClass) => `.${edgeClass}`).join(',');
 
-              select(`.edge_region0_to_region${index + 1}`)
+              select(`.edge_region0_to_region_${index + 1}`)
                 .selectAll('path')
                 .style('stroke-opacity', 0);
               selectAll(edgesVisibleSlashDot).style('stroke-opacity', 1);
             } else {
-              select(`.edge_region0_to_region${index + 1}`)
+              select(`.edge_region0_to_region_${index + 1}`)
                 .selectAll('path')
                 .style('stroke-opacity', 0);
             }
@@ -207,67 +296,391 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
     };
   }, []);
 
-  const handleResultJitter = (data: DataPoint[]) => {
-    setComputedData((prevData) => {
-      if (prevData.region1.length === 0) {
-        return {
-          ...prevData,
-          region1: data,
-        };
-      } else {
-        return {
-          ...prevData,
-          region2: data,
-        };
-      }
-    });
+  const handleResultJitter = (data: DataPoint[], idScatterplot: number) => {
+    //console.log('DONE JITTER ', idScatterplot);
+    if (idScatterplot == IDScatterplotR0.current) {
+      setComputedData((prevData) => ({
+        ...prevData,
+        region1: data,
+      }));
+    } else {
+      setComputedData((prevData) => ({
+        ...prevData,
+        region2: data,
+      }));
+    }
   };
 
   useEffect(() => {
-    if (divRef.current) {
-      setDivSize({ width: divRef.current.getBoundingClientRect().width, height: divRef.current.getBoundingClientRect().height });
+    function handleResize() {
+      if (divRef.current) {
+        setDivSize({ width: divRef.current.getBoundingClientRect().width, height: divRef.current.getBoundingClientRect().height });
+      }
+    }
+
+    window.addEventListener('resize', handleResize);
+    if (divRef.current) new ResizeObserver(handleResize).observe(divRef.current);
+
+    return () => {
+      window.removeEventListener('resize', handleResize);
+    };
+  }, []);
+
+  useEffect(() => {
+    if (idBrushed.current.length != 0) {
+      if (idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data.length != 0) {
+        handleBrushUpdate(idBrushed.current.find((obj) => obj.idScatterplot === 0)?.data ?? [], 'region_0');
+      }
     }
-  }, [divRef]);
+  }, [stateEdges]);
 
+  // manages the addition of edges elements
   useEffect(() => {
+    //console.log('computedData', computedData.region1.length > 0 && computedData.region2.length > 0, computedData, newScatterplotIs.current);
     if (computedData.region1.length > 0 && computedData.region2.length > 0) {
-      let colorEdges: string;
+      if (newScatterplotIs.current === 'add' || !stateEdges.edgePlotted[IDEdgeUpdating.current]) {
+        // !FIXME !stateEdges.edgePlotted[IDEdgeUpdating.current] was added to solve bug, but now only last scatter shows edges
+
+        //console.log('ADD EDGES ');
+        const temporalConfigVisualEdges: VisualEdgesConfig = {
+          ...configVisualEdges.current,
+          height: configVisualRegion.height * appState.scatterplots.length,
+          offsetY: configVisualRegion.height * (appState.scatterplots.length - 2),
+        };
+
+        const visualConfigRef = { current: temporalConfigVisualEdges } as React.MutableRefObject<VisualEdgesConfig>;
+
+        const newEdgePlot: KeyedEdgesLayerProps = {
+          key: appState.scatterplots.length.toString(),
+          dataConnections: arrayConnections.current[indexNewEdge.current - 1],
+          visualConfig: visualConfigRef,
+          visualScatterplot: configVisualRegion,
+          data1: computedData.region1,
+          data2: computedData.region2,
+          nameEdges: informationEdges.current.nameEdges[indexNewEdge.current - 1],
+        };
+
+        //console.log('newEdgePlot', newEdgePlot);
+        setStateEdges({
+          edgePlotted: [...stateEdges.edgePlotted, newEdgePlot],
+        });
+
+        // update edges
+      } else if (IDScatterplotUpdating.current === IDScatterplotR0.current) {
+        //console.log('UPDATE EDGES of R0 ');
+        const stateEdgesTemporal = cloneDeep(stateEdges.edgePlotted);
+
+        const modifiedStateEdges = stateEdgesTemporal.map((obj, index) => {
+          const data1 = (stateEdgesTemporal[index].data1 = computedData.region1);
+          const dataConnections = arrayConnections.current[index];
+
+          const temporalConfigVisualEdges: VisualEdgesConfig = {
+            ...configVisualEdges.current,
+            height: configVisualRegion.height * (index + 2),
+            offsetY: configVisualRegion.height * index,
+          };
+
+          const visualConfigRef = { current: temporalConfigVisualEdges } as React.MutableRefObject<VisualEdgesConfig>;
+
+          return {
+            ...obj,
+            visualConfig: visualConfigRef,
+            data1,
+            dataConnections,
+          };
+        });
+
+        setStateEdges({
+          edgePlotted: modifiedStateEdges,
+        });
+      } else if (stateEdges.edgePlotted[IDEdgeUpdating.current]) {
+        //console.log('UPDATE EDGES NO R0');
+
+        //console.log('informationEdges.current.nameEdges ', informationEdges.current.nameEdges);
+
+        const stateEdgesTemporal = cloneDeep(stateEdges.edgePlotted);
+
+        //console.log('IDEdgeUpdating', IDEdgeUpdating.current, stateEdges.edgePlotted, stateEdgesTemporal[IDEdgeUpdating.current]);
+        stateEdgesTemporal[IDEdgeUpdating.current].data1 = computedData.region1; // necessary ?
+        stateEdgesTemporal[IDEdgeUpdating.current].data2 = computedData.region2;
+        stateEdgesTemporal[IDEdgeUpdating.current].dataConnections = arrayConnections.current[IDEdgeUpdating.current];
+        setStateEdges({
+          edgePlotted: stateEdgesTemporal,
+        });
+      } else {
+        console.error('Error: Edge not found', IDScatterplotUpdating.current, stateEdges.edgePlotted);
+      }
+    }
+  }, [computedData.region2, computedData.region1]);
+
+  function createNewScatterplot(newPanel: DataFromPanel) {
+    //console.log('createNewScatterplot:', newPanel, 'IDScatterplotR0: ', IDScatterplotR0.current);
+    if (idScatterplotsFromConfig.current.length === 0 && !IDScatterplotR0.current) {
+      IDScatterplotR0.current = newPanel.id;
+      //console.log('newPanel ', newPanel);
+    }
 
-      if (isColorCircleFix) {
-        colorEdges = config.edges.stroke;
+    idScatterplotsFromConfig.current.push(newPanel.id);
+    newScatterplotIs.current = 'add';
+    return handleNewDataRegion(newPanel.data, newPanel.id);
+  }
+
+  function removeScatterplot(deletedPanel?: DataFromPanel) {
+    if (deletedPanel) {
+      // checks if deleted one is R0
+      if (deletedPanel.id === IDScatterplotR0.current) {
+        // !FIXME: dont allow delete of R0
+        /*
+        setComputedData((prevState) => ({
+          ...prevState,
+          region1: [],
+        }));
+        */
       } else {
-        colorEdges = config.edges.stroke;
+        // checks if deleted one is RX
+
+        // Delete scatterplot and associated variables
+        idScatterplotsFromConfig.current = idScatterplotsFromConfig.current.filter((item) => item !== deletedPanel.id);
+        setAppState((prevState) => ({
+          scatterplots: prevState.scatterplots.filter((scatterplot) => scatterplot.key !== deletedPanel.id),
+          dataRegions: prevState.dataRegions.filter((_, index) => prevState.scatterplots[index].key !== deletedPanel.id),
+        }));
+
+        idBrushed.current = idBrushed.current.filter((item) => item.idScatterplot !== deletedPanel.id);
+
+        // Delete edges
+        const removeIndexEdge = informationEdges.current.nameEdges.findIndex(
+          (name) => name === `edge_region0_to_region_${deletedPanel.id}`,
+        );
+        const stateEdgesTemporal = cloneDeep(stateEdges.edgePlotted);
+        const stateEdgesTemporalFiltered = stateEdgesTemporal.filter((_, index) => index !== removeIndexEdge);
+
+        if (removeIndexEdge != -1) {
+          // check if it need it
+          IDScatterplot2IDEdge.current = IDScatterplot2IDEdge.current.filter((_, index) => index !== removeIndexEdge);
+
+          informationEdges.current.idEdges = informationEdges.current.idEdges.filter((_, index) => index !== removeIndexEdge);
+          informationEdges.current.nameEdges = informationEdges.current.nameEdges.filter((_, index) => index !== removeIndexEdge);
+          arrayConnections.current = arrayConnections.current.filter((_, index) => index !== removeIndexEdge);
+
+          const modifiedStateEdges = stateEdgesTemporalFiltered.map((obj, index) => {
+            const temporalConfigVisualEdges: VisualEdgesConfig = {
+              ...configVisualEdges.current,
+              height: configVisualRegion.height * (index + 2),
+              offsetY: configVisualRegion.height * index,
+            };
+
+            const visualConfigRef = { current: temporalConfigVisualEdges } as React.MutableRefObject<VisualEdgesConfig>;
+
+            return {
+              ...obj,
+              visualConfig: visualConfigRef,
+            };
+          });
+
+          setStateEdges({
+            edgePlotted: modifiedStateEdges,
+          });
+        }
+
+        indexNewEdge.current--;
+      }
+    }
+  }
+
+  function updateScatterplot(updatedPanel?: DataFromPanel) {
+    if (updatedPanel) {
+      //console.log('updatedPanel', updatedPanel, appState.scatterplots);
+
+      const idScatterplotUpdate = appState.scatterplots.findIndex((item) => item.key === updatedPanel.id);
+      newScatterplotIs.current = 'update';
+      if (idScatterplotUpdate !== -1) {
+        //handleBrushClear(`region_${indexOnState}`);
+
+        if (!updatedPanel.data.entitySelected) return;
+        //console.log('UPDATE: appState ', idScatterplotUpdate);
+
+        const regionUserSelection: UserSelection = {
+          name: appState.dataRegions[idScatterplotUpdate].name,
+          nodeName: updatedPanel.data.entitySelected,
+          attributeAsRegion: updatedPanel.data.attributeSelected,
+          attributeAsRegionSelection: updatedPanel.data.attributeValueSelected,
+          placement: {
+            xAxis: updatedPanel.data.xAxisSelected,
+            yAxis: updatedPanel.data.yAxisSelected,
+            colorNodes: appState.dataRegions[idScatterplotUpdate].colorNodes,
+            colorNodesStroke: appState.dataRegions[idScatterplotUpdate].colorNodesStroke,
+            colorFillBrush: config.brush.fillClr,
+            colorStrokeBrush: config.brush.strokeClr,
+          },
+        };
+
+        const regionDataUser: RegionData = getRegionData(augmentedNodes, regionUserSelection);
+
+        let xScaleShared: any;
+        let yScaleShared: any;
 
-        if (appState.scatterPlots.length < numColorsCategorical) {
-          colorEdges = visualizationColors.GPCat.colors[14][appState.scatterPlots.length + 1];
+        if (!regionDataUser.xAxisName && !regionDataUser.yAxisName) {
+          xScaleShared = noDataRange;
+          yScaleShared = noDataRange;
+        } else if (regionDataUser.xAxisName && regionDataUser.yAxisName) {
+          if (typeof regionDataUser.xData[0] != 'number') {
+            const xExtent = getUniqueValues(regionDataUser.xData);
+            xScaleShared = xExtent;
+          } else {
+            const xExtent: [number, number] = setExtension(marginAxis, [...regionDataUser.xData, ...regionDataUser.xData]);
+            xScaleShared = xExtent;
+          }
+
+          if (typeof regionDataUser.yData[0] != 'number') {
+            const yExtent = getUniqueValues(regionDataUser.yData);
+            yScaleShared = yExtent;
+          } else {
+            const yExtent: [number, number] = setExtension(marginAxis, [...regionDataUser.yData, ...regionDataUser.yData]);
+            yScaleShared = yExtent;
+          }
+        } else if (regionDataUser.xAxisName) {
+          if (typeof regionDataUser.xData[0] != 'number') {
+            const xExtent = getUniqueValues(regionDataUser.xData);
+            xScaleShared = xExtent;
+
+            yScaleShared = noDataRange;
+          } else {
+            const xExtent: string[] | number[] = setExtension(marginAxis, [...regionDataUser.xData, ...regionDataUser.xData]);
+            xScaleShared = xExtent;
+
+            yScaleShared = noDataRange;
+          }
+        } else if (regionDataUser.yAxisName) {
+          if (typeof regionDataUser.yData[0] != 'number') {
+            const yExtent = getUniqueValues(regionDataUser.yData);
+            yScaleShared = yExtent;
+
+            xScaleShared = noDataRange;
+          } else {
+            const yExtent: [number, number] = setExtension(marginAxis, [...regionDataUser.yData, ...regionDataUser.yData]);
+
+            yScaleShared = yExtent;
+
+            xScaleShared = noDataRange;
+          }
+        }
+
+        const updatedScatterplot = {
+          key: appState.scatterplots[idScatterplotUpdate].key,
+          data: regionDataUser,
+          visualConfig: configVisualRegion,
+          xScaleRange: xScaleShared,
+          yScaleRange: yScaleShared,
+          onBrushUpdate: handleBrushUpdate,
+          onResultJitter: handleResultJitter,
+          onBrushClear: handleBrushClear,
+        };
+
+        // modify scatterplot
+        setAppState((prevState) => {
+          const scatterplots = [...prevState.scatterplots];
+          scatterplots[idScatterplotUpdate] = updatedScatterplot;
+          return { ...prevState, scatterplots };
+        });
+
+        // modify edge layer
+        const arrayIDs = regionDataUser.idData.map((item) => item);
+        IDScatterplotUpdating.current = idScatterplotUpdate;
+        //console.log('IDScatterplotUpdating', IDScatterplotUpdating.current, IDScatterplotR0.current, idScatterplotUpdate);
+        if (idScatterplotUpdate === IDScatterplotR0.current) {
+          const stateEdgesTemporal = cloneDeep(stateEdges.edgePlotted);
+
+          stateEdgesTemporal.forEach((obj, index) => {
+            const IDsConnectedScatterplot = obj.data2.map((value) => value.id);
+            const [connectedD, connectedD2] = findConnectionsNodes(
+              arrayIDs,
+              IDsConnectedScatterplot,
+              graphologyGraph,
+              regionDataUser.label,
+              true,
+            );
+
+            informationEdges.current.idEdges[index] = connectedD2;
+            arrayConnections.current[index] = connectedD;
+          });
         } else {
-          colorEdges = visualizationColors.GPCat.colors[14][appState.scatterPlots.length + 1 - numColorsCategorical];
+          // get indices to modify
+          const IDEdgeBasedOnIDscatterplot = IDScatterplot2IDEdge.current[idScatterplotUpdate - 1];
+          IDEdgeUpdating.current = IDEdgeBasedOnIDscatterplot;
+
+          const indexEdgeInvolved = informationEdges.current.nameEdges.findIndex(
+            (name) => name === `edge_region0_to_region_${idScatterplotUpdate}`,
+          );
+          //console.log('edge involved: ', IDEdgeBasedOnIDscatterplot, indexEdgeInvolved);
+          // modify data structures
+          const [connectedD, connectedD2] = findConnectionsNodes(
+            arrayIDs,
+            appState.dataRegions[IDScatterplotR0.current].idData,
+            graphologyGraph,
+            regionDataUser.label,
+          );
+
+          informationEdges.current.idEdges[IDEdgeBasedOnIDscatterplot] = connectedD2;
+          arrayConnections.current[IDEdgeBasedOnIDscatterplot] = connectedD;
         }
+
+        //
+      } else {
+        console.log('Error: Scatterplot not found', idScatterplotUpdate, updatedPanel.id, appState.scatterplots);
       }
+    }
+  }
 
-      configVisualEdges.current = {
-        ...configVisualEdges.current,
-        stroke: colorEdges,
-      };
+  // manages when the settingsPanel changes
+  useEffect(() => {
+    if (isMounted.current && configVisualRegion.width > 0 && !isEqual(settings.dataPanels, prevDataPanelsRef.current)) {
+      const prevDataPanels = prevDataPanelsRef.current;
+      const currentDataPanels = settings.dataPanels;
+
+      if (currentDataPanels.length > prevDataPanels.length) {
+        // Element added
+        //console.log('ADD SCATTERPLOT');
+        const newPanel = currentDataPanels.filter((panel: DataFromPanel) => !prevDataPanels.some((prevPanel) => prevPanel.id === panel.id));
+        const newDataRegions = [];
+        const newScatterplots = [];
+        for (const panel of newPanel) {
+          const { dataRegions, scatterplot } = createNewScatterplot(panel);
+          newDataRegions.push(dataRegions);
+          newScatterplots.push(scatterplot);
+        }
+        setAppState({
+          scatterplots: [...appState.scatterplots, ...newScatterplots],
+          dataRegions: [...appState.dataRegions, ...newDataRegions],
+        });
+      } else if (currentDataPanels.length < prevDataPanels.length) {
+        // Element deleted
+        const deletedPanel = prevDataPanels.find(
+          (prevPanel) => !currentDataPanels.some((panel: DataFromPanel) => panel.id === prevPanel.id),
+        );
 
-      const newEdgePlot: KeyedEdgesLayerProps = {
-        key: appState.scatterPlots.length.toString(),
-        dataConnections: arrayConnections[appState.scatterPlots.length - 2],
-        visualConfig: configVisualEdges,
-        data1: computedData.region1,
-        data2: computedData.region2,
-        nameEdges: nameEdges.current[appState.dataRegions.length - 2],
-        width: 0,
-        nameRegions: [appState.dataRegions[0].attributeSelected, appState.dataRegions[appState.dataRegions.length - 1].attributeSelected],
-      };
+        //console.log('DELETE SCATTERPLOT: ', deletedPanel);
 
-      setStateEdges({
-        edgePlotted: [...stateEdges.edgePlotted, newEdgePlot],
-      });
+        removeScatterplot(deletedPanel);
+      } else {
+        // Element updated
+        const updatedPanel = currentDataPanels.find((panel: DataFromPanel) => {
+          const prevPanel = prevDataPanels.find((prevPanel) => prevPanel.id === panel.id);
+          return prevPanel && !isEqual(prevPanel.data, panel.data);
+        });
+        //console.log('UPDATE SCATTERPLOT: ', updatedPanel);
+        if (updatedPanel !== undefined) {
+          updateScatterplot(updatedPanel);
+        }
+      }
+      prevDataPanelsRef.current = currentDataPanels;
+    } else {
+      isMounted.current = true;
     }
-  }, [computedData.region2]);
+  }, [settings.dataPanels, configVisualRegion]);
+  //}, [settings.dataPanels]);
 
-  const handleUpdateData = (data: DataConfig) => {
+  const handleNewDataRegion = (data: DataPanelConfig, idNew: number) => {
     let colorCircle: string;
     let strokeCircle: string;
 
@@ -275,23 +688,23 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
       colorCircle = config.circle.fillClr;
       strokeCircle = config.circle.strokeClr;
     } else {
-      if (appState.scatterPlots.length < numColorsCategorical) {
-        colorCircle = visualizationColors.GPCat.colors[14][appState.scatterPlots.length + 1];
+      if (idNew < numColorsCategorical) {
+        colorCircle = nodeColorHex(idNew + 1);
       } else {
-        colorCircle = visualizationColors.GPCat.colors[14][appState.scatterPlots.length + 1 - numColorsCategorical];
+        colorCircle = nodeColorHex(idNew + 1 - numColorsCategorical);
       }
 
       strokeCircle = config.circle.strokeClr;
     }
 
     const regionUserSelection: UserSelection = {
-      name: `region${appState.scatterPlots.length}`,
-      nodeName: data.entityVertical,
-      attributeAsRegion: data.attributeEntity,
+      name: `region_${idNew}`,
+      nodeName: data.entitySelected,
+      attributeAsRegion: data.attributeSelected,
       attributeAsRegionSelection: data.attributeValueSelected,
       placement: {
-        xAxis: data.orderNameXAxis,
-        yAxis: data.orderNameYAxis,
+        xAxis: data.xAxisSelected,
+        yAxis: data.yAxisSelected,
         colorNodes: colorCircle,
         colorNodesStroke: strokeCircle,
         colorFillBrush: config.brush.fillClr,
@@ -304,7 +717,10 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
     let xScaleShared: any;
     let yScaleShared: any;
 
-    if (regionDataUser.xData.length != 0 && regionDataUser.yData.length != 0) {
+    if (!regionDataUser.xAxisName && !regionDataUser.yAxisName) {
+      xScaleShared = noDataRange;
+      yScaleShared = noDataRange;
+    } else if (regionDataUser.xAxisName && regionDataUser.yAxisName) {
       if (typeof regionDataUser.xData[0] != 'number') {
         const xExtent = getUniqueValues(regionDataUser.xData);
         xScaleShared = xExtent;
@@ -312,7 +728,6 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
         const xExtent: [number, number] = setExtension(marginAxis, [...regionDataUser.xData, ...regionDataUser.xData]);
         xScaleShared = xExtent;
       }
-
       if (typeof regionDataUser.yData[0] != 'number') {
         const yExtent = getUniqueValues(regionDataUser.yData);
         yScaleShared = yExtent;
@@ -320,100 +735,92 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
         const yExtent: [number, number] = setExtension(marginAxis, [...regionDataUser.yData, ...regionDataUser.yData]);
         yScaleShared = yExtent;
       }
-    } else if (regionDataUser.xData.length != 0) {
+    } else if (regionDataUser.xAxisName) {
       if (typeof regionDataUser.xData[0] != 'number') {
         const xExtent = getUniqueValues(regionDataUser.xData);
         xScaleShared = xExtent;
-
-        yScaleShared = [-1, 1];
+        yScaleShared = noDataRange;
       } else {
         const xExtent: string[] | number[] = setExtension(marginAxis, [...regionDataUser.xData, ...regionDataUser.xData]);
         xScaleShared = xExtent;
-
-        yScaleShared = [-1, 1];
+        yScaleShared = noDataRange;
       }
-    } else if (regionDataUser.yData.length != 0) {
+    } else if (regionDataUser.yAxisName) {
       if (typeof regionDataUser.yData[0] != 'number') {
         const yExtent = getUniqueValues(regionDataUser.yData);
         yScaleShared = yExtent;
-
-        xScaleShared = [-1, 1];
+        xScaleShared = noDataRange;
       } else {
         const yExtent: [number, number] = setExtension(marginAxis, [...regionDataUser.yData, ...regionDataUser.yData]);
-
         yScaleShared = yExtent;
-
-        xScaleShared = [-1, 1];
+        xScaleShared = noDataRange;
       }
     }
 
     const arrayIDs = regionDataUser.idData.map((item) => item);
-    const newScatterPlot: KeyedScatterPlotProps = {
-      key: appState.scatterPlots.length,
+
+    // update scatterplot state
+
+    const newScatterplot: KeyedScatterplotProps = {
+      key: idNew,
       data: regionDataUser,
       visualConfig: configVisualRegion,
       xScaleRange: xScaleShared,
       yScaleRange: yScaleShared,
-      width: 0,
       onBrushUpdate: handleBrushUpdate,
       onResultJitter: handleResultJitter,
       onBrushClear: handleBrushClear,
     };
 
-    setAppState({
-      ...appState,
-      scatterPlots: [...appState.scatterPlots, newScatterPlot],
-      dataRegions: [...appState.dataRegions, regionDataUser],
-    });
-
-    idBrushed.current[appState.scatterPlots.length] = [];
+    idBrushed.current.push({ idScatterplot: idNew, data: [] });
 
-    if (appState.scatterPlots.length >= 2) {
-      configVisualEdges.current = {
-        ...configVisualEdges.current,
-        height: configVisualEdges.current.height + configVisualRegion.height * (appState.scatterPlots.length - 1),
-        offsetY: configVisualRegion.height * (appState.scatterPlots.length - 1),
-      };
-    }
-
-    if (appState.scatterPlots.length == 0) {
+    if (IDScatterplotR0.current === idNew) {
+      arrayIDScatterplotR0.current = arrayIDs;
     } else {
       if (graphologyGraph) {
+        if (IDScatterplot2IDEdge.current) {
+          IDScatterplot2IDEdge.current[idNew - 1] = indexNewEdge.current;
+        }
         const [connectedD, connectedD2] = findConnectionsNodes(
           arrayIDs,
-          appState.dataRegions[0].idData,
+          arrayIDScatterplotR0.current,
           graphologyGraph,
           regionDataUser.label,
         );
 
-        idEdges.current.push(connectedD2);
-
-        pushElement(connectedD);
-
-        nameEdges.current.push(`edge_region0_to_${regionUserSelection.name}`);
+        informationEdges.current.nameEdges.push(`edge_region0_to_${regionUserSelection.name}`);
+        //console.log('informationEdges ', informationEdges.current.nameEdges);
+        informationEdges.current.idEdges.push(connectedD2);
+        arrayConnections.current.push(connectedD);
+        indexNewEdge.current++;
       }
     }
+
+    return {
+      scatterplot: newScatterplot,
+      dataRegions: regionDataUser,
+    };
   };
 
   return (
-    <div className="w-full font-inter overflow-x-hidden overflow-y-hidden">
-      <div className="w-full  flex flex-row justify-center">
-        <ConfigPanel data={augmentedNodes} onUpdateData={handleUpdateData} />
-      </div>
+    <div className="w-full font-inter overflow-x-hidden ">
       <div className="w-full relative" ref={divRef}>
-        {divSize.width > 0 && (
+        {configVisualRegion.width > 0 && appState.scatterplots.some((s) => s.visualConfig.width > 0) && (
           <>
             <div className="w-full regionContainer z-0">
-              {appState.scatterPlots.map((scatterPlot) => (
-                <ScatterPlot {...scatterPlot} width={divSize.width} />
+              {appState.scatterplots.map((scatterplot) => (
+                <Scatterplot {...scatterplot} />
               ))}
             </div>
             <div className="pointer-events-none absolute top-0 w-full flex flex-row justify-center">
-              {stateEdges.edgePlotted.map((edgePlot, index) => (
-                <div key={index} className="absolute">
-                  <EdgesLayer {...edgePlot} width={divSize.width} />
-                </div>
-              ))}
+              {stateEdges.edgePlotted.map(
+                (edegePlot, index) =>
+                  edegePlot.dataConnections && (
+                    <div key={index} className="absolute">
+                      <EdgesLayer {...edegePlot} />
+                    </div>
+                  ),
+              )}
             </div>
           </>
         )}
@@ -422,10 +829,101 @@ export const VisSemanticSubstrates = ({ data }: VisualizationPropTypes<SemSubstr
   );
 };
 
-const SemSubstrSettings = ({ settings, updateSettings }: VisualizationSettingsPropTypes<SemSubstrProps>) => {
+const SemSubstrSettings = ({ settings, updateSettings, graphMetadata }: VisualizationSettingsPropTypes<SemSubstrProps>) => {
+  useEffect(() => {
+    // setup default scatterplots
+
+    if (settings.dataPanels.length === 0 && graphMetadata.nodes.labels.length > 0) {
+      const panels = graphMetadata.nodes.labels.map((nodeName, index) => {
+        return {
+          id: index,
+          data: {
+            entitySelected: nodeName,
+            attributeSelected: undefined,
+            attributeValueSelected: undefined,
+            xAxisSelected: undefined,
+            yAxisSelected: undefined,
+          },
+          settingsOpen: true,
+        };
+      });
+
+      updateDataPanels([...settings.dataPanels, ...panels]);
+    }
+  }, [graphMetadata]);
+
+  const updateDataPanels = (updatedData: DataFromPanel[]) => {
+    const newConfiguration = {
+      ...settings,
+      dataPanels: updatedData,
+    };
+
+    if (!isEqual(settings, newConfiguration)) {
+      updateSettings(newConfiguration);
+    } else {
+    }
+  };
+
+  const addPanel = (data?: DataPanelConfig) => {
+    const nextId = settings.dataPanels.length === 0 ? 0 : settings.dataPanels[settings.dataPanels.length - 1].id + 1;
+
+    if (!data) {
+      const firstNodeName = graphMetadata.nodes.labels?.[0];
+      data = {
+        entitySelected: firstNodeName,
+        attributeSelected: undefined,
+        attributeValueSelected: undefined,
+        xAxisSelected: undefined,
+        yAxisSelected: undefined,
+      };
+    }
+
+    const newPanelData = {
+      id: nextId,
+      data: data,
+      settingsOpen: true,
+    };
+    updateDataPanels([...settings.dataPanels, newPanelData]);
+  };
+
+  const getDataFromPanel = (data: DataPanelConfig, id: number) => {
+    const updatedData = settings.dataPanels.map((panel) => (panel.id === id ? { ...panel, data } : panel));
+    updateDataPanels(updatedData);
+    return updatedData;
+  };
+
+  const handleDeletePanel = (id: number) => {
+    const updatedPanelData = settings.dataPanels.filter((panel) => panel.id !== id);
+    updateDataPanels(updatedPanelData);
+  };
+
   return (
     <SettingsContainer>
-      <Input type="boolean" label="Show color" value={settings.showColor} onChange={(val) => updateSettings({ showColor: val })} />
+      <div className="">
+        <div className="flex justify-between items-center px-3 py-1">
+          <span className="text-xs font-semibold">Substrates</span>
+          <Button variantType="secondary" variant="ghost" size="sm" iconComponent={<Add />} onClick={() => addPanel()} />
+        </div>
+        {settings.dataPanels.map((panel, index) => (
+          <SemSubsConfigPanel
+            dataFromPanel={panel}
+            key={panel.id}
+            colorNode={nodeColorHex(panel.id + 1)}
+            onCollapse={(isOpen: boolean) => {
+              const updatedData = settings.dataPanels.map((panelData) =>
+                panelData.id === panel.id ? { ...panelData, settingsOpen: isOpen } : panelData,
+              );
+              //updateDataPanels(updatedData);
+            }}
+            graphMetaData={graphMetadata}
+            onUpdateData={(data) => {
+              getDataFromPanel({ ...panel.data, ...data }, panel.id);
+            }}
+            isFirstPanel={index === 0}
+            onDelete={() => handleDeletePanel(panel.id)}
+          />
+        ))}
+      </div>
     </SettingsContainer>
   );
 };
diff --git a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/utils.ts b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/utils.ts
index 3c224437d292546b0384e53eeb46135d08835c93..f622beab65176c707f8c5dd047ec20b5e7f6a28c 100644
--- a/libs/shared/lib/vis/visualizations/semanticsubstratesvis/utils.ts
+++ b/libs/shared/lib/vis/visualizations/semanticsubstratesvis/utils.ts
@@ -1,7 +1,10 @@
 import { visualizationColors } from 'config';
 import { MultiGraph } from 'graphology';
-import { AugmentedEdgeAttributes, GraphData, VisualRegionConfig } from './components/types';
-import { GraphQueryResult, Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
+import { GraphData } from './components/types';
+import { Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice';
+
+export const noDataRange = [-1, 1];
+export const noSelection = 'None';
 
 const buildGraphology = (data: GraphData): MultiGraph => {
   const graph = new MultiGraph();
@@ -34,7 +37,8 @@ const buildGraphology = (data: GraphData): MultiGraph => {
 };
 
 const numColorsCategorical = visualizationColors.GPCat.colors[14].length;
-export const isColorCircleFix = true;
+export const isColorCircleFix = false;
+
 let config: any = {};
 if (isColorCircleFix) {
   config = {
@@ -43,7 +47,7 @@ if (isColorCircleFix) {
       strokeClr: 'hsl(var(--clr-sec--600))',
     },
     edges: {
-      stroke: 'bg-primary-600',
+      stroke: 'bg-primary-800',
       strokeWidth: '2',
       strokeOpacity: '0.7',
     },
@@ -60,7 +64,7 @@ if (isColorCircleFix) {
       strokeClr: 'hsl(var(--clr-sec--500))',
     },
     edges: {
-      stroke: 'NO_USED',
+      stroke: 'hsl(var(--clr-sec--300))',
       strokeWidth: '2',
       strokeOpacity: '0.7',
     },
@@ -73,24 +77,4 @@ if (isColorCircleFix) {
 
 const marginAxis = 0.2;
 
-const configVisualRegion: VisualRegionConfig = {
-  marginPercentage: { top: 0.14, right: 0.15, bottom: 0.2, left: 0.15 },
-  margin: { top: 0.0, right: 0.0, bottom: 0.0, left: 0.0 },
-  width: 600,
-  widthPercentage: 0.4,
-  height: 300,
-  widthMargin: 0.0,
-  heightMargin: 0.0,
-};
-
-configVisualRegion.margin = {
-  top: configVisualRegion.marginPercentage.top * configVisualRegion.height,
-  right: configVisualRegion.marginPercentage.right * configVisualRegion.width,
-  bottom: configVisualRegion.marginPercentage.bottom * configVisualRegion.height,
-  left: configVisualRegion.marginPercentage.left * configVisualRegion.width,
-};
-
-configVisualRegion.widthMargin = configVisualRegion.width - configVisualRegion.margin.right - configVisualRegion.margin.left;
-configVisualRegion.heightMargin = configVisualRegion.height - configVisualRegion.margin.top - configVisualRegion.margin.bottom;
-
-export { buildGraphology, numColorsCategorical, config, configVisualRegion, marginAxis };
+export { buildGraphology, numColorsCategorical, config, marginAxis };