Skip to content

Commit 9f36203

Browse files
Merge pull request #27 from sightmachine/ENG-721_show_hidden
[ENG-721] Show_hidden, Bonus Bug Fix
2 parents bacdba5 + c17592d commit 9f36203

11 files changed

Lines changed: 252 additions & 25 deletions

File tree

docs/entities/machine.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,50 @@ Machines are just that, machines in factories. The machine object is how the Si
44
## Functions
55

66
### get_type_from_machine
7-
The get_type_from_machine function allows you to get the type of any machine from it's name and is called this way:
7+
The get_type_from_machine function allows you to get the type of any machine from it's name(or display name) and is called this way:
88
```
99
cli.get_type_from_machine(machine_name)
1010
```
1111

1212
And will return something like the following:
1313
```
1414
'Lasercut'
15+
```
16+
17+
### get_machine_schema
18+
The get_machine_schema functions returns the fields of the machine schema for a given machine source and is called this way:
19+
```
20+
cli.get_machine_schema(machine_source, types, show_hidden, return_mtype)
21+
```
22+
23+
The only required field in this case is the machine_source, we will go over each variable in a second. The function will return a pandas data frame that looks like the following:
24+
```
25+
name display type
26+
0 stats__Alarms__val Alarms float
27+
1 stats__BLOCKED__val BLOCKED float
28+
2 stats__DOWN__val DOWN float
29+
3 stats__DefectCategory__val Defect Category string
30+
```
31+
32+
#### machine_source
33+
This is the name of the machine that you are trying to grab the schema of. This will also work with it's display name or source_clean. This is the only required parameter for this function.
34+
35+
#### types
36+
This is an optional parameter and is a list of strings. If this is set the function will only return colomns that match the types given. For example if we were to pass ['string'] as our types parameter in the previous example we would instead have returned:
37+
```
38+
name display type
39+
0 stats__DefectCategory__val Defect Category string
40+
```
41+
42+
#### show_hidden
43+
This is an optional parameter and is a boolean. There are a few fields we have set to be hiddden from our ui in our application and by defualt these are also hidden from the return in this function if set to True we will also return these fields.
44+
45+
#### return_mtype
46+
This is an optional parameter and is a boolean. If set to True this will instead of returning just the pandas dataframe will return a Tupple with a string that is the machine type of the machine_soure for example:
47+
```
48+
('Lasercut',
49+
name display type
50+
0 stats__Alarms__val Alarms float
51+
1 stats__BLOCKED__val BLOCKED float
52+
...)
1553
```

docs/entities/machine_type.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Machine Types
2+
Machine Types are the schema for the various machines in a factory.
3+
4+
## Functions
5+
6+
### get_fields_of_machine_type
7+
The get_fields_of_machine_type function returns the fields of the machine schema for a given machine type and is called this way:
8+
```
9+
cli.get_fields_of_machine_type(machine_type, types, show_hidden)
10+
```
11+
12+
The only required field in this case is the machine_type, we will go over each variable in a second. The function will return a pandas list that looks like the following:
13+
```
14+
[{'display_name': 'Machine', 'unit': '', 'type': 'categorical', 'data_type': 'string', 'stream_types': [], 'raw_data_field': '', 'name': 'machine__source'}, {'display_name': 'Cycle Start Time', 'unit': '', 'type': 'datetime', 'data_type': 'datetime', 'stream_types': [], 'raw_data_field': '', 'name': 'starttime'},..]
15+
```
16+
17+
#### machine_type
18+
This is the name of the machine type that you are trying to grab the fields of. This is the only required parameter for this function.
19+
20+
#### types
21+
This is an optional parameter and is a list of strings. If this is set the function will only return colomns that match the types given. For example if we were to pass ['string'] as our types parameter in the previous example we would instead have returned:
22+
```
23+
[{'display_name': 'Machine', 'unit': '', 'type': 'categorical', 'data_type': 'string', 'stream_types': [], 'raw_data_field': '', 'name': 'machine__source'}]
24+
```
25+
26+
#### show_hidden
27+
This is an optional parameter and is a boolean. There are a few fields we have set to be hiddden from our ui in our application and by defualt these are also hidden from the return in this function if set to True we will also return these fields.

smsdk/client.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -210,24 +210,6 @@ def get_parts(self, normalize=True, clean_strings_in=True, clean_strings_out=Tru
210210
df = self.get_data_v1('part_v1', 'get_parts', normalize, *args, **kwargs)
211211

212212
return df
213-
214-
215-
@ClientV0.get_machine_schema_decorator
216-
def get_machine_schema(self, machine_source, types=[], return_mtype=False, **kwargs):
217-
stats = kwargs.get('stats', [])
218-
fields = []
219-
for stat in stats:
220-
if not stat.get('display', {}).get('ui_hidden', False):
221-
if len(types) == 0 or stat['analytics']['columns'][0]['type'] in types:
222-
try:
223-
fields.append({'name': stat['analytics']['columns'][0]['name'],
224-
'display': stat['display']['title_prefix'],
225-
'type': stat['analytics']['columns'][0]['type']})
226-
except:
227-
log.warning(
228-
f"Unknow stat schema identified :: machine_type {machine_source} - "
229-
f"title_prefix :: {stat.get('display', {}).get('title_prefix', '')}")
230-
return fields
231213

232214
def get_kpis(self, **kwargs):
233215
kpis = smsdkentities.get('kpi')
@@ -277,4 +259,31 @@ def get_type_from_machine(self, machine_source=None, **kwargs):
277259
self.config["protocol"], self.tenant, self.config["site.domain"]
278260
)
279261
return machine(self.session, base_url).get_type_from_machine_name(machine_source, **kwargs)
262+
263+
def get_machine_schema(self, machine_source, types=[], show_hidden=False, return_mtype=False, **kwargs):
264+
machineType= smsdkentities.get('machine_type')
265+
machine_type = self.get_type_from_machine(machine_source)
266+
base_url = get_url(
267+
self.config["protocol"], self.tenant, self.config["site.domain"]
268+
)
269+
fields = machineType(self.session, base_url).get_fields(machine_type, **kwargs)
270+
fields = [field for field in fields if not field.get('ui_hidden') or show_hidden]
271+
if len(types) > 0:
272+
fields = [field for field in fields if field.get('type') in types]
280273

274+
if return_mtype:
275+
return (machine_type, pd.DataFrame(fields))
276+
277+
return pd.DataFrame(fields)
278+
279+
def get_fields_of_machine_type(self, machine_type, types=[], show_hidden=False, **kwargs):
280+
machineType= smsdkentities.get('machine_type')
281+
base_url = get_url(
282+
self.config["protocol"], self.tenant, self.config["site.domain"]
283+
)
284+
fields = machineType(self.session, base_url).get_fields(machine_type, **kwargs)
285+
fields = [field for field in fields if not field.get('ui_hidden') or show_hidden]
286+
if len(types) > 0:
287+
fields = [field for field in fields if field.get('type') in types]
288+
289+
return fields

smsdk/client_v0.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ def inner(self, normalize=True, clean_strings_in=True, clean_strings_out=True, d
424424
def get_machine_schema_decorator(func):
425425

426426
@functools.wraps(func)
427-
def inner(self, machine_source, types=[], return_mtype=False, **kwargs):
427+
def inner(self, machine_source, types=[], show_hidden=False, return_mtype=False, **kwargs):
428428

429429
try:
430430
machine_type = self.get_machines(source=machine_source)['source_type'][0]
@@ -448,7 +448,7 @@ def inner(self, machine_source, types=[], return_mtype=False, **kwargs):
448448
print(f"Exception in getting machine type stats {ex}")
449449
kwargs['stats'] = stats
450450

451-
fields = func(self, machine_source, types=[], return_mtype=False, **kwargs)
451+
fields = func(self, machine_source, types, show_hidden, return_mtype, **kwargs)
452452

453453
if return_mtype:
454454
return machine_type, pd.DataFrame(fields)

smsdk/config/api_endpoints.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"url" : "/api/factory"
1212
},
1313
"MachineType": {
14-
"url" : "/api/machinetype"
14+
"url" : "/api/machinetype",
15+
"fields": "/v1/selector/datatab/cycle/{}/field"
1516
},
1617
"Machine": {
1718
"url" : "/api/machine"

smsdk/smsdk_entities/machine/machine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ def get_type_from_machine_name(self, machine_source, *args, **kwargs):
5555
records = self._get_records_v1(url, method="get", **kwargs)[0]["machine"]
5656
machine_type = ''
5757
for record in records:
58-
if record['name'] == machine_source:
58+
if record['name'] == machine_source or record['display_name'] == machine_source:
5959
machine_type = record['type']
6060
return machine_type

smsdk/smsdk_entities/machine_type/machinetype.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,16 @@ def get_machine_types(self, *args, **kwargs):
4343
if not isinstance(records, List):
4444
raise ValueError("Error - {}".format(records))
4545
return records
46+
47+
@mod_util
48+
def get_fields(self, machine_type, *args, **kwargs):
49+
"""
50+
Utility function to get the machine types
51+
from the ma machine API
52+
Recommend to use 'enable_pagination':True for larger datasets
53+
"""
54+
url = "{}{}".format(self.base_url, ENDPOINTS["MachineType"]["fields"].format(machine_type))
55+
records = self._get_records(url, **kwargs)
56+
if not isinstance(records, List):
57+
raise ValueError("Error - {}".format(records))
58+
return records

tests/machine/machine_data.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,22 @@
255255
"source_type": "UpperComponentBacking",
256256
},
257257
]
258+
259+
MACHINE_TYPE =[
260+
{
261+
'type': 'float',
262+
'name': 'stat__test_float',
263+
'title_prefix': 'test float'
264+
},
265+
{
266+
'type': 'string',
267+
'name': 'stat__test_string',
268+
'title_prefix': 'test string'
269+
},
270+
{
271+
'type': 'string',
272+
'name': 'stat__test_hidden',
273+
'title_prefix': 'test hidden',
274+
'ui_hidden' : True
275+
}
276+
]

tests/machine/test_machine.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pandas as pd
44
from requests.sessions import Session
55
from smsdk.client import Client
6-
from tests.machine.machine_data import JSON_MACHINE
6+
from tests.machine.machine_data import JSON_MACHINE, MACHINE_TYPE
77
from smsdk.smsdk_entities.machine.machine import Machine
88

99

@@ -59,3 +59,62 @@ def json():
5959

6060
# Verify
6161
assert type == 'test_type'
62+
63+
64+
@patch("smsdk.smsdk_entities.machine_type.machinetype.MachineType.get_fields")
65+
@patch("smsdk.client.Client.get_type_from_machine")
66+
def test_get_machine_schema(mocked_types, mocked_machines):
67+
mocked_machines.return_value = MACHINE_TYPE
68+
mocked_types.return_value = 'test'
69+
dt = Client("demo")
70+
71+
# Run
72+
fields = dt.get_machine_schema('test')
73+
assert fields.shape == (2, 3)
74+
# Verify
75+
assert fields.name.sort_values().tolist() == ['stat__test_float', 'stat__test_string']
76+
77+
78+
@patch("smsdk.smsdk_entities.machine_type.machinetype.MachineType.get_fields")
79+
@patch("smsdk.client.Client.get_type_from_machine")
80+
def test_get_machine_schema_hidden(mocked_types, mocked_machines):
81+
mocked_machines.return_value = MACHINE_TYPE
82+
mocked_types.return_value = 'test'
83+
dt = Client("demo")
84+
85+
# Run
86+
fields = dt.get_machine_schema('test', show_hidden=True)
87+
assert fields.shape == (3, 4)
88+
89+
# Verify
90+
assert fields.name.sort_values().tolist() == ['stat__test_float', 'stat__test_hidden', 'stat__test_string']
91+
92+
@patch("smsdk.smsdk_entities.machine_type.machinetype.MachineType.get_fields")
93+
@patch("smsdk.client.Client.get_type_from_machine")
94+
def test_get_machine_schema_types(mocked_types, mocked_machines):
95+
mocked_machines.return_value = MACHINE_TYPE
96+
mocked_types.return_value = 'test'
97+
dt = Client("demo")
98+
99+
# Run
100+
fields = dt.get_machine_schema('test', types=['float'])
101+
assert fields.shape == (1, 3)
102+
103+
# Verify
104+
assert fields.name.sort_values().tolist() == ['stat__test_float']
105+
106+
@patch("smsdk.smsdk_entities.machine_type.machinetype.MachineType.get_fields")
107+
@patch("smsdk.client.Client.get_type_from_machine")
108+
def test_get_machine_schema_types_return_mtype(mocked_types, mocked_machines):
109+
mocked_machines.return_value = MACHINE_TYPE
110+
mocked_types.return_value = 'test'
111+
dt = Client("demo")
112+
113+
# Run
114+
fields = dt.get_machine_schema('test', return_mtype=True)
115+
assert fields[0] == 'test'
116+
assert fields[1].shape == (2, 3)
117+
# Verify
118+
assert fields[1].name.sort_values().tolist() == ['stat__test_float', 'stat__test_string']
119+
120+

tests/machine_type/machine_type_data.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4411,3 +4411,22 @@
44114411
},
44124412
},
44134413
]
4414+
4415+
MACHINE_TYPE_FIELDS =[
4416+
{
4417+
'type': 'float',
4418+
'name': 'stat__test_float',
4419+
'title_prefix': 'test float'
4420+
},
4421+
{
4422+
'type': 'string',
4423+
'name': 'stat__test_string',
4424+
'title_prefix': 'test string'
4425+
},
4426+
{
4427+
'type': 'string',
4428+
'name': 'stat__test_hidden',
4429+
'title_prefix': 'test hidden',
4430+
'ui_hidden' : True
4431+
}
4432+
]

0 commit comments

Comments
 (0)