class Subject(): def __init__(self, participant_id): self.participant_id = participant_id self.condition = None # Data logged from iFEED self.learning_task_data = dict() self.design_synthesis_task_data = dict() self.feature_synthesis_task_data = dict() # Concept map data self.cmap_prior_data = dict() self.cmap_learning_data = dict() self.cmap_learning_data_extended = dict() # Problem answers self.feature_classification_answer = [] self.feature_classification_confidence = [] self.feature_comparison_answer = [] self.feature_comparison_confidence = [] self.design_classification_answer = [] self.design_classification_confidence = [] self.design_comparison_answer = [] self.design_comparison_confidence = [] # Feature preference questions self.feature_preference_data = dict() # Self-assessment of learning self.learning_self_assessment_data = [] # Demographic info self.demographic_data = dict() self.prior_experience_data = dict() # Graded score and answers self.grader = Grader() self.feature_classification_score = None self.feature_classification_graded_answers = [] self.feature_comparison_score = None self.feature_comparison_graded_answers = [] self.design_classification_score = None self.design_classification_graded_answers = [] self.design_comparison_score = None self.design_comparison_graded_answers = [] # Transcript data self.transcript_problem_solving = None self.transcript_survey = None # IDG and distance to utopia self.feature_synthesis_dist2UP = dict() self.design_IGD = dict() self.design_num_designs_to_shortest_dist = -1 self.design_HV = None self.design_entropy = None def gradeAnswers(self, confidenceThreshold=None): self.feature_classification_score, self.feature_classification_graded_answers = self.grader.gradeAnswers( "feature", "classification", self.feature_classification_answer, self.feature_classification_confidence, confidenceThreshold=confidenceThreshold) self.feature_comparison_score, self.feature_comparison_graded_answers = self.grader.gradeAnswers( "feature", "comparison", self.feature_comparison_answer, self.feature_comparison_confidence, confidenceThreshold=confidenceThreshold) self.design_classification_score, self.design_classification_graded_answers = self.grader.gradeAnswers( "design", "classification", self.design_classification_answer, self.design_classification_confidence, confidenceThreshold=confidenceThreshold) self.design_comparison_score, self.design_comparison_graded_answers = self.grader.gradeAnswers( "design", "comparison", self.design_comparison_answer, self.design_comparison_confidence, confidenceThreshold=confidenceThreshold) def getMeanConfidence(self, problemTopic=None, problemType=None, countOnlyCorrectAnswers=False, countOnlyWrongAnswers=False): if self.feature_classification_score is None or self.feature_comparison_score is None or self.design_classification_score is None or self.design_comparison_score is None: raise ValueError() gradedAnswers = [] confidences = [] if problemTopic is None and problemType is None: gradedAnswers = self.feature_classification_graded_answers + self.feature_comparison_graded_answers + self.design_classification_graded_answers + self.design_comparison_graded_answers confidences = self.feature_classification_confidence + self.feature_comparison_confidence + self.design_classification_confidence + self.design_comparison_confidence targetGrade = None if countOnlyCorrectAnswers: targetGrade = 1 elif countOnlyWrongAnswers: targetGrade = 0 if targetGrade is not None: tempConfidences = [] for i, c in enumerate(gradedAnswers): if gradedAnswers[i] == targetGrade: tempConfidences.append(confidences[i]) confidences = tempConfidences return np.mean(confidences) def printloggedDataSummary(self, task=None, loggedData=None): if task is None and loggedData is None: raise ValueError() if task is not None: if task == "learning_task": data = self.learning_task_data elif task == "feature_synthesis_task": data = self.feature_synthesis_task_data elif task == "design_synthesis_task": data = self.design_synthesis_task_data elif loggedData is not None: data = loggedData out = [ "Subject: {0} - condition: {1}".format(self.participant_id, self.condition) ] for key in data.keys(): if key in [ "participantID", "treatmentCondition", "stage", "duration", "paramsInfo" ]: continue val = data[key] if key == "designs_evaluated": val = str(len(data[key])) elif key == "features_found": val = str(len(data[key])) out.append("{0}: {1}".format(key, val)) print("\n".join(out)) def getAggregateScore(self, combineFandD=True): FScore = (self.feature_classification_score + self.feature_comparison_score) / 2 DScore = (self.design_classification_score + self.design_comparison_score) / 2 if combineFandD: total = (FScore + DScore) / 2 return round(total, 2) else: FScore = round(FScore, 2) DScore = round(DScore, 2) return FScore, DScore def printAggregateScore(self, combineFandD=True): print("Subject: {0} - condition: {1}".format(self.participant_id, self.condition)) if combineFandD: total = self.getAggregateScore(combineFandD=combineFandD) print("Total score: {0}".format(total)) else: FScore, DScore = self.getAggregateScore(combineFandD=combineFandD) print("Feature: {0}, Design: {1}".format(FScore, DScore)) def printScoreSummary(self): print("Subject: {0} - condition: {1}".format(self.participant_id, self.condition)) print("Fcl: {0}, Fpwc: {1}, Dcl: {2}, Dpwc: {3}".format( self.feature_classification_score, self.feature_comparison_score, self.design_classification_score, self.design_comparison_score)) def gradePositiveFeatures(self): return self.grader.gradePositiveOrNegativeFeatures( self.feature_classification_graded_answers, self.feature_comparison_graded_answers, positive=True) def gradeNegativeFeatures(self): return self.grader.gradePositiveOrNegativeFeatures( self.feature_classification_graded_answers, self.feature_comparison_graded_answers, positive=False) def gradeHighLevelFeatures(self): return self.grader.gradeHighVsLowLevelFeatures( self.feature_classification_graded_answers, self.feature_comparison_graded_answers, highLevel=True) def gradeLowLevelFeatures(self): return self.grader.gradeHighVsLowLevelFeatures( self.feature_classification_graded_answers, self.feature_comparison_graded_answers, highLevel=False) def getDist2Utopia(self): if len(self.feature_synthesis_task_data ) != 0 and 'features_found' in self.feature_synthesis_task_data: features = self.feature_synthesis_task_data['features_found'] self.feature_synthesis_dist2UP = 1 for count, feature in enumerate(features): x = feature['metrics'][2] y = feature['metrics'][3] dist = math.sqrt((1.0 - x)**2 + (1.0 - y)**2) if dist < self.feature_synthesis_dist2UP: self.feature_synthesis_dist2UP = dist return self.feature_synthesis_dist2UP def computeDesignEntropy(self): def rearrangeDesignInputs(inputs): inputAppearance = [] for designIndex, designInputString in enumerate(inputs): if len(inputAppearance) == 0: inputAppearance = [[] for k in range(len(designInputString))] for inputIndex, val in enumerate(designInputString): if val == "1": inputAppearance[inputIndex].append(designIndex) return inputAppearance def getEntropy(inputAppearances, base=10): N = len(inputAppearances) sig = 0 for i, appearances in enumerate(inputAppearances): if len(appearances) == 0: continue else: p = len(appearances) / N sig += p * math.log(p, base) H = -1 / math.log(N, base) * sig return H inputs = [] designs = self.design_synthesis_task_data['designs_evaluated'] for d in designs: inputs.append(d['inputs']) inputAppearances = rearrangeDesignInputs(inputs) entropy = getEntropy(inputAppearances) self.design_entropy = entropy
class Subject(): def __init__(self, jsonFilesRootPath, participant_id): self.jsonFilesRootPath = jsonFilesRootPath self.participant_id = participant_id self.condition = None # Data logged from iFEED self.learning_task_data = dict() self.design_synthesis_task_data = dict() self.feature_synthesis_task_data = dict() # Concept map data self.cmap_prior_data = dict() self.cmap_learning_data = dict() # Problem answers self.feature_classification_answer = [] self.feature_classification_confidence = [] self.feature_comparison_answer = [] self.feature_comparison_confidence = [] self.design_classification_answer = [] self.design_classification_confidence = [] self.design_comparison_answer = [] self.design_comparison_confidence = [] # Feature preference questions self.feature_preference_data = dict() # Self-assessment of learning self.learning_self_assessment_data = [] # Demographic info self.demographic_data = dict() self.prior_experience_data = dict() # Read JSON files self.readJSONFiles() # Graded score and answers self.grader = Grader() self.feature_classification_score = None self.feature_classification_graded_answers = [] self.feature_comparison_score = None self.feature_comparison_graded_answers = [] self.design_classification_score = None self.design_classification_graded_answers = [] self.design_comparison_score = None self.design_comparison_graded_answers = [] def gradeAnswers(self, confidenceThreshold=None): if confidenceThreshold is not None: self.grader.setConfidenceThreshold(confidenceThreshold) self.feature_classification_score, self.feature_classification_graded_answers = self.grader.gradeAnswers( "feature", "classification", self.feature_classification_answer, self.feature_classification_confidence) self.feature_comparison_score, self.feature_comparison_graded_answers = self.grader.gradeAnswers( "feature", "comparison", self.feature_comparison_answer, self.feature_comparison_confidence) self.design_classification_score, self.design_classification_graded_answers = self.grader.gradeAnswers( "design", "classification", self.design_classification_answer, self.design_classification_confidence) self.design_comparison_score, self.design_comparison_graded_answers = self.grader.gradeAnswers( "design", "comparison", self.design_comparison_answer, self.design_comparison_confidence) def printScoreSummary(self): print("Subject: {0} - condition: {1}".format(self.participant_id, self.condition)) print("Fcl: {0}, Fpwc: {1}, Dcl: {2}, Dpwc: {3}".format( self.feature_classification_score, self.feature_comparison_score, self.design_classification_score, self.design_comparison_score)) def readJSONFiles(self): dirname = os.path.join(self.jsonFilesRootPath, self.participant_id) if not os.path.isdir(dirname): print("Failed to load the JSON file - directory not found: {0}". format(dirname)) return # raise OSError("Directory not found: {0}".format(dirname)) jsonFiles = [ os.path.join(dirname, f) for f in os.listdir(dirname) if os.path.isfile(os.path.join(dirname, f)) and f.endswith(".json") ] for filename in jsonFiles: with open(filename, newline='') as file: try: data = json.loads(file.read()) if 'treatmentCondition' in data: if self.condition is None: # Condition 1: Manual - without generalization # Condition 2: Automated - without generalization # Condition 3: Interactive - without generalization # Condition 4: Manual - with generalization # Condition 5: Automated - with generalization # Condition 6: Interactive - with generalization self.condition = data['treatmentCondition'] if "learning" in os.path.basename(filename): self.learning_task_data = data elif "feature_synthesis" in os.path.basename(filename): self.feature_synthesis_task_data = data elif "design_synthesis" in os.path.basename(filename): self.design_synthesis_task_data = data elif "conceptMap-prior" in os.path.basename(filename): self.cmap_prior_data = data elif "conceptMap-learning" in os.path.basename(filename): self.cmap_learning_data = data except: print("Exception while reading: {0}".format(filename)) traceback.print_exc() def countFeatureParity(self, positive=True): return self.grader.countFeatureParity( self.feature_classification_graded_answers, self.feature_comparison_graded_answers, positive=positive)