reflexive 0.1.9__py3-none-any.whl → 1.0.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
reflexive/__init__.py CHANGED
@@ -1,9 +1,5 @@
1
- from .common.parameters import *
2
- from .common.local import *
3
- from .common.util import *
4
- from .visual.display import *
5
- from .analyse.reflexive_expressions import *
6
- from .analyse.aws_nlp import *
7
- from .analyse.general import *
8
- from .aws_connect.comprehend import *
9
- from .aws_connect.s3 import *
1
+ import reflexive.analyse
2
+ import reflexive.cfg
3
+ import reflexive.session
4
+ import reflexive.util
5
+ import reflexive.visualise
reflexive/analyse.py ADDED
@@ -0,0 +1,431 @@
1
+
2
+ import json
3
+ import pandas as pd
4
+ import re
5
+
6
+ from reflexive import util
7
+ from reflexive import cfg
8
+ from reflexive import session
9
+ import reflexive as rfx
10
+
11
+ import logging
12
+ logging.basicConfig(level=logging.DEBUG)
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class Nlp:
17
+ aws:session.AWS = None
18
+ config:cfg.Config = None
19
+
20
+ top_ngrams = {}
21
+
22
+
23
+ def __init__(self,aws):
24
+ self.aws = aws
25
+ self.aws = aws
26
+ self.config = self.aws.config
27
+
28
+ ### GENERAL ANALYSIS FUNCTIONS ######
29
+
30
+ #checked
31
+ def text_length(self,df,text_col_name='text'):
32
+ self.config.text_col_name = text_col_name
33
+ custom_df = df.copy()
34
+ custom_df["text_length"] = df[text_col_name].apply(lambda x: len(x))
35
+ if (len(custom_df)>1):
36
+ custom_df["text_scaled"] = util.scale_min_max(custom_df[['text_length']])
37
+ else:
38
+ custom_df["text_scaled"] = 1
39
+ return custom_df
40
+
41
+ #checked
42
+ def remove_IQR_outliers(self,df):
43
+ fence = util.outlier_fence(df.text_length)
44
+ logger.debug("Fence: %s",repr(fence))
45
+ if fence['LOWER']==fence['UPPER']:
46
+ logger.info("No fence, returning original df")
47
+ return df
48
+ else:
49
+ tempdf = df.copy()
50
+ # Check change with removed outliers
51
+ checkdf = tempdf[tempdf.text_length<fence['UPPER']]
52
+ checkdf.reset_index(drop=True,inplace=True)
53
+ logger.debug("Original:",len(tempdf))
54
+ logger.debug(tempdf.describe())
55
+ logger.info:("Outliers: %s",repr(len(tempdf)-len(checkdf)))
56
+ logger.debug("No outliers:",len(checkdf))
57
+ logger.debug(checkdf.describe())
58
+ return checkdf
59
+
60
+ #checked
61
+ #Add domain terms to config
62
+ def add_domain_terms(self,domain_terms):
63
+ self.config.domain_terms = domain_terms
64
+
65
+ #checked
66
+ # Parse text for domain terms
67
+ def parse_text_domain_terms(self,text):
68
+ matched_terms = {}
69
+ for dtk,dtv in self.config.domain_terms.items():
70
+ temp_matches = []
71
+ for term in dtv:
72
+ if term[0]=='_': #acronym - treat as whole word
73
+ regex = r"\b{}\b".format(term[1:])
74
+ matches = re.findall(regex,str.lower(text))
75
+ if len(matches)>0:
76
+ temp_matches.append((term[1:],len(matches)))
77
+ else:
78
+ count = str.lower(text).count(term)
79
+ if count > 0:
80
+ temp_matches.append((term,count))
81
+ matched_terms[dtk] = dict(temp_matches)
82
+ return dict(matched_terms)
83
+
84
+ #checked
85
+ def match_domain_terms(self,df):
86
+ custom_df = df.copy()
87
+ custom_df["domain_terms"] = df[self.config.text_col_name].apply(lambda t: self.parse_text_domain_terms(t))
88
+ custom_df["domain_counts"] = custom_df["domain_terms"].apply(lambda d: self.__count_domain_terms(d))
89
+ return custom_df
90
+
91
+ #checked
92
+ # Count domain terms
93
+ def __count_domain_terms(self,domain_terms):
94
+ domain_counts = {}
95
+ for domain,terms in domain_terms.items():
96
+ domain_counts[domain] = sum(terms.values())
97
+ return domain_counts
98
+
99
+ #checked
100
+ def get_top_ngrams(self,text_series,min_val=3):
101
+ ngrams = {}
102
+ for text in text_series:
103
+ self.__ngrams345(text,ngrams)
104
+ #print("Generated 3,4,5 ngrams:", len(ngrams))
105
+ f_ngrams = util.filter_dict_by_value(ngrams,min_val)
106
+ self.top_ngrams = util.sort_dict_by_value(f_ngrams)
107
+ return self.top_ngrams
108
+
109
+
110
+ #checked
111
+ def match_top_ngrams(self,df):
112
+ custom_df = df.copy()
113
+ custom_df["top_ngrams"] = df[self.config.text_col_name].apply(lambda t: self.parse_text_top_ngrams(t))
114
+ custom_df["top_ngrams_count"] = custom_df["top_ngrams"].apply(lambda n: self.__ngram_counts(n))
115
+ return custom_df
116
+
117
+ #checked
118
+ def parse_text_top_ngrams(self,text):
119
+ ngrams = self.__ngrams345(text,{})
120
+ return {key: ngrams[key] for key in self.top_ngrams.keys() if key in ngrams}
121
+
122
+ #checked
123
+ def __ngram_counts(self,ref_top_ngrams):
124
+ return sum(ref_top_ngrams.values())
125
+
126
+ #checked
127
+ # Given text and number of terms, create ngrams from the text
128
+ def __make_ngrams(self,text, n=1):
129
+ # Replace all none alphanumeric characters with spaces
130
+ s = re.sub(r'[^a-zA-Z0-9\s]', ' ', text.lower())
131
+ tokens = [token for token in s.split(" ") if token != ""]
132
+ ngrams = zip(*[tokens[i:] for i in range(n)])
133
+ return [" ".join(ngram) for ngram in ngrams]
134
+
135
+ #checked
136
+ # Generate 3,4,5 -grams
137
+ def __ngrams345(self,text,ngrams):
138
+ ngrams3 = self.__make_ngrams(text,3)
139
+ for n in ngrams3:
140
+ ngrams[n] = ngrams.get(n,0)+1
141
+ ngrams4 = self.__make_ngrams(text,4)
142
+ for n in ngrams4:
143
+ ngrams[n] = ngrams.get(n,0)+1
144
+ ngrams5 = self.__make_ngrams(text,5)
145
+ for n in ngrams5:
146
+ ngrams[n] = ngrams.get(n,0)+1
147
+ return ngrams
148
+
149
+
150
+ #### COMPREHEND ANALYSIS
151
+
152
+ #checked
153
+ def comprehend_analysis(self,comprehend,df):
154
+ self.analysis_types = self.config.analysis_types
155
+ #print(type(df.text))
156
+ # chunk the text for batch analysis
157
+ chunked_text = util.series_to_chunked_list(series=df[self.config.text_col_name])
158
+ print("Number of chunks:",len(chunked_text))
159
+ # start batch analysis
160
+ chunked_results = comprehend.get_multiple_batch_analysis(chunked_text)
161
+ print("Finished Analysis.")
162
+ # write to file
163
+ print("Writing data to file...")
164
+ with open(f"{self.config.local_path}{self.config.prefix}analysis_chunks{self.config.postfix}.json", "w") as fp:
165
+ json.dump(chunked_results,fp)
166
+ print("DONE!")
167
+ # unchunk
168
+ final_results = {}
169
+ for key in chunked_results.keys():
170
+ final_results[key] = comprehend.unbatch_results(self.analysis_types[key],chunked_results[key])
171
+ print("Finished Unbatching",key," - Writing data to file...")
172
+ filename = f"{self.config.local_path}{self.config.prefix}{key}{self.config.postfix}.json"
173
+ with open(filename, "w") as fp:
174
+ json.dump(final_results[key],fp)
175
+ print("DONE!")
176
+ # Save final_results for reload if necessary
177
+ with open(f"{self.config.local_path}{self.config.prefix}final_results{self.config.postfix}.json", "w") as fp:
178
+ json.dump(final_results,fp)
179
+ return final_results
180
+
181
+ #checked
182
+ def check_results(self,results):
183
+ print("Checking for errors...")
184
+ for key in results.keys():
185
+ errors = results[key]['errors']
186
+ print(f"Errors for {key}: {errors}")
187
+ print()
188
+ print("Checking that we have results for all docs")
189
+ for key in results.keys():
190
+ num_results= len(results[key]['results'])
191
+ print(f"Number of results for {key}: {num_results}")
192
+ return errors
193
+
194
+ #checked
195
+ def add_results_to_df(self,results,df):
196
+ for key in results.keys():
197
+ rs = results[key]['results']
198
+ newresults = {}
199
+ for oldkey in rs.keys():
200
+ newresults[int(oldkey)] = rs[oldkey] # Need to change keys to int to properly add to dataframe
201
+ df[key] = pd.Series(newresults)
202
+ return df
203
+
204
+ #checked
205
+ def comprehend_analytics(self,df):
206
+ temp_df = df.copy()
207
+ temp_df = self.keyphrase_analytics(temp_df)
208
+ temp_df = self.named_entity_analytics(temp_df)
209
+ temp_df = self.targeted_sentiment_analytics(temp_df)
210
+ temp_df = self.syntax_analytics(temp_df)
211
+ return temp_df
212
+
213
+ #checked
214
+ def keyphrase_analytics(self,df):
215
+ df["key_phrases"] = df.KeyPhraseResults.apply(self.parse_keyPhraseResults)
216
+ df["key_phrase_counts"] = df.key_phrases.apply(util.count_keys)
217
+ df["key_phrases_total"] = df.key_phrase_counts.apply(util.tuple_values_total)
218
+ if (len(df)>1):
219
+ df["key_phrases_scaled"] = util.scale_min_max(df[['key_phrases_total']])
220
+ else:
221
+ df["key_phrases_scaled"] = 1
222
+ # Normalise based on text_scaled
223
+ df['key_phrases_norm'] = util.normalise_scaled(df,'key_phrases_scaled')
224
+ return df
225
+
226
+ #checked
227
+ def named_entity_analytics(self,df):
228
+ df["named_entities"] = df.TargetedSentimentResults.apply(self.parse_namedEntities)
229
+ df['named_entity_counts'] = df.named_entities.apply(util.count_entities)
230
+ df["named_entity_ratios"] = df.named_entity_counts.apply(util.ratios)
231
+ df["named_entities_total"] = df.named_entity_counts.apply(util.tuple_values_total)
232
+ if (len(df)>1):
233
+ df["named_entities_scaled"] = util.scale_min_max(df[['named_entities_total']])
234
+ else:
235
+ df["named_entities_scaled"] = 1
236
+ df['named_entities_norm'] = util.normalise_scaled(df,'named_entities_scaled')
237
+ return df
238
+
239
+ #checked
240
+ def targeted_sentiment_analytics(self,df):
241
+ df["targeted_sentiment"] = df.TargetedSentimentResults.apply(self.parse_targetedSentimentResults)
242
+ df['targeted_sentiment_counts'] = df.targeted_sentiment.apply(util.count_entities)
243
+ df["targeted_sentiment_ratios"] = df.targeted_sentiment_counts.apply(util.ratios)
244
+ df["targeted_sentiment_total"] = df.targeted_sentiment_counts.apply(util.tuple_values_total)
245
+ if (len(df)>1):
246
+ df["targeted_sentiment_scaled"] = util.scale_min_max(df[['targeted_sentiment_total']])
247
+ else:
248
+ df["targeted_sentiment_scaled"] = 1
249
+ df['targeted_sentiment_norm'] = util.normalise_scaled(df,'targeted_sentiment_scaled')
250
+ return df
251
+
252
+ #checked
253
+ def syntax_analytics(self,df):
254
+ df["pos_tags"] = df.SyntaxResults.apply(self.parse_syntaxResults)
255
+ df['pos_tag_counts'] = df.pos_tags.apply(util.count_labels)
256
+ df["pos_tag_ratios"] = df.pos_tag_counts.apply(util.ratios)
257
+ df["pos_tags_total"] = df.pos_tag_counts.apply(util.tuple_values_total)
258
+ if (len(df)>1):
259
+ df["pos_tags_scaled"] = util.scale_min_max(df[['pos_tags_total']])
260
+ else:
261
+ df["pos_tags_scaled"] = 1
262
+ df['pos_tags_norm'] = util.normalise_scaled(df,'pos_tags_scaled')
263
+ return df
264
+
265
+ #checked
266
+ # Parse key_phrases results - include all above threshold
267
+ def parse_keyPhraseResults(self,keyPhraseResults,threshold=0.95,min_count=1):
268
+ phrases = {}
269
+ filtered = [str.lower(r['Text']) for r in keyPhraseResults if r['Score'] > threshold]
270
+ for phrase in filtered:
271
+ phrases[phrase] = phrases.get(phrase,0)+1
272
+
273
+ filtered_phrases = {k:v for k,v in phrases.items() if v >= min_count}
274
+ return util.sort_dict_by_value(filtered_phrases)
275
+
276
+ #checked
277
+ # Parse syntax results - include specific postags
278
+ def parse_syntaxResults(self,syntax_results,postags_keep = ['ADV','VERB','AUX','ADJ','NOUN','PRON','PROPN']):
279
+ sequence = list()
280
+ for token in syntax_results:
281
+ tag = token['PartOfSpeech']['Tag']
282
+ if tag in postags_keep:
283
+ sequence.append((str.lower(token['Text']),tag))
284
+ return sequence
285
+
286
+ #checked
287
+ # Parse targeted sentiment results - keep non-neutral above threshold
288
+ def parse_targetedSentimentResults(self,targetedSentiment_results,threshold = 0.4):
289
+ sents = dict()
290
+ for grp in targetedSentiment_results:
291
+ for mention in grp["Mentions"]:
292
+ if mention['Score'] >= threshold:
293
+ if not "NEUTRAL" in mention['MentionSentiment']['Sentiment']:
294
+ k = mention['MentionSentiment']['Sentiment']
295
+ text = str.lower(mention['Text'])
296
+ sents.setdefault(k,{text}).add(text)
297
+ for k,v in sents.items():
298
+ sents[k] = list(v) # change set to list
299
+ return sents
300
+
301
+ #checked
302
+ # Parse targeted sentiment results for named entities
303
+ def parse_namedEntities(self,targetedSentimentResults,threshold = 0.1):
304
+ ents = dict()
305
+ for grp in targetedSentimentResults:
306
+ for mention in grp["Mentions"]:
307
+ if mention['Score'] >= threshold:
308
+ k = mention['Type']
309
+ text = str.lower(mention['Text'])
310
+ ents.setdefault(k,{text}).add(text)
311
+ for k,v in ents.items():
312
+ ents[k] = list(v) # change set to list
313
+ return ents
314
+
315
+ #--
316
+ # Ratio between action POS and object POS
317
+ # def action_object_ratio(self,pos_ratios,action_pos = ['VERB'],object_pos = ['NOUN','PROPN']):
318
+ # ap = [s[1] for s in pos_ratios if s[0] in action_pos]
319
+ # if ap:
320
+ # aps = sum(ap)
321
+ # else:
322
+ # aps = 0
323
+ # op = [s[1] for s in pos_ratios if s[0] in object_pos]
324
+ # if op:
325
+ # ops = sum(op)
326
+ # else:
327
+ # ops = 1 #avoid divide zero error - only happens with aps of 1
328
+ # #print("aps",aps,"ops",ops)
329
+ # return aps/ops
330
+
331
+ ######## REFLEXIVE EXPRESSION ANALYSIS FUNCTIONS
332
+
333
+ #checked
334
+ def analyse_reflexive_expressions(self,df,s3:session.S3,comprehend):
335
+ #self.__bucket_name = s3_bucket_name
336
+ text_series = df.text.replace('\r\n','\n') # Comprehend treats \r\n as one character
337
+ # Upload reflections to S3 for analysis
338
+ s3.upload_docs(text_series)
339
+
340
+ # Save a copy of reflections locally for offline analysis
341
+ self.save_docs(text_series)
342
+
343
+ # Submit the job
344
+ return comprehend.submit_custom_entity_job("reflexive_expressions_analysis") #submitReflexiveExpressionsJob(access_role_arn, entity_recogniser_arn)
345
+
346
+ #checked
347
+ def save_docs(self,text_series,):
348
+ logger.info(f"Saving {len(text_series)} docs to {self.config.local_path}...")
349
+ for idx in text_series.index:
350
+ file_name = f"{self.config.prefix}{idx}.txt"
351
+ file_body = text_series.iloc[idx]
352
+ logger.info(f"Saving {file_name}")
353
+ with open(f"{self.config.local_path}{file_name}",'w') as fp:
354
+ fp.write(file_body)
355
+ logger.info("Finished saving reflections locally.")
356
+
357
+
358
+
359
+
360
+ #checked
361
+ def extractAnalysisFromResults(self,results):
362
+ analysis_output = dict()
363
+ jresults = json.loads(results)
364
+ for result in jresults:
365
+ j = json.loads(result)
366
+ #print(j)
367
+ idx = j["File"].split('_')[-1].split('.')[0]
368
+ analysis_output[int(idx)] = j["Entities"]
369
+ return analysis_output
370
+
371
+ #checked
372
+ def add_to_dataframe(self,df,results):
373
+ # Extract analysis from raw results
374
+ analysis_output = self.extractAnalysisFromResults(results)
375
+ # Add results to dataframe
376
+ results_df = df.copy()
377
+ results_df['ReflexiveResults'] = pd.Series(analysis_output)
378
+ return results_df
379
+
380
+ #--
381
+ def reflexive_analytics(self,df):
382
+ #util = Util()
383
+ custom_df = df.copy()
384
+ # custom_df["text_length"] = df.text.apply(lambda x: len(x))
385
+ # if (len(custom_df)>1):
386
+ # custom_df["text_scaled"] = util.scale_min_max(custom_df[['text_length']])
387
+ # else:
388
+ # custom_df["text_scaled"] = 1
389
+ #custom_df["reflexive_results"] = df.reflexiveResults
390
+ # The expressions and their reflexive expression labels
391
+ custom_df["reflexive_expressions"] = df.ReflexiveResults.apply(self.parse_reflexiveResults)
392
+ # The counts for each labels
393
+ custom_df["reflexive_counts"] = custom_df.reflexive_expressions.apply(util.count_labels)
394
+ # Ratios between reflexive expressions
395
+ custom_df["reflexive_ratio"] = custom_df.reflexive_counts.apply(util.ratios)
396
+ # Ratio vector
397
+ custom_df['ratio_vector'] = custom_df.reflexive_ratio.apply(self.make_ratio_vector)
398
+ # Get the diversity of reflexive types - out of 8 possible types
399
+ custom_df["reflexive_type_diversity"] = custom_df.reflexive_counts.apply(lambda x: len(x)/8)
400
+ # A total of all labels
401
+ custom_df["reflexive_total"] = custom_df.reflexive_counts.apply(util.tuple_values_total)
402
+ # MinMax scale the reflexive_total
403
+ if (len(custom_df)>1):
404
+ custom_df["reflexive_scaled"] = util.scale_min_max(custom_df[['reflexive_total']])
405
+ else:
406
+ custom_df["reflexive_scaled"] = 1
407
+ # Normalise based on text_scaled
408
+ custom_df['reflexive_norm'] = util.normalise_scaled(custom_df,'reflexive_scaled')
409
+ return custom_df
410
+
411
+ #checked
412
+ # Parse reflexive results - include all above threshold
413
+ def parse_reflexiveResults(self,reflexiveResults,threshold=0.5):
414
+ final_refs = list()
415
+ #rr = json.loads(reflexiveResults)
416
+ for ref in reflexiveResults:
417
+ if ref['Score'] > threshold:
418
+ final_refs.append((str.lower(ref['Text']),ref['Type']))
419
+ return final_refs
420
+
421
+ #--
422
+ # Function for creating a vector out of reflexive ratio - could be used for others
423
+ def make_ratio_vector(self,ratio_list,ref_codes = ['RR','ER','VR','AR','EP','AF','CN','EV']):
424
+ ratio_dict = dict(ratio_list)
425
+ vec = []
426
+ for rc in ref_codes:
427
+ if rc in ratio_dict.keys():
428
+ vec.append(ratio_dict[rc])
429
+ else:
430
+ vec.append(0)
431
+ return vec
reflexive/cfg.py ADDED
@@ -0,0 +1,118 @@
1
+ import logging
2
+ import os
3
+ from datetime import datetime
4
+ import json
5
+ import reflexive as rfx
6
+
7
+ logging.basicConfig(level=logging.DEBUG)
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class Config:
11
+
12
+ aws_profile = None
13
+ aws_region = None
14
+ aws_account_number = None
15
+ aws_access_key = None
16
+
17
+ local_path = None
18
+ date_string = None
19
+ analysis_types = None
20
+ prefix = None
21
+ postfix = None
22
+
23
+ s3_access_point = None
24
+ s3_bucket_name = None
25
+ s3_accesspoint_arn = None
26
+
27
+ comprehend_service_role_name = None
28
+ comprehend_access_role_arn = None
29
+
30
+ s3_files_folder = None
31
+ s3_results_folder = None
32
+ s3_input_uri = None
33
+ s3_output_uri = None
34
+ reflexive_entity_name = None
35
+ reflexive_entity_version = None
36
+ reflexive_entity_arn = None
37
+
38
+ text_col_name = 'text'
39
+ domain_terms = {}
40
+
41
+ display_priority_tags = None
42
+ display_colours = None
43
+ display_options = None
44
+
45
+ def __init__(self,profile="default"):
46
+ self.aws_profile = profile
47
+
48
+ def get_parameters(self):
49
+ return self.__dict__
50
+
51
+ def set_parameters(self,name_prefix="rfx",local_path=None,date_string=None):
52
+ working_dir = os.getcwd()
53
+ self.local_path = local_path
54
+ self.date_string = date_string
55
+ self.analysis_types = {
56
+ "KeyPhraseResults":"KeyPhrases",
57
+ "SentimentResults":"Sentiment",
58
+ "TargetedSentimentResults":"Entities",
59
+ "SyntaxResults":"SyntaxTokens"
60
+ }
61
+
62
+ # General parameters
63
+
64
+ if not local_path:
65
+ logger.warning("No path supplied, creating a data directory...")
66
+ #print(f"WD: {working_dir}")
67
+ data_dir = working_dir+"/data/"
68
+ if not os.path.exists(data_dir):
69
+ os.makedirs(data_dir)
70
+ logger.info("Created:%s",repr(data_dir))
71
+ self.local_path = data_dir
72
+ else:
73
+ data_dir = local_path
74
+ if not os.path.exists(data_dir):
75
+ logger.warning("Path does not exist, creating directory")
76
+ os.makedirs(data_dir)
77
+ logger.info(f"Created %s",repr(data_dir))
78
+ self.local_path = local_path
79
+ if not date_string:
80
+ date_string = datetime.today().strftime('%Y%m%d')
81
+ logger.warning(f"No date_string supplied, using today: {date_string}")
82
+ self.date_string = date_string
83
+ self.prefix = f"{name_prefix}_"
84
+ self.postfix = f"-{date_string}"
85
+ return self.get_parameters()
86
+
87
+
88
+ def set_s3_parameters(self,s3_access_point,s3_bucket_name):
89
+ self.s3_access_point = s3_access_point
90
+ self.s3_bucket_name = s3_bucket_name
91
+ self.s3_accesspoint_arn = f"arn:aws:s3:{self.aws_region}:{self.aws_account_number}:accesspoint/{s3_access_point}"
92
+ return self.get_parameters()
93
+
94
+ def set_comprehend_parameters(self,comprehend_service_role_name):
95
+ self.comprehend_service_role_name = comprehend_service_role_name
96
+ self.comprehend_access_role_arn = f"arn:aws:iam::{self.aws_account_number}:role/service-role/{comprehend_service_role_name}"
97
+ return self.get_parameters()
98
+
99
+ def set_comprehend_custom_entity_parameters(self,reflexive_entity_name,reflexive_entity_version):
100
+ #Comprehend requires S3 parameters
101
+ self.s3_files_folder = f"{self.prefix}files{self.postfix}"
102
+ self.s3_results_folder = f"{self.prefix}results{self.postfix}"
103
+ self.s3_input_uri = f"s3://{self.s3_bucket_name}/{self.s3_files_folder}/{self.prefix}"
104
+ self.s3_output_uri = f"s3://{self.s3_bucket_name}/{self.s3_results_folder}/"
105
+ self.reflexive_entity_name = reflexive_entity_name
106
+ self.reflexive_entity_version = reflexive_entity_version
107
+ self.reflexive_entity_arn = f"arn:aws:comprehend:{self.aws_region}:{self.aws_account_number}:entity-recognizer/{self.reflexive_entity_name}/version/{self.reflexive_entity_version}"
108
+ return self.get_parameters()
109
+
110
+ def set_display_parameters(self,priority_tags,display_colours,display_options):
111
+ self.display_priority_tags = priority_tags
112
+ self.display_colours = display_colours
113
+ self.display_options = display_options
114
+ return self.get_parameters()
115
+
116
+
117
+
118
+