Skip to content

API Reference

comproscanner

ComProScanner - A package for extracting composition-property data from scientific articles.

This package provides tools to collect metadata, process articles from various sources, extract composition-property relationships, evaluate extraction performance and visualize data distribution.

Main functions: - collect_metadata: Collect and filter metadata from scientific articles - process_articles: Process articles from various sources (Elsevier, Wiley, etc.) - extract_composition_property_data: Extract composition-property relationships from articles - clean_data: Clean the extracted composition-property data - evaluate_semantic: Evaluate extraction quality using semantic similarity - evaluate_agentic: Evaluate extraction quality using agent-based methods - create_knowledge_graph: Create knowledge graph from extracted data

ComProScanner

Source code in src/comproscanner/comproscanner.py
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
class ComProScanner:
    def __init__(self, main_property_keyword: str = None):
        self.main_property_keyword = main_property_keyword
        if self.main_property_keyword is None:
            raise ValueErrorHandler(
                "Please provide a main property keyword to proceed."
            )

    def collect_metadata(
        self,
        base_queries: Optional[list] = None,
        extra_queries: Optional[list] = None,
        start_year: int = int(time.strftime("%Y")),
        end_year: int = int(time.strftime("%Y")) - 2,
    ):
        """Collect metadata from the articles.

        Args:
            base_queries (list, optional): List of base queries to search for in the articles. Defaults to None.
            extra_queries (list, optional): List of extra queries to search for in the articles. Defaults to None.
            start_year (int, optional): Start year for the search. Defaults to int(time.strftime("%Y")).
            end_year (int, optional): End year for the search. Defaults to int(time.strftime("%Y")) - 2.
        """
        if start_year < end_year:
            raise ValueErrorHandler(
                message="Start year should be greater than the end year."
            )
        if start_year > int(time.strftime("%Y")):
            raise ValueErrorHandler(
                message="Start year cannot be greater than the current year."
            )
        if start_year == end_year:
            raise ValueErrorHandler(
                message="Start year and End year cannot be the same."
            )
        # Fetch metadata
        fetch_metadata = FetchMetadata(
            main_property_keyword=self.main_property_keyword,
            start_year=start_year,
            end_year=end_year,
            base_queries=base_queries,
            extra_queries=extra_queries,
        )
        fetch_metadata.main_fetch()

        # Filter metadata
        filter_metadata = FilterMetadata(
            main_property_keyword=self.main_property_keyword
        )
        filter_metadata.update_publisher_information()

    def process_articles(
        self,
        property_keywords: dict = None,
        source_list: list = ["elsevier", "wiley", "iop", "springer"],
        folder_path: str = None,
        sql_batch_size: int = 500,
        csv_batch_size: int = 1,
        start_row: int = None,
        end_row: int = None,
        doi_list: list = None,
        is_sql_db: bool = False,
        is_save_xml: bool = False,
        is_save_pdf: bool = False,
        rag_db_path: str = "db",
        chunk_size: int = 1000,
        chunk_overlap: int = 25,
        embedding_model: str = "huggingface:thellert/physbert_cased",
    ):
        """Process articles for the main property keyword.

        Args:
            property_keywords (dict, required): A dictionary of property keywords which will be used for filtering sentences and should look like the following:
            {
                "exact_keywords": ["example1", "example2"],
                "substring_keywords": [" example 1 ", " example 2 "],
            }
            source_list (list, optional): List of sources to process the articles from. Defaults to ["elsevier", "wiley", "iop", "springer"] - currently supported publishers.
            folder_path (str, optional): Path to the folder containing PDFs. Defaults to None.
            sql_batch_size (int, optional): The number of rows to write to the database at once (Applicable only if is_sql_db is True). Defaults to 500.
            csv_batch_size (int, optional): The number of rows to write to the CSV file at once. Defaults to 1.
            start_row (int, optional): Start row to process the articles from. Defaults to None.
            end_row (int, optional): End row to process the articles to. Defaults to None.
            doi_list (list, optional): List of DOIs to process the articles for. Defaults to None.
            is_sql_db (bool, optional): A flag to indicate if the data should be written to the database. Defaults to False.
            is_save_xml (bool, optional): A flag to indicate if the XML files should be saved. Defaults to False.
            is_save_pdf (bool, optional): A flag to indicate if the PDF files should be saved. Defaults to False.
            rag_db_path (str, optional): Path to the vector database. Defaults to 'db'.
            chunk_size (int, optional): Size of the chunks to split the input text into. Defaults to 1000.
            chunk_overlap (int, optional): Overlap between the chunks. Defaults to 25.
            embedding_model (str, optional): Name of the embedding model. Defaults to 'thellert/physbert_cased'.

        Raises:
            ValueErrorHandler: If property_keywords is not provided.
        """
        if property_keywords is None:
            raise ValueErrorHandler(
                message="Please provide property_keywords dictionary to proceed."
            )
        rag_config = RAGConfig(
            rag_db_path=rag_db_path,
            chunk_size=chunk_size,
            chunk_overlap=chunk_overlap,
            embedding_model=embedding_model,
        )

        # Process Elsevier articles
        if "elsevier" in source_list:
            from .article_processors.elsevier_processor import ElsevierArticleProcessor

            elsevier_processor = ElsevierArticleProcessor(
                main_property_keyword=self.main_property_keyword,
                property_keywords=property_keywords,
                sql_batch_size=sql_batch_size,
                csv_batch_size=csv_batch_size,
                start_row=start_row,
                end_row=end_row,
                doi_list=doi_list,
                is_sql_db=is_sql_db,
                is_save_xml=is_save_xml,
                rag_config=rag_config,
            )
            elsevier_processor.process_elsevier_articles()

        # Process Springer articles
        if "springer" in source_list:
            from .article_processors.springer_processor import SpringerArticleProcessor

            springer_processor = SpringerArticleProcessor(
                main_property_keyword=self.main_property_keyword,
                property_keywords=property_keywords,
                sql_batch_size=sql_batch_size,
                csv_batch_size=csv_batch_size,
                start_row=start_row,
                end_row=end_row,
                doi_list=doi_list,
                is_sql_db=is_sql_db,
                is_save_xml=is_save_xml,
                rag_config=rag_config,
            )
            springer_processor.process_springer_articles()

        # Process Wiley articles
        if "wiley" in source_list:
            from .article_processors.wiley_processor import WileyArticleProcessor

            wiley_processor = WileyArticleProcessor(
                main_property_keyword=self.main_property_keyword,
                property_keywords=property_keywords,
                sql_batch_size=sql_batch_size,
                csv_batch_size=csv_batch_size,
                start_row=start_row,
                end_row=end_row,
                doi_list=doi_list,
                is_sql_db=is_sql_db,
                is_save_pdf=is_save_pdf,
                rag_config=rag_config,
            )
            wiley_processor.process_wiley_articles()

        # Process IOP articles
        if "iop" in source_list:
            from .article_processors.iop_processor import IOPArticleProcessor

            iop_processor = IOPArticleProcessor(
                main_property_keyword=self.main_property_keyword,
                property_keywords=property_keywords,
                sql_batch_size=sql_batch_size,
                csv_batch_size=csv_batch_size,
                start_row=start_row,
                end_row=end_row,
                doi_list=doi_list,
                is_sql_db=is_sql_db,
                rag_config=rag_config,
            )
            iop_processor.process_iop_articles()

        # Process PDFs
        if "pdfs" in source_list:
            from .article_processors.pdfs_processor import PDFsProcessor

            pdf_processor = PDFsProcessor(
                folder_path=folder_path,
                main_property_keyword=self.main_property_keyword,
                property_keywords=property_keywords,
                sql_batch_size=sql_batch_size,
                csv_batch_size=csv_batch_size,
                is_sql_db=is_sql_db,
                rag_config=rag_config,
            )
            pdf_processor.process_pdfs()

    def extract_composition_property_data(
        self,
        main_extraction_keyword: str = None,
        start_row: int = 0,
        num_rows: int = None,
        is_test_data_preparation=False,
        test_doi_list_file=None,
        total_test_data: int = 50,
        is_only_consider_test_doi_list: bool = False,
        test_random_seed: int = 42,
        checked_doi_list_file: str = "checked_dois.txt",
        json_results_file: str = "results.json",
        csv_results_file: str = "results.csv",
        is_extract_synthesis_data: bool = True,
        is_save_csv: bool = False,
        is_save_relevant: bool = True,
        materials_data_identifier_query: str = None,  # Will be set based on the main_property_keyword if not provided
        model: str = "gpt-4o-mini",
        api_base: Optional[str] = None,
        base_url: Optional[str] = None,
        api_key: Optional[str] = None,
        output_log_folder: Optional[str] = None,
        is_log_json: bool = False,
        task_output_folder: Optional[str] = None,
        verbose: bool = True,
        temperature: float = 0.1,
        top_p: float = 0.9,
        timeout: int = 60,
        frequency_penalty: Optional[float] = None,
        max_tokens: Optional[int] = None,
        rag_db_path: str = "db",
        embedding_model: str = "huggingface:thellert/physbert_cased",
        rag_chat_model: str = "gpt-4o-mini",
        rag_max_tokens: int = 512,
        rag_top_k: int = 3,
        rag_base_url: Optional[str] = None,
        **flow_optional_args,
    ):
        """Extract the composition-property data and synthesis data if the property is present in the article.

        Args:
            main_extraction_keyword (str, required): The main keyword to extract the composition-property data for.
            start_row (int, optional): Start row to process the articles from. Defaults to 0.
            num_rows (int, optional): Number of rows to process the articles for. Defaults to all rows.
            is_test_data_preparation (bool, optional): A flag to indicate if the test data preparation is required. Defaults to False.
            test_doi_list_file (str, optional): Path to the file containing the test DOIs. Defaults to None.
            total_test_data (int, optional): Total number of test data. Defaults to 50 if not provided and is_test_data_preparation is True.
            is_only_consider_test_doi_list (bool, optional): A flag to indicate if only the test DOI list should be considered. Defaults to False. Should be set to True if the test_doi_list_file has required number of test DOIs.
            test_random_seed (int, optional): Random seed for test data preparation. Defaults to 42.
            checked_doi_list_file (list, optional): List of DOIs which have been checked already. Defaults to "checked_dois.txt".
            json_results_file (str, optional): Path to the JSON results file. Defaults to "results.json".
            csv_results_file (str, optional): Path to the CSV results file. Defaults to "results.csv".
            is_extract_synthesis_data (bool, optional): A flag to indicate if the synthesis data should be extracted. Defaults to True.
            is_save_csv (bool, optional): A flag to indicate if the results should be saved in the CSV file. Defaults to False.
            is_save_relevant (bool, optional): A flag to indicate if only papers with composition-property data should be saved. If True, only saves papers with composition data. If False, saves all processed papers. Defaults to True.
            llm (LLM, optional): An instance of the LLM class. Defaults to None.
            materials_data_identifier_query (str, optional): Query to identify the materials data. Must be an 'yes/no' answer. Defaults to "Is there any material chemical composition and corresponding {main_property_keyword} value mentioned in the paper? GIVE ONE WORD ANSWER. Either yes or no."
            model (str: optional): The model to use (defaults to "gpt-4o-mini")
            api_base (str, optional): Base URL for standard API endpoints
            base_url (str, optional): Base URL for the model service
            api_key (str, optional): API key for the model service
            output_log_folder (str, optional): Base folder path to save logs. Logs will be saved in {output_log_folder}/{doi}/ subdirectory. Logs will be in JSON format if is_log_json is True, otherwise plain text. Defaults to None.
            task_output_folder (str, optional): Base folder path to save task outputs. Task outputs will be saved as .txt files in {task_output_folder}/{doi}/ subdirectory. Defaults to None.
            is_log_json (bool, optional): Flag to save logs in JSON format. Defaults to False.
            verbose (bool, optional): Flag to enable verbose output inside the terminal (defaults to True)
            temperature (float, optional): Temperature for text generation - controls randomness (defaults to 0.1)
            top_p (float, optional): Nucleus sampling parameter for text generation - controls diversity (defaults to 0.9)
            timeout (int, optional): Request timeout in seconds (defaults to 60)
            frequency_penalty (float, optional): Frequency penalty for text generation
            max_tokens (int, optional): Maximum tokens for completion
            rag_db_path (str, optional): Path to the vector database. Defaults to 'db'.
            embedding_model (str, optional): Name of the embedding model for RAG. Defaults to 'huggingface:thellert/physbert_cased'.
            rag_chat_model (str, optional): Name of the chat model for RAG. Defaults to 'gpt-4o-mini'.
            rag_max_tokens (int, optional): Maximum tokens for completion for RAG. Defaults to 512.
            rag_top_k (int, optional): Top k value for sampling for RAG. Defaults to 3.
            rag_base_url (str, optional): Base URL for the RAG model service.
            **flow_optional_args: Optional arguments for the MaterialsFlow class.

        Raises:
            ValueErrorHandler: If main_extraction_keyword is not provided.
        """
        if main_extraction_keyword is None:
            logger.error(
                "main_extraction_keyword cannot be None. Please provide a valid keyword. Exiting..."
            )
            raise ValueErrorHandler(
                message="Please provide main_extraction_keyword to proceed for identifying sentences based on property."
            )
        if is_test_data_preparation and test_doi_list_file is None:
            logger.error("Test data file name is required for test data preparation.")
            raise ValueErrorHandler(
                message="Test data file name is required for test data preparation."
            )
        self.is_test_data_preparation = is_test_data_preparation
        if is_test_data_preparation:
            self.test_doi_list_file = test_doi_list_file
            if total_test_data is None:
                self.total_test_data = 50
            else:
                self.total_test_data = total_test_data
        llm_config = LLMConfig(
            model=model,
            api_base=api_base,
            base_url=base_url,
            api_key=api_key,
            temperature=temperature,
            top_p=top_p,
            timeout=timeout,
            frequency_penalty=frequency_penalty,
            max_tokens=max_tokens,
        )
        llm = llm_config.get_llm()
        rag_config = RAGConfig(
            rag_db_path=rag_db_path,
            embedding_model=embedding_model,
            rag_chat_model=rag_chat_model,
            rag_max_tokens=rag_max_tokens,
            rag_top_k=rag_top_k,
            rag_base_url=rag_base_url,
        )
        if materials_data_identifier_query is None:
            materials_data_identifier_query = f"Is there any material chemical composition and corresponding {self.main_property_keyword} value mentioned in the paper? Give one word answer. Either yes or no."
        preparator = MatPropDataPreparator(
            main_property_keyword=self.main_property_keyword,
            main_extraction_keyword=main_extraction_keyword,
            json_results_file=json_results_file,
            start_row=start_row,
            num_rows=num_rows,
            is_test_data_preparation=is_test_data_preparation,
            test_doi_list_file=test_doi_list_file,
            is_only_consider_test_doi_list=is_only_consider_test_doi_list,
            total_test_data=total_test_data,
            test_random_seed=test_random_seed,
            checked_doi_list_file=checked_doi_list_file,
        )
        paper_data_list = preparator.get_unprocessed_data()

        paper_metadata_extractor = PaperMetadataExtractor()

        def _has_composition_data(comp_data):
            """Check if composition data contains actual values"""
            if not comp_data or not isinstance(comp_data, dict):
                return False

            comp_values = comp_data.get("compositions_property_values", {})
            return bool(
                comp_values and isinstance(comp_values, dict) and len(comp_values) > 0
            )

        test_dois_with_data = []
        if is_test_data_preparation:
            if os.path.exists(test_doi_list_file):
                try:
                    with open(test_doi_list_file, "r") as f:
                        test_dois_with_data = [
                            line.strip() for line in f.readlines() if line.strip()
                        ]
                        if test_dois_with_data[-1] == "":
                            test_dois_with_data.pop()
                except Exception as e:
                    logger.warning(
                        f"Error reading test DOI file {test_doi_list_file}: {str(e)}"
                    )

        # Extract composition-property and synthesis data
        for paper_data in tqdm(
            paper_data_list,
            total=len(paper_data_list),
            desc="Processing Papers",
            unit="paper",
        ):
            logger.debug(f"\n\nProcessing DOI: {paper_data['doi']}")
            current_doi = paper_data["doi"]

            try:
                try:
                    flow = DataExtractionFlow(
                        doi=paper_data["doi"],
                        main_extraction_keyword=main_extraction_keyword,
                        composition_property_text_data=paper_data["comp_prop_text"],
                        synthesis_text_data=paper_data["synthesis_text"],
                        llm=llm,
                        materials_data_identifier_query=materials_data_identifier_query,
                        is_extract_synthesis_data=is_extract_synthesis_data,
                        rag_config=rag_config,
                        output_log_folder=output_log_folder,
                        task_output_folder=task_output_folder,
                        is_log_json=is_log_json,
                        verbose=verbose,
                        **flow_optional_args,
                    )
                    result_dict = flow.kickoff()

                    # Extract composition and synthesis data
                    composition_data = result_dict["composition_data"]
                    synthesis_data = result_dict["synthesis_data"]
                except Exception as e:
                    logger.error(
                        f"Error in MaterialsFlow processing for DOI: {paper_data['doi']}. {e}"
                    )
                    continue

                # Try to get paper metadata
                try:
                    paper_metadata = paper_metadata_extractor.get_article_metadata(
                        paper_data["doi"]
                    )
                    result_dict["article_metadata"] = paper_metadata
                except Exception as e:
                    logger.error(
                        f"Error fetching paper metadata for DOI: {paper_data['doi']}. {e}"
                    )
                    continue

                # Determine if the paper should be saved or not
                should_save = True
                if not _has_composition_data(composition_data):
                    if is_test_data_preparation:
                        should_save = False
                        logger.debug(
                            f"Skipping save for DOI {current_doi} - no composition data (test data preparation mode)"
                        )
                    elif is_save_relevant:
                        should_save = False
                        logger.debug(
                            f"Skipping save for DOI {current_doi} - no composition data (is_save_relevant is True)"
                        )

                # If the paper is relevant or is_save_relevant is False, save the results
                if should_save:
                    try:
                        result_saver = SaveResults(json_results_file, csv_results_file)
                        result_saver.update_in_json(paper_data["doi"], result_dict)
                        if is_save_csv:
                            result_saver.update_in_csv(result_dict)
                    except Exception as e:
                        logger.error(
                            f"Error saving results for DOI: {paper_data['doi']}. {e}"
                        )
                        continue

                # For test data preparation, track DOIs with non-empty composition data
                if is_test_data_preparation and composition_data != {}:
                    if current_doi not in test_dois_with_data:
                        test_dois_with_data.append(current_doi)
                        with open(test_doi_list_file, "w") as f:
                            for doi in test_dois_with_data:
                                f.write(f"{doi}\n")
                        logger.info(
                            f"Added DOI to test list: {current_doi} (now have {len(test_dois_with_data)})"
                        )
                        if len(test_dois_with_data) >= total_test_data:
                            logger.info(
                                f"Reached target test data count: {total_test_data}"
                            )
                            break

                # log the processed DOI in the checked DOIs file
                try:
                    dir_path = os.path.dirname(checked_doi_list_file)
                    if dir_path:
                        os.makedirs(dir_path, exist_ok=True)
                    # Read existing DOIs first
                    existing_dois = set()
                    if os.path.exists(checked_doi_list_file):
                        with open(checked_doi_list_file, "r") as f:
                            existing_dois = set(line.strip() for line in f)

                    # Append only if DOI is not already present
                    if paper_data["doi"] not in existing_dois:
                        with open(checked_doi_list_file, "a") as f:
                            logger.info(
                                f"Adding DOI to checked list: {paper_data['doi']}"
                            )
                            f.write(f"{paper_data['doi']}\n")
                    else:
                        logger.debug(
                            f"DOI already in checked list: {paper_data['doi']}"
                        )
                except Exception as e:
                    logger.error(
                        f"Error writing to checked DOIs file {checked_doi_list_file}: {str(e)}"
                    )

                # Delay before next paper
                time.sleep(5)  # 5-second delay

            except KeyboardInterrupt as kie:
                logger.error(
                    f"Keyboard Interruption Detected. Exiting the program... {kie}"
                )
                raise KeyboardInterruptHandler()
            except Exception as e:
                logger.error(f"Error processing DOI: {paper_data['doi']}. {e}")
                continue

        data_cleaner = DataCleaner(results_file=json_results_file)
        final_data = data_cleaner.get_useful_data()
        # Save back to the JSON file
        with open(json_results_file, "w", encoding="utf-8") as file:
            json.dump(final_data, file, indent=2, default=str)

    def clean_data(
        self,
        json_results_file: str = None,
        is_save_separate_results: bool = True,
        cleaned_json_results_file: str = "cleaned_results.json",
        is_save_composition_property_file: bool = True,
        composition_property_file: str = "composition_property.json",
        cleaning_strategy: str = "full",
    ):
        """
        Removes extra information (key-value pairs) provided by extracted agents. Finally, cleans the composition-property data based on periodic elements, abbreviations and resolves arithmetic calculations, fractions etc.

        Args:
            json_results_file (str, required): Path to the JSON results file.
            is_save_separate_results (bool, optional): Whether to save separate results file after cleaning. Defaults to True.
            cleaned_json_results_file (str, optional): Path to the cleaned JSON results file with articles having relevant composition-property data. Defaults to "cleaned_results.json".
            is_save_composition_property_file (bool, optional): Whether to save composition-property values to a separate file. Defaults to True.
            composition_property_file (str, optional): Path to the composition-property file containing a dictionary of composition-property data. Defaults to "composition_property.json".
            cleaning_strategy (str, optional): The cleaning strategy to use. Defaults to "full" (with periodic element validation). "basic" (without periodic element validation) is the other option.

        Returns:
            Dict[str, Any]: Cleaned data based on selected strategy with relevant composition-property data.
            Dict[str, Any]: All composition-property values collected from the cleaned data. (Returned only if is_save_composition_property_file is True)
        """
        if json_results_file is None:
            logger.error(
                "json_results_file cannot be None. Please provide a valid file path. Exiting..."
            )
            raise ValueErrorHandler(
                message="Please provide json_results_file to proceed for data cleaning."
            )
        if os.path.exists(json_results_file) is False:
            logger.error(
                f"JSON results file {json_results_file} does not exist. Cannot proceed with data cleaning."
            )
            raise ValueErrorHandler(
                message=f"JSON results file {json_results_file} does not exist. Cannot proceed with data cleaning."
            )
        if cleaning_strategy not in [CleaningStrategy.FULL, CleaningStrategy.BASIC]:
            logger.error(
                f"Invalid cleaning strategy: {cleaning_strategy}. Please choose either 'full' or 'basic'."
            )
            raise ValueErrorHandler(
                message=f"Invalid cleaning strategy: {cleaning_strategy}. Please choose either 'full' or 'basic'."
            )
        data_cleaner = DataCleaner(results_file=json_results_file)
        final_data = data_cleaner.clean_data_with_relevant_compositions(
            strategy=cleaning_strategy
        )
        # Save the cleaned data back to the cleaned JSON file
        if is_save_separate_results:
            result_file = cleaned_json_results_file
        else:
            result_file = json_results_file
        with open(result_file, "w", encoding="utf-8") as file:
            json.dump(final_data, file, indent=2, default=str)
        logger.info(
            f"Cleaned data saved to {result_file} with relevant composition-property data."
        )
        # Collect all composition-property values from all DOIs
        if is_save_composition_property_file:
            all_composition_property_values = {}
            for _, article_data in final_data.items():
                if "composition_data" in article_data:
                    compositions_property_values = article_data["composition_data"].get(
                        "compositions_property_values", {}
                    )
                    all_composition_property_values.update(compositions_property_values)
            # Save all composition-property values to a separate JSON file
            with open(composition_property_file, "w", encoding="utf-8") as file:
                json.dump(all_composition_property_values, file, indent=2, default=str)
            logger.info(
                f"All composition-property values saved to {composition_property_file}."
            )
            return final_data, all_composition_property_values
        return final_data

    def evaluate_semantic(
        self,
        ground_truth_file: str = None,
        test_data_file: str = None,
        extraction_agent_model_name: str = None,
        weights: dict[str, float] = None,
        output_file: str = "semantic_evaluation_result.json",
        is_synthesis_evaluation: bool = True,
        use_semantic_model=True,
        primary_model_name="thellert/physbert_cased",
        fallback_model_name="all-mpnet-base-v2",
        similarity_thresholds=None,
    ):
        """Evaluate the extracted data using semantic evaluation.

        Args:
            ground_truth_file (str, required): Path to the ground truth file
            test_data_file (str, required): Path to the test data file.
            extraction_agent_model_name (str, required): Name of the agent model used for extraction.
            weights (dict, optional): Weights for evaluation metrics. If not provided, uses default weights: {"compositions_property_values": 0.3, "property_unit": 0.1, "family": 0.1, "method": 0.1, "precursors": 0.15, "characterization_techniques": 0.15, "steps": 0.1}
            output_file (str, optional): Path to the output file for saving the evaluation results. Defaults to "semantic_evaluation_result.json".
            is_synthesis_evaluation (bool, optional): A flag to indicate if synthesis evaluation is required. Defaults to True.
            use_semantic_model (bool, optional): A flag to indicate if semantic model should be used for evaluation. Defaults to True. If False, it will use the fallback SequenceMatcher class from difflib library.
            primary_model_name (str, optional): Name of the primary model for semantic evaluation. Defaults to "thellert/physbert_cased".
            fallback_model_name (str, optional): Name of the fallback model for semantic evaluation. Defaults to "all-mpnet-base-v2".
            similarity_thresholds (dict, optional): Similarity thresholds for evaluation. Defaults to 0.8 for each metric.

        Returns:
            results (dict): Evaluation results containing various metrics.
        """
        if not ground_truth_file:
            raise ValueErrorHandler(
                message="Ground truth file path is required for semantic evaluation."
            )
        if not test_data_file:
            raise ValueErrorHandler(
                message="Test data file path is required for semantic evaluation."
            )
        evaluator = MaterialsDataSemanticEvaluator(
            use_semantic_model=use_semantic_model,
            primary_model_name=primary_model_name,
            fallback_model_name=fallback_model_name,
            similarity_thresholds=similarity_thresholds,
        )
        results = evaluator.evaluate(
            ground_truth_file=ground_truth_file,
            test_data_file=test_data_file,
            weights=weights,
            output_file=output_file,
            extraction_agent_model_name=extraction_agent_model_name,
            is_synthesis_evaluation=is_synthesis_evaluation,
        )
        return results

    def evaluate_agentic(
        self,
        ground_truth_file: str = None,
        test_data_file: str = None,
        extraction_agent_model_name: str = None,
        weights: dict[str, float] = None,
        output_file: str = "agentic_evaluation_result.json",
        is_synthesis_evaluation: bool = True,
        llm: Optional[LLM] = None,
    ):
        """Evaluate the extracted data using agentic evaluation.

        Args:
            ground_truth_file (str, required): Path to the ground truth file.
            test_data_file (str, required): Path to the test data file.
            extraction_agent_model_name (str, required): Name of the agent model for evaluation.
            weights (dict, optional): Weights for the evaluation metrics. Defaults to None.
            output_file (str, optional): Path to the output file for saving the evaluation results. Defaults to "agentic_evaluation_result.json".
            is_synthesis_evaluation (bool, optional): A flag to indicate if synthesis evaluation is required. Defaults to True.
            llm (LLM, optional): An instance of the LLM class. Defaults to instance of LLM with model="o3-mini"

        Returns:
            results (dict): Evaluation results containing various metrics.
        """
        if not ground_truth_file:
            raise ValueErrorHandler(
                message="Ground truth file path is required for agentic evaluation."
            )
        if not test_data_file:
            raise ValueErrorHandler(
                message="Test data file path is required for agentic evaluation."
            )

        evaluator = MaterialsDataAgenticEvaluatorFlow(
            ground_truth_file=ground_truth_file,
            test_data_file=test_data_file,
            output_file=output_file,
            extraction_agent_model_name=extraction_agent_model_name,
            is_synthesis_evaluation=is_synthesis_evaluation,
            weights=weights,
            llm=llm,
        )
        results = evaluator.kickoff()
        return results

collect_metadata

collect_metadata(base_queries: Optional[list] = None, extra_queries: Optional[list] = None, start_year: int = int(time.strftime('%Y')), end_year: int = int(time.strftime('%Y')) - 2)

Collect metadata from the articles.

Parameters:

Name Type Description Default
base_queries list

List of base queries to search for in the articles. Defaults to None.

None
extra_queries list

List of extra queries to search for in the articles. Defaults to None.

None
start_year int

Start year for the search. Defaults to int(time.strftime("%Y")).

int(strftime('%Y'))
end_year int

End year for the search. Defaults to int(time.strftime("%Y")) - 2.

int(strftime('%Y')) - 2
Source code in src/comproscanner/comproscanner.py
def collect_metadata(
    self,
    base_queries: Optional[list] = None,
    extra_queries: Optional[list] = None,
    start_year: int = int(time.strftime("%Y")),
    end_year: int = int(time.strftime("%Y")) - 2,
):
    """Collect metadata from the articles.

    Args:
        base_queries (list, optional): List of base queries to search for in the articles. Defaults to None.
        extra_queries (list, optional): List of extra queries to search for in the articles. Defaults to None.
        start_year (int, optional): Start year for the search. Defaults to int(time.strftime("%Y")).
        end_year (int, optional): End year for the search. Defaults to int(time.strftime("%Y")) - 2.
    """
    if start_year < end_year:
        raise ValueErrorHandler(
            message="Start year should be greater than the end year."
        )
    if start_year > int(time.strftime("%Y")):
        raise ValueErrorHandler(
            message="Start year cannot be greater than the current year."
        )
    if start_year == end_year:
        raise ValueErrorHandler(
            message="Start year and End year cannot be the same."
        )
    # Fetch metadata
    fetch_metadata = FetchMetadata(
        main_property_keyword=self.main_property_keyword,
        start_year=start_year,
        end_year=end_year,
        base_queries=base_queries,
        extra_queries=extra_queries,
    )
    fetch_metadata.main_fetch()

    # Filter metadata
    filter_metadata = FilterMetadata(
        main_property_keyword=self.main_property_keyword
    )
    filter_metadata.update_publisher_information()

process_articles

process_articles(property_keywords: dict = None, source_list: list = ['elsevier', 'wiley', 'iop', 'springer'], folder_path: str = None, sql_batch_size: int = 500, csv_batch_size: int = 1, start_row: int = None, end_row: int = None, doi_list: list = None, is_sql_db: bool = False, is_save_xml: bool = False, is_save_pdf: bool = False, rag_db_path: str = 'db', chunk_size: int = 1000, chunk_overlap: int = 25, embedding_model: str = 'huggingface:thellert/physbert_cased')

Process articles for the main property keyword.

Parameters:

Name Type Description Default
property_keywords (dict, required)

A dictionary of property keywords which will be used for filtering sentences and should look like the following:

None
source_list list

List of sources to process the articles from. Defaults to ["elsevier", "wiley", "iop", "springer"] - currently supported publishers.

['elsevier', 'wiley', 'iop', 'springer']
folder_path str

Path to the folder containing PDFs. Defaults to None.

None
sql_batch_size int

The number of rows to write to the database at once (Applicable only if is_sql_db is True). Defaults to 500.

500
csv_batch_size int

The number of rows to write to the CSV file at once. Defaults to 1.

1
start_row int

Start row to process the articles from. Defaults to None.

None
end_row int

End row to process the articles to. Defaults to None.

None
doi_list list

List of DOIs to process the articles for. Defaults to None.

None
is_sql_db bool

A flag to indicate if the data should be written to the database. Defaults to False.

False
is_save_xml bool

A flag to indicate if the XML files should be saved. Defaults to False.

False
is_save_pdf bool

A flag to indicate if the PDF files should be saved. Defaults to False.

False
rag_db_path str

Path to the vector database. Defaults to 'db'.

'db'
chunk_size int

Size of the chunks to split the input text into. Defaults to 1000.

1000
chunk_overlap int

Overlap between the chunks. Defaults to 25.

25
embedding_model str

Name of the embedding model. Defaults to 'thellert/physbert_cased'.

'huggingface:thellert/physbert_cased'

Raises:

Type Description
ValueErrorHandler

If property_keywords is not provided.

Source code in src/comproscanner/comproscanner.py
def process_articles(
    self,
    property_keywords: dict = None,
    source_list: list = ["elsevier", "wiley", "iop", "springer"],
    folder_path: str = None,
    sql_batch_size: int = 500,
    csv_batch_size: int = 1,
    start_row: int = None,
    end_row: int = None,
    doi_list: list = None,
    is_sql_db: bool = False,
    is_save_xml: bool = False,
    is_save_pdf: bool = False,
    rag_db_path: str = "db",
    chunk_size: int = 1000,
    chunk_overlap: int = 25,
    embedding_model: str = "huggingface:thellert/physbert_cased",
):
    """Process articles for the main property keyword.

    Args:
        property_keywords (dict, required): A dictionary of property keywords which will be used for filtering sentences and should look like the following:
        {
            "exact_keywords": ["example1", "example2"],
            "substring_keywords": [" example 1 ", " example 2 "],
        }
        source_list (list, optional): List of sources to process the articles from. Defaults to ["elsevier", "wiley", "iop", "springer"] - currently supported publishers.
        folder_path (str, optional): Path to the folder containing PDFs. Defaults to None.
        sql_batch_size (int, optional): The number of rows to write to the database at once (Applicable only if is_sql_db is True). Defaults to 500.
        csv_batch_size (int, optional): The number of rows to write to the CSV file at once. Defaults to 1.
        start_row (int, optional): Start row to process the articles from. Defaults to None.
        end_row (int, optional): End row to process the articles to. Defaults to None.
        doi_list (list, optional): List of DOIs to process the articles for. Defaults to None.
        is_sql_db (bool, optional): A flag to indicate if the data should be written to the database. Defaults to False.
        is_save_xml (bool, optional): A flag to indicate if the XML files should be saved. Defaults to False.
        is_save_pdf (bool, optional): A flag to indicate if the PDF files should be saved. Defaults to False.
        rag_db_path (str, optional): Path to the vector database. Defaults to 'db'.
        chunk_size (int, optional): Size of the chunks to split the input text into. Defaults to 1000.
        chunk_overlap (int, optional): Overlap between the chunks. Defaults to 25.
        embedding_model (str, optional): Name of the embedding model. Defaults to 'thellert/physbert_cased'.

    Raises:
        ValueErrorHandler: If property_keywords is not provided.
    """
    if property_keywords is None:
        raise ValueErrorHandler(
            message="Please provide property_keywords dictionary to proceed."
        )
    rag_config = RAGConfig(
        rag_db_path=rag_db_path,
        chunk_size=chunk_size,
        chunk_overlap=chunk_overlap,
        embedding_model=embedding_model,
    )

    # Process Elsevier articles
    if "elsevier" in source_list:
        from .article_processors.elsevier_processor import ElsevierArticleProcessor

        elsevier_processor = ElsevierArticleProcessor(
            main_property_keyword=self.main_property_keyword,
            property_keywords=property_keywords,
            sql_batch_size=sql_batch_size,
            csv_batch_size=csv_batch_size,
            start_row=start_row,
            end_row=end_row,
            doi_list=doi_list,
            is_sql_db=is_sql_db,
            is_save_xml=is_save_xml,
            rag_config=rag_config,
        )
        elsevier_processor.process_elsevier_articles()

    # Process Springer articles
    if "springer" in source_list:
        from .article_processors.springer_processor import SpringerArticleProcessor

        springer_processor = SpringerArticleProcessor(
            main_property_keyword=self.main_property_keyword,
            property_keywords=property_keywords,
            sql_batch_size=sql_batch_size,
            csv_batch_size=csv_batch_size,
            start_row=start_row,
            end_row=end_row,
            doi_list=doi_list,
            is_sql_db=is_sql_db,
            is_save_xml=is_save_xml,
            rag_config=rag_config,
        )
        springer_processor.process_springer_articles()

    # Process Wiley articles
    if "wiley" in source_list:
        from .article_processors.wiley_processor import WileyArticleProcessor

        wiley_processor = WileyArticleProcessor(
            main_property_keyword=self.main_property_keyword,
            property_keywords=property_keywords,
            sql_batch_size=sql_batch_size,
            csv_batch_size=csv_batch_size,
            start_row=start_row,
            end_row=end_row,
            doi_list=doi_list,
            is_sql_db=is_sql_db,
            is_save_pdf=is_save_pdf,
            rag_config=rag_config,
        )
        wiley_processor.process_wiley_articles()

    # Process IOP articles
    if "iop" in source_list:
        from .article_processors.iop_processor import IOPArticleProcessor

        iop_processor = IOPArticleProcessor(
            main_property_keyword=self.main_property_keyword,
            property_keywords=property_keywords,
            sql_batch_size=sql_batch_size,
            csv_batch_size=csv_batch_size,
            start_row=start_row,
            end_row=end_row,
            doi_list=doi_list,
            is_sql_db=is_sql_db,
            rag_config=rag_config,
        )
        iop_processor.process_iop_articles()

    # Process PDFs
    if "pdfs" in source_list:
        from .article_processors.pdfs_processor import PDFsProcessor

        pdf_processor = PDFsProcessor(
            folder_path=folder_path,
            main_property_keyword=self.main_property_keyword,
            property_keywords=property_keywords,
            sql_batch_size=sql_batch_size,
            csv_batch_size=csv_batch_size,
            is_sql_db=is_sql_db,
            rag_config=rag_config,
        )
        pdf_processor.process_pdfs()

extract_composition_property_data

extract_composition_property_data(main_extraction_keyword: str = None, start_row: int = 0, num_rows: int = None, is_test_data_preparation=False, test_doi_list_file=None, total_test_data: int = 50, is_only_consider_test_doi_list: bool = False, test_random_seed: int = 42, checked_doi_list_file: str = 'checked_dois.txt', json_results_file: str = 'results.json', csv_results_file: str = 'results.csv', is_extract_synthesis_data: bool = True, is_save_csv: bool = False, is_save_relevant: bool = True, materials_data_identifier_query: str = None, model: str = 'gpt-4o-mini', api_base: Optional[str] = None, base_url: Optional[str] = None, api_key: Optional[str] = None, output_log_folder: Optional[str] = None, is_log_json: bool = False, task_output_folder: Optional[str] = None, verbose: bool = True, temperature: float = 0.1, top_p: float = 0.9, timeout: int = 60, frequency_penalty: Optional[float] = None, max_tokens: Optional[int] = None, rag_db_path: str = 'db', embedding_model: str = 'huggingface:thellert/physbert_cased', rag_chat_model: str = 'gpt-4o-mini', rag_max_tokens: int = 512, rag_top_k: int = 3, rag_base_url: Optional[str] = None, **flow_optional_args)

Extract the composition-property data and synthesis data if the property is present in the article.

Parameters:

Name Type Description Default
main_extraction_keyword (str, required)

The main keyword to extract the composition-property data for.

None
start_row int

Start row to process the articles from. Defaults to 0.

0
num_rows int

Number of rows to process the articles for. Defaults to all rows.

None
is_test_data_preparation bool

A flag to indicate if the test data preparation is required. Defaults to False.

False
test_doi_list_file str

Path to the file containing the test DOIs. Defaults to None.

None
total_test_data int

Total number of test data. Defaults to 50 if not provided and is_test_data_preparation is True.

50
is_only_consider_test_doi_list bool

A flag to indicate if only the test DOI list should be considered. Defaults to False. Should be set to True if the test_doi_list_file has required number of test DOIs.

False
test_random_seed int

Random seed for test data preparation. Defaults to 42.

42
checked_doi_list_file list

List of DOIs which have been checked already. Defaults to "checked_dois.txt".

'checked_dois.txt'
json_results_file str

Path to the JSON results file. Defaults to "results.json".

'results.json'
csv_results_file str

Path to the CSV results file. Defaults to "results.csv".

'results.csv'
is_extract_synthesis_data bool

A flag to indicate if the synthesis data should be extracted. Defaults to True.

True
is_save_csv bool

A flag to indicate if the results should be saved in the CSV file. Defaults to False.

False
is_save_relevant bool

A flag to indicate if only papers with composition-property data should be saved. If True, only saves papers with composition data. If False, saves all processed papers. Defaults to True.

True
llm LLM

An instance of the LLM class. Defaults to None.

required
materials_data_identifier_query str

Query to identify the materials data. Must be an 'yes/no' answer. Defaults to "Is there any material chemical composition and corresponding {main_property_keyword} value mentioned in the paper? GIVE ONE WORD ANSWER. Either yes or no."

None
model (str

optional): The model to use (defaults to "gpt-4o-mini")

required
api_base str

Base URL for standard API endpoints

None
base_url str

Base URL for the model service

None
api_key str

API key for the model service

None
output_log_folder str

Base folder path to save logs. Logs will be saved in {output_log_folder}/{doi}/ subdirectory. Logs will be in JSON format if is_log_json is True, otherwise plain text. Defaults to None.

None
task_output_folder str

Base folder path to save task outputs. Task outputs will be saved as .txt files in {task_output_folder}/{doi}/ subdirectory. Defaults to None.

None
is_log_json bool

Flag to save logs in JSON format. Defaults to False.

False
verbose bool

Flag to enable verbose output inside the terminal (defaults to True)

True
temperature float

Temperature for text generation - controls randomness (defaults to 0.1)

0.1
top_p float

Nucleus sampling parameter for text generation - controls diversity (defaults to 0.9)

0.9
timeout int

Request timeout in seconds (defaults to 60)

60
frequency_penalty float

Frequency penalty for text generation

None
max_tokens int

Maximum tokens for completion

None
rag_db_path str

Path to the vector database. Defaults to 'db'.

'db'
embedding_model str

Name of the embedding model for RAG. Defaults to 'huggingface:thellert/physbert_cased'.

'huggingface:thellert/physbert_cased'
rag_chat_model str

Name of the chat model for RAG. Defaults to 'gpt-4o-mini'.

'gpt-4o-mini'
rag_max_tokens int

Maximum tokens for completion for RAG. Defaults to 512.

512
rag_top_k int

Top k value for sampling for RAG. Defaults to 3.

3
rag_base_url str

Base URL for the RAG model service.

None
**flow_optional_args

Optional arguments for the MaterialsFlow class.

{}

Raises:

Type Description
ValueErrorHandler

If main_extraction_keyword is not provided.

Source code in src/comproscanner/comproscanner.py
def extract_composition_property_data(
    self,
    main_extraction_keyword: str = None,
    start_row: int = 0,
    num_rows: int = None,
    is_test_data_preparation=False,
    test_doi_list_file=None,
    total_test_data: int = 50,
    is_only_consider_test_doi_list: bool = False,
    test_random_seed: int = 42,
    checked_doi_list_file: str = "checked_dois.txt",
    json_results_file: str = "results.json",
    csv_results_file: str = "results.csv",
    is_extract_synthesis_data: bool = True,
    is_save_csv: bool = False,
    is_save_relevant: bool = True,
    materials_data_identifier_query: str = None,  # Will be set based on the main_property_keyword if not provided
    model: str = "gpt-4o-mini",
    api_base: Optional[str] = None,
    base_url: Optional[str] = None,
    api_key: Optional[str] = None,
    output_log_folder: Optional[str] = None,
    is_log_json: bool = False,
    task_output_folder: Optional[str] = None,
    verbose: bool = True,
    temperature: float = 0.1,
    top_p: float = 0.9,
    timeout: int = 60,
    frequency_penalty: Optional[float] = None,
    max_tokens: Optional[int] = None,
    rag_db_path: str = "db",
    embedding_model: str = "huggingface:thellert/physbert_cased",
    rag_chat_model: str = "gpt-4o-mini",
    rag_max_tokens: int = 512,
    rag_top_k: int = 3,
    rag_base_url: Optional[str] = None,
    **flow_optional_args,
):
    """Extract the composition-property data and synthesis data if the property is present in the article.

    Args:
        main_extraction_keyword (str, required): The main keyword to extract the composition-property data for.
        start_row (int, optional): Start row to process the articles from. Defaults to 0.
        num_rows (int, optional): Number of rows to process the articles for. Defaults to all rows.
        is_test_data_preparation (bool, optional): A flag to indicate if the test data preparation is required. Defaults to False.
        test_doi_list_file (str, optional): Path to the file containing the test DOIs. Defaults to None.
        total_test_data (int, optional): Total number of test data. Defaults to 50 if not provided and is_test_data_preparation is True.
        is_only_consider_test_doi_list (bool, optional): A flag to indicate if only the test DOI list should be considered. Defaults to False. Should be set to True if the test_doi_list_file has required number of test DOIs.
        test_random_seed (int, optional): Random seed for test data preparation. Defaults to 42.
        checked_doi_list_file (list, optional): List of DOIs which have been checked already. Defaults to "checked_dois.txt".
        json_results_file (str, optional): Path to the JSON results file. Defaults to "results.json".
        csv_results_file (str, optional): Path to the CSV results file. Defaults to "results.csv".
        is_extract_synthesis_data (bool, optional): A flag to indicate if the synthesis data should be extracted. Defaults to True.
        is_save_csv (bool, optional): A flag to indicate if the results should be saved in the CSV file. Defaults to False.
        is_save_relevant (bool, optional): A flag to indicate if only papers with composition-property data should be saved. If True, only saves papers with composition data. If False, saves all processed papers. Defaults to True.
        llm (LLM, optional): An instance of the LLM class. Defaults to None.
        materials_data_identifier_query (str, optional): Query to identify the materials data. Must be an 'yes/no' answer. Defaults to "Is there any material chemical composition and corresponding {main_property_keyword} value mentioned in the paper? GIVE ONE WORD ANSWER. Either yes or no."
        model (str: optional): The model to use (defaults to "gpt-4o-mini")
        api_base (str, optional): Base URL for standard API endpoints
        base_url (str, optional): Base URL for the model service
        api_key (str, optional): API key for the model service
        output_log_folder (str, optional): Base folder path to save logs. Logs will be saved in {output_log_folder}/{doi}/ subdirectory. Logs will be in JSON format if is_log_json is True, otherwise plain text. Defaults to None.
        task_output_folder (str, optional): Base folder path to save task outputs. Task outputs will be saved as .txt files in {task_output_folder}/{doi}/ subdirectory. Defaults to None.
        is_log_json (bool, optional): Flag to save logs in JSON format. Defaults to False.
        verbose (bool, optional): Flag to enable verbose output inside the terminal (defaults to True)
        temperature (float, optional): Temperature for text generation - controls randomness (defaults to 0.1)
        top_p (float, optional): Nucleus sampling parameter for text generation - controls diversity (defaults to 0.9)
        timeout (int, optional): Request timeout in seconds (defaults to 60)
        frequency_penalty (float, optional): Frequency penalty for text generation
        max_tokens (int, optional): Maximum tokens for completion
        rag_db_path (str, optional): Path to the vector database. Defaults to 'db'.
        embedding_model (str, optional): Name of the embedding model for RAG. Defaults to 'huggingface:thellert/physbert_cased'.
        rag_chat_model (str, optional): Name of the chat model for RAG. Defaults to 'gpt-4o-mini'.
        rag_max_tokens (int, optional): Maximum tokens for completion for RAG. Defaults to 512.
        rag_top_k (int, optional): Top k value for sampling for RAG. Defaults to 3.
        rag_base_url (str, optional): Base URL for the RAG model service.
        **flow_optional_args: Optional arguments for the MaterialsFlow class.

    Raises:
        ValueErrorHandler: If main_extraction_keyword is not provided.
    """
    if main_extraction_keyword is None:
        logger.error(
            "main_extraction_keyword cannot be None. Please provide a valid keyword. Exiting..."
        )
        raise ValueErrorHandler(
            message="Please provide main_extraction_keyword to proceed for identifying sentences based on property."
        )
    if is_test_data_preparation and test_doi_list_file is None:
        logger.error("Test data file name is required for test data preparation.")
        raise ValueErrorHandler(
            message="Test data file name is required for test data preparation."
        )
    self.is_test_data_preparation = is_test_data_preparation
    if is_test_data_preparation:
        self.test_doi_list_file = test_doi_list_file
        if total_test_data is None:
            self.total_test_data = 50
        else:
            self.total_test_data = total_test_data
    llm_config = LLMConfig(
        model=model,
        api_base=api_base,
        base_url=base_url,
        api_key=api_key,
        temperature=temperature,
        top_p=top_p,
        timeout=timeout,
        frequency_penalty=frequency_penalty,
        max_tokens=max_tokens,
    )
    llm = llm_config.get_llm()
    rag_config = RAGConfig(
        rag_db_path=rag_db_path,
        embedding_model=embedding_model,
        rag_chat_model=rag_chat_model,
        rag_max_tokens=rag_max_tokens,
        rag_top_k=rag_top_k,
        rag_base_url=rag_base_url,
    )
    if materials_data_identifier_query is None:
        materials_data_identifier_query = f"Is there any material chemical composition and corresponding {self.main_property_keyword} value mentioned in the paper? Give one word answer. Either yes or no."
    preparator = MatPropDataPreparator(
        main_property_keyword=self.main_property_keyword,
        main_extraction_keyword=main_extraction_keyword,
        json_results_file=json_results_file,
        start_row=start_row,
        num_rows=num_rows,
        is_test_data_preparation=is_test_data_preparation,
        test_doi_list_file=test_doi_list_file,
        is_only_consider_test_doi_list=is_only_consider_test_doi_list,
        total_test_data=total_test_data,
        test_random_seed=test_random_seed,
        checked_doi_list_file=checked_doi_list_file,
    )
    paper_data_list = preparator.get_unprocessed_data()

    paper_metadata_extractor = PaperMetadataExtractor()

    def _has_composition_data(comp_data):
        """Check if composition data contains actual values"""
        if not comp_data or not isinstance(comp_data, dict):
            return False

        comp_values = comp_data.get("compositions_property_values", {})
        return bool(
            comp_values and isinstance(comp_values, dict) and len(comp_values) > 0
        )

    test_dois_with_data = []
    if is_test_data_preparation:
        if os.path.exists(test_doi_list_file):
            try:
                with open(test_doi_list_file, "r") as f:
                    test_dois_with_data = [
                        line.strip() for line in f.readlines() if line.strip()
                    ]
                    if test_dois_with_data[-1] == "":
                        test_dois_with_data.pop()
            except Exception as e:
                logger.warning(
                    f"Error reading test DOI file {test_doi_list_file}: {str(e)}"
                )

    # Extract composition-property and synthesis data
    for paper_data in tqdm(
        paper_data_list,
        total=len(paper_data_list),
        desc="Processing Papers",
        unit="paper",
    ):
        logger.debug(f"\n\nProcessing DOI: {paper_data['doi']}")
        current_doi = paper_data["doi"]

        try:
            try:
                flow = DataExtractionFlow(
                    doi=paper_data["doi"],
                    main_extraction_keyword=main_extraction_keyword,
                    composition_property_text_data=paper_data["comp_prop_text"],
                    synthesis_text_data=paper_data["synthesis_text"],
                    llm=llm,
                    materials_data_identifier_query=materials_data_identifier_query,
                    is_extract_synthesis_data=is_extract_synthesis_data,
                    rag_config=rag_config,
                    output_log_folder=output_log_folder,
                    task_output_folder=task_output_folder,
                    is_log_json=is_log_json,
                    verbose=verbose,
                    **flow_optional_args,
                )
                result_dict = flow.kickoff()

                # Extract composition and synthesis data
                composition_data = result_dict["composition_data"]
                synthesis_data = result_dict["synthesis_data"]
            except Exception as e:
                logger.error(
                    f"Error in MaterialsFlow processing for DOI: {paper_data['doi']}. {e}"
                )
                continue

            # Try to get paper metadata
            try:
                paper_metadata = paper_metadata_extractor.get_article_metadata(
                    paper_data["doi"]
                )
                result_dict["article_metadata"] = paper_metadata
            except Exception as e:
                logger.error(
                    f"Error fetching paper metadata for DOI: {paper_data['doi']}. {e}"
                )
                continue

            # Determine if the paper should be saved or not
            should_save = True
            if not _has_composition_data(composition_data):
                if is_test_data_preparation:
                    should_save = False
                    logger.debug(
                        f"Skipping save for DOI {current_doi} - no composition data (test data preparation mode)"
                    )
                elif is_save_relevant:
                    should_save = False
                    logger.debug(
                        f"Skipping save for DOI {current_doi} - no composition data (is_save_relevant is True)"
                    )

            # If the paper is relevant or is_save_relevant is False, save the results
            if should_save:
                try:
                    result_saver = SaveResults(json_results_file, csv_results_file)
                    result_saver.update_in_json(paper_data["doi"], result_dict)
                    if is_save_csv:
                        result_saver.update_in_csv(result_dict)
                except Exception as e:
                    logger.error(
                        f"Error saving results for DOI: {paper_data['doi']}. {e}"
                    )
                    continue

            # For test data preparation, track DOIs with non-empty composition data
            if is_test_data_preparation and composition_data != {}:
                if current_doi not in test_dois_with_data:
                    test_dois_with_data.append(current_doi)
                    with open(test_doi_list_file, "w") as f:
                        for doi in test_dois_with_data:
                            f.write(f"{doi}\n")
                    logger.info(
                        f"Added DOI to test list: {current_doi} (now have {len(test_dois_with_data)})"
                    )
                    if len(test_dois_with_data) >= total_test_data:
                        logger.info(
                            f"Reached target test data count: {total_test_data}"
                        )
                        break

            # log the processed DOI in the checked DOIs file
            try:
                dir_path = os.path.dirname(checked_doi_list_file)
                if dir_path:
                    os.makedirs(dir_path, exist_ok=True)
                # Read existing DOIs first
                existing_dois = set()
                if os.path.exists(checked_doi_list_file):
                    with open(checked_doi_list_file, "r") as f:
                        existing_dois = set(line.strip() for line in f)

                # Append only if DOI is not already present
                if paper_data["doi"] not in existing_dois:
                    with open(checked_doi_list_file, "a") as f:
                        logger.info(
                            f"Adding DOI to checked list: {paper_data['doi']}"
                        )
                        f.write(f"{paper_data['doi']}\n")
                else:
                    logger.debug(
                        f"DOI already in checked list: {paper_data['doi']}"
                    )
            except Exception as e:
                logger.error(
                    f"Error writing to checked DOIs file {checked_doi_list_file}: {str(e)}"
                )

            # Delay before next paper
            time.sleep(5)  # 5-second delay

        except KeyboardInterrupt as kie:
            logger.error(
                f"Keyboard Interruption Detected. Exiting the program... {kie}"
            )
            raise KeyboardInterruptHandler()
        except Exception as e:
            logger.error(f"Error processing DOI: {paper_data['doi']}. {e}")
            continue

    data_cleaner = DataCleaner(results_file=json_results_file)
    final_data = data_cleaner.get_useful_data()
    # Save back to the JSON file
    with open(json_results_file, "w", encoding="utf-8") as file:
        json.dump(final_data, file, indent=2, default=str)

clean_data

clean_data(json_results_file: str = None, is_save_separate_results: bool = True, cleaned_json_results_file: str = 'cleaned_results.json', is_save_composition_property_file: bool = True, composition_property_file: str = 'composition_property.json', cleaning_strategy: str = 'full')

Removes extra information (key-value pairs) provided by extracted agents. Finally, cleans the composition-property data based on periodic elements, abbreviations and resolves arithmetic calculations, fractions etc.

Parameters:

Name Type Description Default
json_results_file (str, required)

Path to the JSON results file.

None
is_save_separate_results bool

Whether to save separate results file after cleaning. Defaults to True.

True
cleaned_json_results_file str

Path to the cleaned JSON results file with articles having relevant composition-property data. Defaults to "cleaned_results.json".

'cleaned_results.json'
is_save_composition_property_file bool

Whether to save composition-property values to a separate file. Defaults to True.

True
composition_property_file str

Path to the composition-property file containing a dictionary of composition-property data. Defaults to "composition_property.json".

'composition_property.json'
cleaning_strategy str

The cleaning strategy to use. Defaults to "full" (with periodic element validation). "basic" (without periodic element validation) is the other option.

'full'

Returns:

Type Description

Dict[str, Any]: Cleaned data based on selected strategy with relevant composition-property data.

Dict[str, Any]: All composition-property values collected from the cleaned data. (Returned only if is_save_composition_property_file is True)

Source code in src/comproscanner/comproscanner.py
def clean_data(
    self,
    json_results_file: str = None,
    is_save_separate_results: bool = True,
    cleaned_json_results_file: str = "cleaned_results.json",
    is_save_composition_property_file: bool = True,
    composition_property_file: str = "composition_property.json",
    cleaning_strategy: str = "full",
):
    """
    Removes extra information (key-value pairs) provided by extracted agents. Finally, cleans the composition-property data based on periodic elements, abbreviations and resolves arithmetic calculations, fractions etc.

    Args:
        json_results_file (str, required): Path to the JSON results file.
        is_save_separate_results (bool, optional): Whether to save separate results file after cleaning. Defaults to True.
        cleaned_json_results_file (str, optional): Path to the cleaned JSON results file with articles having relevant composition-property data. Defaults to "cleaned_results.json".
        is_save_composition_property_file (bool, optional): Whether to save composition-property values to a separate file. Defaults to True.
        composition_property_file (str, optional): Path to the composition-property file containing a dictionary of composition-property data. Defaults to "composition_property.json".
        cleaning_strategy (str, optional): The cleaning strategy to use. Defaults to "full" (with periodic element validation). "basic" (without periodic element validation) is the other option.

    Returns:
        Dict[str, Any]: Cleaned data based on selected strategy with relevant composition-property data.
        Dict[str, Any]: All composition-property values collected from the cleaned data. (Returned only if is_save_composition_property_file is True)
    """
    if json_results_file is None:
        logger.error(
            "json_results_file cannot be None. Please provide a valid file path. Exiting..."
        )
        raise ValueErrorHandler(
            message="Please provide json_results_file to proceed for data cleaning."
        )
    if os.path.exists(json_results_file) is False:
        logger.error(
            f"JSON results file {json_results_file} does not exist. Cannot proceed with data cleaning."
        )
        raise ValueErrorHandler(
            message=f"JSON results file {json_results_file} does not exist. Cannot proceed with data cleaning."
        )
    if cleaning_strategy not in [CleaningStrategy.FULL, CleaningStrategy.BASIC]:
        logger.error(
            f"Invalid cleaning strategy: {cleaning_strategy}. Please choose either 'full' or 'basic'."
        )
        raise ValueErrorHandler(
            message=f"Invalid cleaning strategy: {cleaning_strategy}. Please choose either 'full' or 'basic'."
        )
    data_cleaner = DataCleaner(results_file=json_results_file)
    final_data = data_cleaner.clean_data_with_relevant_compositions(
        strategy=cleaning_strategy
    )
    # Save the cleaned data back to the cleaned JSON file
    if is_save_separate_results:
        result_file = cleaned_json_results_file
    else:
        result_file = json_results_file
    with open(result_file, "w", encoding="utf-8") as file:
        json.dump(final_data, file, indent=2, default=str)
    logger.info(
        f"Cleaned data saved to {result_file} with relevant composition-property data."
    )
    # Collect all composition-property values from all DOIs
    if is_save_composition_property_file:
        all_composition_property_values = {}
        for _, article_data in final_data.items():
            if "composition_data" in article_data:
                compositions_property_values = article_data["composition_data"].get(
                    "compositions_property_values", {}
                )
                all_composition_property_values.update(compositions_property_values)
        # Save all composition-property values to a separate JSON file
        with open(composition_property_file, "w", encoding="utf-8") as file:
            json.dump(all_composition_property_values, file, indent=2, default=str)
        logger.info(
            f"All composition-property values saved to {composition_property_file}."
        )
        return final_data, all_composition_property_values
    return final_data

evaluate_semantic

evaluate_semantic(ground_truth_file: str = None, test_data_file: str = None, extraction_agent_model_name: str = None, weights: dict[str, float] = None, output_file: str = 'semantic_evaluation_result.json', is_synthesis_evaluation: bool = True, use_semantic_model=True, primary_model_name='thellert/physbert_cased', fallback_model_name='all-mpnet-base-v2', similarity_thresholds=None)

Evaluate the extracted data using semantic evaluation.

Parameters:

Name Type Description Default
ground_truth_file (str, required)

Path to the ground truth file

None
test_data_file (str, required)

Path to the test data file.

None
extraction_agent_model_name (str, required)

Name of the agent model used for extraction.

None
weights dict

Weights for evaluation metrics. If not provided, uses default weights: {"compositions_property_values": 0.3, "property_unit": 0.1, "family": 0.1, "method": 0.1, "precursors": 0.15, "characterization_techniques": 0.15, "steps": 0.1}

None
output_file str

Path to the output file for saving the evaluation results. Defaults to "semantic_evaluation_result.json".

'semantic_evaluation_result.json'
is_synthesis_evaluation bool

A flag to indicate if synthesis evaluation is required. Defaults to True.

True
use_semantic_model bool

A flag to indicate if semantic model should be used for evaluation. Defaults to True. If False, it will use the fallback SequenceMatcher class from difflib library.

True
primary_model_name str

Name of the primary model for semantic evaluation. Defaults to "thellert/physbert_cased".

'thellert/physbert_cased'
fallback_model_name str

Name of the fallback model for semantic evaluation. Defaults to "all-mpnet-base-v2".

'all-mpnet-base-v2'
similarity_thresholds dict

Similarity thresholds for evaluation. Defaults to 0.8 for each metric.

None

Returns:

Name Type Description
results dict

Evaluation results containing various metrics.

Source code in src/comproscanner/comproscanner.py
def evaluate_semantic(
    self,
    ground_truth_file: str = None,
    test_data_file: str = None,
    extraction_agent_model_name: str = None,
    weights: dict[str, float] = None,
    output_file: str = "semantic_evaluation_result.json",
    is_synthesis_evaluation: bool = True,
    use_semantic_model=True,
    primary_model_name="thellert/physbert_cased",
    fallback_model_name="all-mpnet-base-v2",
    similarity_thresholds=None,
):
    """Evaluate the extracted data using semantic evaluation.

    Args:
        ground_truth_file (str, required): Path to the ground truth file
        test_data_file (str, required): Path to the test data file.
        extraction_agent_model_name (str, required): Name of the agent model used for extraction.
        weights (dict, optional): Weights for evaluation metrics. If not provided, uses default weights: {"compositions_property_values": 0.3, "property_unit": 0.1, "family": 0.1, "method": 0.1, "precursors": 0.15, "characterization_techniques": 0.15, "steps": 0.1}
        output_file (str, optional): Path to the output file for saving the evaluation results. Defaults to "semantic_evaluation_result.json".
        is_synthesis_evaluation (bool, optional): A flag to indicate if synthesis evaluation is required. Defaults to True.
        use_semantic_model (bool, optional): A flag to indicate if semantic model should be used for evaluation. Defaults to True. If False, it will use the fallback SequenceMatcher class from difflib library.
        primary_model_name (str, optional): Name of the primary model for semantic evaluation. Defaults to "thellert/physbert_cased".
        fallback_model_name (str, optional): Name of the fallback model for semantic evaluation. Defaults to "all-mpnet-base-v2".
        similarity_thresholds (dict, optional): Similarity thresholds for evaluation. Defaults to 0.8 for each metric.

    Returns:
        results (dict): Evaluation results containing various metrics.
    """
    if not ground_truth_file:
        raise ValueErrorHandler(
            message="Ground truth file path is required for semantic evaluation."
        )
    if not test_data_file:
        raise ValueErrorHandler(
            message="Test data file path is required for semantic evaluation."
        )
    evaluator = MaterialsDataSemanticEvaluator(
        use_semantic_model=use_semantic_model,
        primary_model_name=primary_model_name,
        fallback_model_name=fallback_model_name,
        similarity_thresholds=similarity_thresholds,
    )
    results = evaluator.evaluate(
        ground_truth_file=ground_truth_file,
        test_data_file=test_data_file,
        weights=weights,
        output_file=output_file,
        extraction_agent_model_name=extraction_agent_model_name,
        is_synthesis_evaluation=is_synthesis_evaluation,
    )
    return results

evaluate_agentic

evaluate_agentic(ground_truth_file: str = None, test_data_file: str = None, extraction_agent_model_name: str = None, weights: dict[str, float] = None, output_file: str = 'agentic_evaluation_result.json', is_synthesis_evaluation: bool = True, llm: Optional[LLM] = None)

Evaluate the extracted data using agentic evaluation.

Parameters:

Name Type Description Default
ground_truth_file (str, required)

Path to the ground truth file.

None
test_data_file (str, required)

Path to the test data file.

None
extraction_agent_model_name (str, required)

Name of the agent model for evaluation.

None
weights dict

Weights for the evaluation metrics. Defaults to None.

None
output_file str

Path to the output file for saving the evaluation results. Defaults to "agentic_evaluation_result.json".

'agentic_evaluation_result.json'
is_synthesis_evaluation bool

A flag to indicate if synthesis evaluation is required. Defaults to True.

True
llm LLM

An instance of the LLM class. Defaults to instance of LLM with model="o3-mini"

None

Returns:

Name Type Description
results dict

Evaluation results containing various metrics.

Source code in src/comproscanner/comproscanner.py
def evaluate_agentic(
    self,
    ground_truth_file: str = None,
    test_data_file: str = None,
    extraction_agent_model_name: str = None,
    weights: dict[str, float] = None,
    output_file: str = "agentic_evaluation_result.json",
    is_synthesis_evaluation: bool = True,
    llm: Optional[LLM] = None,
):
    """Evaluate the extracted data using agentic evaluation.

    Args:
        ground_truth_file (str, required): Path to the ground truth file.
        test_data_file (str, required): Path to the test data file.
        extraction_agent_model_name (str, required): Name of the agent model for evaluation.
        weights (dict, optional): Weights for the evaluation metrics. Defaults to None.
        output_file (str, optional): Path to the output file for saving the evaluation results. Defaults to "agentic_evaluation_result.json".
        is_synthesis_evaluation (bool, optional): A flag to indicate if synthesis evaluation is required. Defaults to True.
        llm (LLM, optional): An instance of the LLM class. Defaults to instance of LLM with model="o3-mini"

    Returns:
        results (dict): Evaluation results containing various metrics.
    """
    if not ground_truth_file:
        raise ValueErrorHandler(
            message="Ground truth file path is required for agentic evaluation."
        )
    if not test_data_file:
        raise ValueErrorHandler(
            message="Test data file path is required for agentic evaluation."
        )

    evaluator = MaterialsDataAgenticEvaluatorFlow(
        ground_truth_file=ground_truth_file,
        test_data_file=test_data_file,
        output_file=output_file,
        extraction_agent_model_name=extraction_agent_model_name,
        is_synthesis_evaluation=is_synthesis_evaluation,
        weights=weights,
        llm=llm,
    )
    results = evaluator.kickoff()
    return results

RAGConfig

Configuration class for RAG model.

Parameters:

Name Type Description Default
rag_db_path (str

optional): Path to the SQLite database (default: db).

required
chunk_size (int

optional): Size of the chunks to split the input text into (default: 1000).

required
chunk_overlap (int

optional): Overlap between the chunks (default: 25).

required
embedding_model (str

optional): Name of the embedding model (default: huggingface:thellert/physbert_cased).

required
rag_chat_model (str

optional): Name of the chat model (default: gpt-4o-mini).

required
rag_max_tokens (int

optional): Maximum length of the input text (default: 512).

required
rag_top_k (int

optional): Top k value for sampling (default: 3).

required
Source code in src/comproscanner/utils/configs/rag_config.py
class RAGConfig:
    """
    Configuration class for RAG model.

    Args:
        rag_db_path (str: optional): Path to the SQLite database (default: db).
        chunk_size (int: optional): Size of the chunks to split the input text into (default: 1000).
        chunk_overlap (int: optional): Overlap between the chunks (default: 25).
        embedding_model (str: optional): Name of the embedding model (default: huggingface:thellert/physbert_cased).
        rag_chat_model (str: optional): Name of the chat model (default: gpt-4o-mini).
        rag_max_tokens (int: optional): Maximum length of the input text (default: 512).
        rag_top_k (int: optional): Top k value for sampling (default: 3).
    """

    DEFAULT_DB_PATH = "db"
    DEFAULT_CHUNK_SIZE = 1000
    DEFAULT_CHUNK_OVERLAP = 25
    DEFAULT_EMBEDDING_MODEL = "huggingface:thellert/physbert_cased"
    DEFAULT_CHAT_MODEL = "gpt-4o-mini"
    DEFAULT_MAX_TOKENS = 512
    DEFAULT_TOP_K = 3

    def __init__(
        self,
        rag_db_path: Optional[str] = None,
        chunk_size: Optional[int] = None,
        chunk_overlap: Optional[int] = None,
        embedding_model: Optional[str] = None,
        rag_chat_model: Optional[str] = None,
        rag_max_tokens: Optional[int] = None,
        rag_top_k: Optional[int] = None,
        rag_base_url: Optional[str] = None,
    ):
        self.rag_db_path = rag_db_path or self.DEFAULT_DB_PATH
        self.chunk_size = chunk_size or self.DEFAULT_CHUNK_SIZE
        self.chunk_overlap = chunk_overlap or self.DEFAULT_CHUNK_OVERLAP
        self.embedding_model = embedding_model or self.DEFAULT_EMBEDDING_MODEL
        self.rag_chat_model = rag_chat_model or self.DEFAULT_CHAT_MODEL
        self.rag_max_tokens = rag_max_tokens or self.DEFAULT_MAX_TOKENS
        self.rag_top_k = rag_top_k or self.DEFAULT_TOP_K
        self.rag_base_url = rag_base_url

LLMConfig

Source code in src/comproscanner/utils/configs/llm_config.py
class LLMConfig:
    # Default values
    DEFAULT_MODEL = "gpt-4o-mini"
    DEFAULT_TEMPERATURE = 0.1
    DEFAULT_TOP_P = 0.9
    DEFAULT_TIMEOUT = 60
    DEFAULT_MAX_TOKENS = 2048

    def __init__(
        self,
        model: Optional[str] = None,
        api_base: Optional[str] = None,
        base_url: Optional[str] = None,
        api_key: Optional[str] = None,
        temperature: Optional[float] = None,
        top_p: Optional[float] = None,
        timeout: Optional[int] = None,
        frequency_penalty: Optional[float] = None,
        max_tokens: Optional[int] = None,
    ):
        self.model = model or self.DEFAULT_MODEL
        self.api_base = api_base
        self.base_url = base_url
        self.api_key = api_key
        self.temperature = temperature or self.DEFAULT_TEMPERATURE
        self.top_p = top_p or self.DEFAULT_TOP_P
        self.timeout = timeout or self.DEFAULT_TIMEOUT
        self.frequency_penalty = frequency_penalty
        self.max_tokens = max_tokens

    def get_llm(self) -> LLM:
        """
        Creates and returns an LLM instance based on the model configuration
        for standard CrewAI supported providers.
        """
        # Initialize kwargs with non-None values
        kwargs = {k: v for k, v in self.__dict__.items() if v is not None}

        # Remove model from kwargs as it's handled separately
        kwargs.pop("model", None)

        # Create LLM instance with standard configurations
        standard_kwargs = {"model": self.model}
        standard_kwargs.update(kwargs)
        return LLM(**standard_kwargs)

get_llm

get_llm() -> LLM

Creates and returns an LLM instance based on the model configuration for standard CrewAI supported providers.

Source code in src/comproscanner/utils/configs/llm_config.py
def get_llm(self) -> LLM:
    """
    Creates and returns an LLM instance based on the model configuration
    for standard CrewAI supported providers.
    """
    # Initialize kwargs with non-None values
    kwargs = {k: v for k, v in self.__dict__.items() if v is not None}

    # Remove model from kwargs as it's handled separately
    kwargs.pop("model", None)

    # Create LLM instance with standard configurations
    standard_kwargs = {"model": self.model}
    standard_kwargs.update(kwargs)
    return LLM(**standard_kwargs)

collect_metadata

collect_metadata(main_property_keyword, base_queries=None, extra_queries=None, start_year=None, end_year=None)

Collect metadata from scientific articles.

Parameters:

Name Type Description Default
main_property_keyword str

The main property keyword to search for

required
base_queries list

List of base queries to search for

None
extra_queries list

List of extra queries to search for

None
start_year int

Start year for the search

None
end_year int

End year for the search

None
Source code in src/comproscanner/__init__.py
def collect_metadata(
    main_property_keyword,
    base_queries=None,
    extra_queries=None,
    start_year=None,
    end_year=None,
):
    """
    Collect metadata from scientific articles.

    Args:
        main_property_keyword (str): The main property keyword to search for
        base_queries (list, optional): List of base queries to search for
        extra_queries (list, optional): List of extra queries to search for
        start_year (int, optional): Start year for the search
        end_year (int, optional): End year for the search
    """
    scanner = ComProScanner(main_property_keyword=main_property_keyword)
    return scanner.collect_metadata(
        base_queries=base_queries,
        extra_queries=extra_queries,
        start_year=start_year,
        end_year=end_year,
    )

process_articles

process_articles(main_property_keyword, property_keywords=None, source_list=['elsevier', 'wiley', 'iop', 'springer', 'pdfs'], **kwargs)

Process articles for the main property keyword.

Parameters:

Name Type Description Default
main_property_keyword str

The main property keyword to search for

required
property_keywords dict

Dictionary of property keywords for filtering

None
source_list list

List of sources to process

['elsevier', 'wiley', 'iop', 'springer', 'pdfs']
**kwargs

Additional arguments to pass to the process_articles method

{}
Source code in src/comproscanner/__init__.py
def process_articles(
    main_property_keyword,
    property_keywords=None,
    source_list=["elsevier", "wiley", "iop", "springer", "pdfs"],
    **kwargs,
):
    """
    Process articles for the main property keyword.

    Args:
        main_property_keyword (str): The main property keyword to search for
        property_keywords (dict): Dictionary of property keywords for filtering
        source_list (list, optional): List of sources to process
        **kwargs: Additional arguments to pass to the process_articles method
    """
    scanner = ComProScanner(main_property_keyword=main_property_keyword)
    return scanner.process_articles(
        property_keywords=property_keywords, source_list=source_list, **kwargs
    )

extract_composition_property_data

extract_composition_property_data(main_property_keyword, main_extraction_keyword=None, **kwargs)

Extract composition-property data from articles.

Parameters:

Name Type Description Default
main_property_keyword str

The main property keyword

required
main_extraction_keyword str

The main keyword to extract data for

None
**kwargs

Additional arguments to pass to the extract_composition_property_data method

{}
Source code in src/comproscanner/__init__.py
def extract_composition_property_data(
    main_property_keyword, main_extraction_keyword=None, **kwargs
):
    """
    Extract composition-property data from articles.

    Args:
        main_property_keyword (str): The main property keyword
        main_extraction_keyword (str): The main keyword to extract data for
        **kwargs: Additional arguments to pass to the extract_composition_property_data method
    """
    scanner = ComProScanner(main_property_keyword=main_property_keyword)
    return scanner.extract_composition_property_data(
        main_extraction_keyword=main_extraction_keyword, **kwargs
    )

clean_data

clean_data(main_property_keyword, json_results_file: str = None, is_save_separate_results: bool = True, cleaned_json_results_file: str = 'cleaned_results.json', is_save_composition_property_file: bool = True, composition_property_file: str = 'composition_property.json', cleaning_strategy: str = 'full')

Clean the extracted composition-property data.

Parameters:

Name Type Description Default
main_property_keyword str

The main property keyword

required
json_results_file (str, required)

Path to the JSON results file.

None
is_save_separate_results bool

Whether to save separate results file after cleaning. Defaults to True.

True
cleaned_json_results_file str

Path to the cleaned JSON results file with articles having relevant composition-property data. Defaults to "cleaned_results.json".

'cleaned_results.json'
is_save_composition_property_file bool

Whether to save composition-property values to a separate file. Defaults to True.

True
composition_property_file str

Path to the composition-property file containing a dictionary of composition-property data. Defaults to "composition_property.json".

'composition_property.json'
cleaning_strategy str

The cleaning strategy to use. Defaults to "full" (with periodic element validation). "basic" (without periodic element validation) is the other option.

'full'
Source code in src/comproscanner/__init__.py
def clean_data(
    main_property_keyword,
    json_results_file: str = None,
    is_save_separate_results: bool = True,
    cleaned_json_results_file: str = "cleaned_results.json",
    is_save_composition_property_file: bool = True,
    composition_property_file: str = "composition_property.json",
    cleaning_strategy: str = "full",
):
    """
    Clean the extracted composition-property data.

    Args:
        main_property_keyword (str): The main property keyword
        json_results_file (str, required): Path to the JSON results file.
        is_save_separate_results (bool, optional): Whether to save separate results file after cleaning. Defaults to True.
        cleaned_json_results_file (str, optional): Path to the cleaned JSON results file with articles having relevant composition-property data. Defaults to "cleaned_results.json".
        is_save_composition_property_file (bool, optional): Whether to save composition-property values to a separate file. Defaults to True.
        composition_property_file (str, optional): Path to the composition-property file containing a dictionary of composition-property data. Defaults to "composition_property.json".
        cleaning_strategy (str, optional): The cleaning strategy to use. Defaults to "full" (with periodic element validation). "basic" (without periodic element validation) is the other option.
    """
    scanner = ComProScanner(main_property_keyword=main_property_keyword)
    return scanner.clean_data(
        json_results_file=json_results_file,
        is_save_separate_results=is_save_separate_results,
        cleaned_json_results_file=cleaned_json_results_file,
        is_save_composition_property_file=is_save_composition_property_file,
        composition_property_file=composition_property_file,
        cleaning_strategy=cleaning_strategy,
    )

evaluate_semantic

evaluate_semantic(ground_truth_file=None, test_data_file=None, weights=None, output_file='semantic_evaluation_result.json', extraction_agent_model_name='gpt-4o-mini', is_synthesis_evaluation=True, use_semantic_model=True, primary_model_name='thellert/physbert_cased', fallback_model_name='all-mpnet-base-v2', similarity_thresholds=None)

Evaluate the extracted data using semantic evaluation.

Parameters:

Name Type Description Default
ground_truth_file str

Path to the ground truth file. Defaults to None.

None
test_data_file str

Path to the test data file. Defaults to None.

None
weights dict

Weights for the evaluation metrics. Defaults to None.

None
output_file str

Path to the output file for saving the evaluation results. Defaults to "semantic_evaluation_result.json".

'semantic_evaluation_result.json'
extraction_agent_model_name str

Name of the agent model used for extraction. Defaults to "GPT-4o-mini".

'gpt-4o-mini'
is_synthesis_evaluation bool

A flag to indicate if synthesis evaluation is required. Defaults to True.

True
use_semantic_model bool

A flag to indicate if semantic model should be used for evaluation. Defaults to True.

True
primary_model_name str

Name of the primary model for semantic evaluation. Defaults to "thellert/physbert_cased".

'thellert/physbert_cased'
fallback_model_name str

Name of the fallback model for semantic evaluation. Defaults to "all-mpnet-base-v2".

'all-mpnet-base-v2'
similarity_thresholds dict

Similarity thresholds for evaluation. Defaults to 0.8 for each metric.

None
Source code in src/comproscanner/__init__.py
def evaluate_semantic(
    ground_truth_file=None,
    test_data_file=None,
    weights=None,
    output_file="semantic_evaluation_result.json",
    extraction_agent_model_name="gpt-4o-mini",
    is_synthesis_evaluation=True,
    use_semantic_model=True,
    primary_model_name="thellert/physbert_cased",
    fallback_model_name="all-mpnet-base-v2",
    similarity_thresholds=None,
):
    """
    Evaluate the extracted data using semantic evaluation.

    Args:
        ground_truth_file (str, optional): Path to the ground truth file. Defaults to None.
        test_data_file (str, optional): Path to the test data file. Defaults to None.
        weights (dict, optional): Weights for the evaluation metrics. Defaults to None.
        output_file (str, optional): Path to the output file for saving the evaluation results. Defaults to "semantic_evaluation_result.json".
        extraction_agent_model_name (str, optional): Name of the agent model used for extraction. Defaults to "GPT-4o-mini".
        is_synthesis_evaluation (bool, optional): A flag to indicate if synthesis evaluation is required. Defaults to True.
        use_semantic_model (bool, optional): A flag to indicate if semantic model should be used for evaluation. Defaults to True.
        primary_model_name (str, optional): Name of the primary model for semantic evaluation. Defaults to "thellert/physbert_cased".
        fallback_model_name (str, optional): Name of the fallback model for semantic evaluation. Defaults to "all-mpnet-base-v2".
        similarity_thresholds (dict, optional): Similarity thresholds for evaluation. Defaults to 0.8 for each metric.
    """
    scanner = ComProScanner(main_property_keyword="placeholder")
    return scanner.evaluate_semantic(
        ground_truth_file=ground_truth_file,
        test_data_file=test_data_file,
        weights=weights,
        output_file=output_file,
        agent_model_name=extraction_agent_model_name,
        is_synthesis_evaluation=is_synthesis_evaluation,
        use_semantic_model=use_semantic_model,
        primary_model_name=primary_model_name,
        fallback_model_name=fallback_model_name,
        similarity_thresholds=similarity_thresholds,
    )

evaluate_agentic

evaluate_agentic(ground_truth_file=None, test_data_file=None, output_file='detailed_evaluation.json', extraction_agent_model_name='gpt-4o-mini', is_synthesis_evaluation=True, weights=None, llm=None)

Evaluate the extracted data using agentic evaluation.

Parameters:

Name Type Description Default
ground_truth_file str

Path to the ground truth file. Defaults to None.

None
test_data_file str

Path to the test data file. Defaults to None.

None
output_file str

Path to the output file for saving the evaluation results. Defaults to "detailed_evaluation.json".

'detailed_evaluation.json'
extraction_agent_model_name str

Name of the agent model used for extraction. Defaults to "GPT-4o-mini".

'gpt-4o-mini'
is_synthesis_evaluation bool

A flag to indicate if synthesis evaluation is required. Defaults to True.

True
weights dict

Weights for the evaluation metrics. Defaults to None.

None
llm LLM

An instance of the LLM class. Defaults to None.

None
Source code in src/comproscanner/__init__.py
def evaluate_agentic(
    ground_truth_file=None,
    test_data_file=None,
    output_file="detailed_evaluation.json",
    extraction_agent_model_name="gpt-4o-mini",
    is_synthesis_evaluation=True,
    weights=None,
    llm=None,
):
    """
    Evaluate the extracted data using agentic evaluation.

    Args:
        ground_truth_file (str, optional): Path to the ground truth file. Defaults to None.
        test_data_file (str, optional): Path to the test data file. Defaults to None.
        output_file (str, optional): Path to the output file for saving the evaluation results. Defaults to "detailed_evaluation.json".
        extraction_agent_model_name (str, optional): Name of the agent model used for extraction. Defaults to "GPT-4o-mini".
        is_synthesis_evaluation (bool, optional): A flag to indicate if synthesis evaluation is required. Defaults to True.
        weights (dict, optional): Weights for the evaluation metrics. Defaults to None.
        llm (LLM, optional): An instance of the LLM class. Defaults to None.
    """
    scanner = ComProScanner(main_property_keyword="placeholder")
    return scanner.evaluate_agentic(
        ground_truth_file=ground_truth_file,
        test_data_file=test_data_file,
        output_file=output_file,
        agent_model_name=extraction_agent_model_name,
        is_synthesis_evaluation=is_synthesis_evaluation,
        weights=weights,
        llm=llm,
    )

options: members: - ComProScanner - RAGConfig - LLMConfig - data_visualizer - eval_visualizer show_root_heading: true heading_level: 2

data_visualizer

data_visualizer.py

Author: Aritra Roy Email: contact@aritraroy.live Website: https://aritraroy.live Date: 07-05-2025

plot_family_pie_chart

plot_family_pie_chart(data_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, figsize: Tuple[int, int] = (10, 8), dpi: int = 300, min_percentage: float = 1.0, title: str = 'Distribution of Material Families', color_palette: str = 'Blues', title_fontsize: int = 14, label_fontsize: int = 10, legend_fontsize: int = 10, is_semantic_clustering_enabled: bool = True, similarity_threshold: float = 0.8)

Create a pie chart visualization of material families distribution.

Parameters:

Name Type Description Default
data_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing materials data

None
folder_path str

Path to folder containing JSON data files

None
output_file str

Path to save the output plot image. If None, the plot is not saved.

None
figsize tuple

Figure size as (width, height) in inches (Default: (10, 8))

(10, 8)
dpi int

DPI for output image (Default: 300)

300
min_percentage float

Minimum percentage for a category to be shown separately (Default: 1.0)

1.0
title str

Title for the plot (Default: "Distribution of Material Families")

'Distribution of Material Families'
color_palette str

Matplotlib colormap name for the pie sections (Default: "Blues")

'Blues'
title_fontsize int

Font size for the title (Default: 14)

14
label_fontsize int

Font size for the percentage labels (Default: 10)

10
legend_fontsize int

Font size for the legend (Default: 10)

10
is_semantic_clustering_enabled bool

Whether to use semantic similarity for clustering similar families (Default: True)

True
similarity_threshold float

Similarity threshold for clustering (Default: 0.8)

0.8

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueError

If neither data_sources nor folder_path is provided, or if no family data found

Source code in src/comproscanner/data_visualizer.py
def plot_family_pie_chart(
    data_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    figsize: Tuple[int, int] = (10, 8),
    dpi: int = 300,
    min_percentage: float = 1.0,
    title: str = "Distribution of Material Families",
    color_palette: str = "Blues",
    title_fontsize: int = 14,
    label_fontsize: int = 10,
    legend_fontsize: int = 10,
    is_semantic_clustering_enabled: bool = True,
    similarity_threshold: float = 0.8,
):
    """
    Create a pie chart visualization of material families distribution.

    Args:
        data_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing materials data
        folder_path (str, optional): Path to folder containing JSON data files
        output_file (str, optional): Path to save the output plot image. If None, the plot is not saved.
        figsize (tuple, optional): Figure size as (width, height) in inches (Default: (10, 8))
        dpi (int, optional): DPI for output image (Default: 300)
        min_percentage (float, optional): Minimum percentage for a category to be shown separately (Default: 1.0)
        title (str, optional): Title for the plot (Default: "Distribution of Material Families")
        color_palette (str, optional): Matplotlib colormap name for the pie sections (Default: "Blues")
        title_fontsize (int, optional): Font size for the title (Default: 14)
        label_fontsize (int, optional): Font size for the percentage labels (Default: 10)
        legend_fontsize (int, optional): Font size for the legend (Default: 10)
        is_semantic_clustering_enabled (bool, optional): Whether to use semantic similarity for clustering similar families (Default: True)
        similarity_threshold (float, optional): Similarity threshold for clustering (Default: 0.8)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueError: If neither data_sources nor folder_path is provided, or if no family data found
    """
    visualizer = DataDistributionVisualizer()
    fig = visualizer.plot_family_pie_chart(
        data_sources=data_sources,
        folder_path=folder_path,
        output_file=output_file,
        figsize=figsize,
        dpi=dpi,
        min_percentage=min_percentage,
        title=title,
        color_palette=color_palette,
        title_fontsize=title_fontsize,
        label_fontsize=label_fontsize,
        legend_fontsize=legend_fontsize,
        is_semantic_clustering_enabled=is_semantic_clustering_enabled,
        similarity_threshold=similarity_threshold,
    )
    return fig

plot_family_histogram

plot_family_histogram(data_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, figsize: Tuple[int, int] = (12, 8), dpi: int = 300, max_items: int = 15, title: str = 'Frequency Distribution of Material Families', color_palette: str = 'Blues', x_label: str = 'Material Family', y_label: str = 'Frequency', rotation: int = 45, title_fontsize: int = 14, xlabel_fontsize: int = 12, ylabel_fontsize: int = 12, xtick_fontsize: int = 10, value_label_fontsize: int = 9, grid_axis: str = 'y', grid_linestyle: str = '--', grid_alpha: float = 0.3, is_semantic_clustering_enabled: bool = True, similarity_threshold: float = 0.8)

Create a histogram visualization of material families distribution.

Parameters:

Name Type Description Default
data_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing materials data

None
folder_path str

Path to folder containing JSON data files

None
output_file str

Path to save the output plot image. If None, the plot is not saved.

None
figsize tuple

Figure size as (width, height) in inches (Default: (12, 8))

(12, 8)
dpi int

DPI for output image (Default: 300)

300
max_items int

Maximum number of items to display (Default: 15)

15
title str

Title for the plot (Default: "Frequency Distribution of Material Families")

'Frequency Distribution of Material Families'
color_palette str

Matplotlib colormap name for the bars (Default: "Blues")

'Blues'
x_label str

Label for the x-axis (Default: "Material Family")

'Material Family'
y_label str

Label for the y-axis (Default: "Frequency")

'Frequency'
rotation int

Rotation angle for x-axis labels (Default: 45)

45
title_fontsize int

Font size for the title (Default: 14)

14
xlabel_fontsize int

Font size for the x-axis label (Default: 12)

12
ylabel_fontsize int

Font size for the y-axis label (Default: 12)

12
xtick_fontsize int

Font size for the x-axis tick labels (Default: 10)

10
value_label_fontsize int

Font size for the value labels on bars (Default: 9)

9
grid_axis str

Axis for grid lines ('x', 'y', 'both', or None for no grid) (Default: "y")

'y'
grid_linestyle str

Line style for grid lines (Default: "--")

'--'
grid_alpha float

Alpha (transparency) for grid lines (Default: 0.3)

0.3
is_semantic_clustering_enabled bool

Whether to enable semantic clustering of families (Default: True)

True
similarity_threshold float

Similarity threshold for clustering (Default: 0.8)

0.8

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueError

If neither data_sources nor folder_path is provided, or if no family data found

Source code in src/comproscanner/data_visualizer.py
def plot_family_histogram(
    data_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    figsize: Tuple[int, int] = (12, 8),
    dpi: int = 300,
    max_items: int = 15,
    title: str = "Frequency Distribution of Material Families",
    color_palette: str = "Blues",
    x_label: str = "Material Family",
    y_label: str = "Frequency",
    rotation: int = 45,
    title_fontsize: int = 14,
    xlabel_fontsize: int = 12,
    ylabel_fontsize: int = 12,
    xtick_fontsize: int = 10,
    value_label_fontsize: int = 9,
    grid_axis: str = "y",
    grid_linestyle: str = "--",
    grid_alpha: float = 0.3,
    is_semantic_clustering_enabled: bool = True,
    similarity_threshold: float = 0.8,
):
    """
    Create a histogram visualization of material families distribution.

    Args:
        data_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing materials data
        folder_path (str, optional): Path to folder containing JSON data files
        output_file (str, optional): Path to save the output plot image. If None, the plot is not saved.
        figsize (tuple, optional): Figure size as (width, height) in inches (Default: (12, 8))
        dpi (int, optional): DPI for output image (Default: 300)
        max_items (int, optional): Maximum number of items to display (Default: 15)
        title (str, optional): Title for the plot (Default: "Frequency Distribution of Material Families")
        color_palette (str, optional): Matplotlib colormap name for the bars (Default: "Blues")
        x_label (str, optional): Label for the x-axis (Default: "Material Family")
        y_label (str, optional): Label for the y-axis (Default: "Frequency")
        rotation (int, optional): Rotation angle for x-axis labels (Default: 45)
        title_fontsize (int, optional): Font size for the title (Default: 14)
        xlabel_fontsize (int, optional): Font size for the x-axis label (Default: 12)
        ylabel_fontsize (int, optional): Font size for the y-axis label (Default: 12)
        xtick_fontsize (int, optional): Font size for the x-axis tick labels (Default: 10)
        value_label_fontsize (int, optional): Font size for the value labels on bars (Default: 9)
        grid_axis (str, optional): Axis for grid lines ('x', 'y', 'both', or None for no grid) (Default: "y")
        grid_linestyle (str, optional): Line style for grid lines (Default: "--")
        grid_alpha (float, optional): Alpha (transparency) for grid lines (Default: 0.3)
        is_semantic_clustering_enabled (bool, optional): Whether to enable semantic clustering of families (Default: True)
        similarity_threshold (float, optional): Similarity threshold for clustering (Default: 0.8)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueError: If neither data_sources nor folder_path is provided, or if no family data found
    """
    visualizer = DataDistributionVisualizer()
    fig = visualizer.plot_family_histogram(
        data_sources=data_sources,
        folder_path=folder_path,
        output_file=output_file,
        figsize=figsize,
        dpi=dpi,
        max_items=max_items,
        title=title,
        color_palette=color_palette,
        x_label=x_label,
        y_label=y_label,
        rotation=rotation,
        title_fontsize=title_fontsize,
        xlabel_fontsize=xlabel_fontsize,
        ylabel_fontsize=ylabel_fontsize,
        xtick_fontsize=xtick_fontsize,
        value_label_fontsize=value_label_fontsize,
        grid_axis=grid_axis,
        grid_linestyle=grid_linestyle,
        grid_alpha=grid_alpha,
        is_semantic_clustering_enabled=is_semantic_clustering_enabled,
        similarity_threshold=similarity_threshold,
    )
    return fig

plot_precursors_pie_chart

plot_precursors_pie_chart(data_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, figsize: Tuple[int, int] = (10, 8), dpi: int = 300, min_percentage: float = 1.0, title: str = 'Distribution of Precursors in Materials Synthesis', color_palette: str = 'Blues', title_fontsize: int = 14, label_fontsize: int = 10, legend_fontsize: int = 10, is_semantic_clustering_enabled: bool = True, similarity_threshold: float = 0.8)

Create a pie chart visualization of precursors distribution.

Parameters:

Name Type Description Default
data_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing materials data

None
folder_path str

Path to folder containing JSON data files

None
output_file str

Path to save the output plot image. If None, the plot is not saved.

None
figsize tuple

Figure size as (width, height) in inches (Default: (10, 8))

(10, 8)
dpi int

DPI for output image (Default: 300)

300
min_percentage float

Minimum percentage for a category to be shown separately (Default: 1.0)

1.0
title str

Title for the plot (Default: "Distribution of Precursors in Materials Synthesis")

'Distribution of Precursors in Materials Synthesis'
color_palette str

Matplotlib colormap name for the pie sections (Default: "Blues")

'Blues'
title_fontsize int

Font size for the title (Default: 14)

14
label_fontsize int

Font size for the percentage labels (Default: 10)

10
legend_fontsize int

Font size for the legend (Default: 10)

10
is_semantic_clustering_enabled bool

Whether to use semantic similarity for clustering similar precursors (Default: True)

True
similarity_threshold float

Threshold for similarity-based clustering when is_semantic_clustering_enabled is True (Default: 0.8)

0.8

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueError

If neither data_sources nor folder_path is provided, or if no precursors data found

Source code in src/comproscanner/data_visualizer.py
def plot_precursors_pie_chart(
    data_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    figsize: Tuple[int, int] = (10, 8),
    dpi: int = 300,
    min_percentage: float = 1.0,
    title: str = "Distribution of Precursors in Materials Synthesis",
    color_palette: str = "Blues",
    title_fontsize: int = 14,
    label_fontsize: int = 10,
    legend_fontsize: int = 10,
    is_semantic_clustering_enabled: bool = True,
    similarity_threshold: float = 0.8,
):
    """
    Create a pie chart visualization of precursors distribution.

    Args:
        data_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing materials data
        folder_path (str, optional): Path to folder containing JSON data files
        output_file (str, optional): Path to save the output plot image. If None, the plot is not saved.
        figsize (tuple, optional): Figure size as (width, height) in inches (Default: (10, 8))
        dpi (int, optional): DPI for output image (Default: 300)
        min_percentage (float, optional): Minimum percentage for a category to be shown separately (Default: 1.0)
        title (str, optional): Title for the plot (Default: "Distribution of Precursors in Materials Synthesis")
        color_palette (str, optional): Matplotlib colormap name for the pie sections (Default: "Blues")
        title_fontsize (int, optional): Font size for the title (Default: 14)
        label_fontsize (int, optional): Font size for the percentage labels (Default: 10)
        legend_fontsize (int, optional): Font size for the legend (Default: 10)
        is_semantic_clustering_enabled (bool, optional): Whether to use semantic similarity for clustering similar precursors (Default: True)
        similarity_threshold (float, optional): Threshold for similarity-based clustering when is_semantic_clustering_enabled is True (Default: 0.8)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueError: If neither data_sources nor folder_path is provided, or if no precursors data found
    """
    visualizer = DataDistributionVisualizer()
    fig = visualizer.plot_precursors_pie_chart(
        data_sources=data_sources,
        folder_path=folder_path,
        output_file=output_file,
        figsize=figsize,
        dpi=dpi,
        min_percentage=min_percentage,
        title=title,
        color_palette=color_palette,
        title_fontsize=title_fontsize,
        label_fontsize=label_fontsize,
        legend_fontsize=legend_fontsize,
        is_semantic_clustering_enabled=is_semantic_clustering_enabled,
        similarity_threshold=similarity_threshold,
    )
    return fig

plot_precursors_histogram

plot_precursors_histogram(data_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, figsize: Tuple[int, int] = (12, 8), dpi: int = 300, max_items: int = 15, title: str = 'Frequency Distribution of Precursors in Materials Synthesis', color_palette: str = 'Blues', x_label: str = 'Precursor', y_label: str = 'Frequency', rotation: int = 45, title_fontsize: int = 14, xlabel_fontsize: int = 12, ylabel_fontsize: int = 12, xtick_fontsize: int = 10, value_label_fontsize: int = 9, grid_axis: str = 'y', grid_linestyle: str = '--', grid_alpha: float = 0.3, is_semantic_clustering_enabled: bool = True, similarity_threshold: float = 0.8)

Create a histogram visualization of precursors distribution.

Parameters:

Name Type Description Default
data_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing materials data

None
folder_path str

Path to folder containing JSON data files

None
output_file str

Path to save the output plot image. If None, the plot is not saved.

None
figsize tuple

Figure size as (width, height) in inches (Default: (12, 8))

(12, 8)
dpi int

DPI for output image (Default: 300)

300
max_items int

Maximum number of items to display (Default: 15)

15
title str

Title for the plot (Default: "Frequency Distribution of Precursors in Materials Synthesis")

'Frequency Distribution of Precursors in Materials Synthesis'
color_palette str

Matplotlib colormap name for the bars (Default: "Blues")

'Blues'
x_label str

Label for the x-axis (Default: "Precursor")

'Precursor'
y_label str

Label for the y-axis (Default: "Frequency")

'Frequency'
rotation int

Rotation angle for x-axis labels (Default: 45)

45
title_fontsize int

Font size for the title (Default: 14)

14
xlabel_fontsize int

Font size for the x-axis label (Default: 12)

12
ylabel_fontsize int

Font size for the y-axis label (Default: 12)

12
xtick_fontsize int

Font size for the x-axis tick labels (Default: 10)

10
value_label_fontsize int

Font size for the value labels on bars (Default: 9)

9
grid_axis str

Axis for grid lines ('x', 'y', 'both', or None for no grid) (Default: "y")

'y'
grid_linestyle str

Line style for grid lines (Default: "--")

'--'
grid_alpha float

Alpha (transparency) for grid lines (Default: 0.3)

0.3
is_semantic_clustering_enabled bool

Whether to enable semantic clustering of precursors (Default: True)

True
similarity_threshold float

Similarity threshold for clustering (Default: 0.8)

0.8

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueError

If neither data_sources nor folder_path is provided, or if no precursors data found

Source code in src/comproscanner/data_visualizer.py
def plot_precursors_histogram(
    data_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    figsize: Tuple[int, int] = (12, 8),
    dpi: int = 300,
    max_items: int = 15,
    title: str = "Frequency Distribution of Precursors in Materials Synthesis",
    color_palette: str = "Blues",
    x_label: str = "Precursor",
    y_label: str = "Frequency",
    rotation: int = 45,
    title_fontsize: int = 14,
    xlabel_fontsize: int = 12,
    ylabel_fontsize: int = 12,
    xtick_fontsize: int = 10,
    value_label_fontsize: int = 9,
    grid_axis: str = "y",
    grid_linestyle: str = "--",
    grid_alpha: float = 0.3,
    is_semantic_clustering_enabled: bool = True,
    similarity_threshold: float = 0.8,
):
    """
    Create a histogram visualization of precursors distribution.

    Args:
        data_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing materials data
        folder_path (str, optional): Path to folder containing JSON data files
        output_file (str, optional): Path to save the output plot image. If None, the plot is not saved.
        figsize (tuple, optional): Figure size as (width, height) in inches (Default: (12, 8))
        dpi (int, optional): DPI for output image (Default: 300)
        max_items (int, optional): Maximum number of items to display (Default: 15)
        title (str, optional): Title for the plot (Default: "Frequency Distribution of Precursors in Materials Synthesis")
        color_palette (str, optional): Matplotlib colormap name for the bars (Default: "Blues")
        x_label (str, optional): Label for the x-axis (Default: "Precursor")
        y_label (str, optional): Label for the y-axis (Default: "Frequency")
        rotation (int, optional): Rotation angle for x-axis labels (Default: 45)
        title_fontsize (int, optional): Font size for the title (Default: 14)
        xlabel_fontsize (int, optional): Font size for the x-axis label (Default: 12)
        ylabel_fontsize (int, optional): Font size for the y-axis label (Default: 12)
        xtick_fontsize (int, optional): Font size for the x-axis tick labels (Default: 10)
        value_label_fontsize (int, optional): Font size for the value labels on bars (Default: 9)
        grid_axis (str, optional): Axis for grid lines ('x', 'y', 'both', or None for no grid) (Default: "y")
        grid_linestyle (str, optional): Line style for grid lines (Default: "--")
        grid_alpha (float, optional): Alpha (transparency) for grid lines (Default: 0.3)
        is_semantic_clustering_enabled (bool, optional): Whether to enable semantic clustering of precursors (Default: True)
        similarity_threshold (float, optional): Similarity threshold for clustering (Default: 0.8)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueError: If neither data_sources nor folder_path is provided, or if no precursors data found
    """
    visualizer = DataDistributionVisualizer()
    fig = visualizer.plot_precursors_histogram(
        data_sources=data_sources,
        folder_path=folder_path,
        output_file=output_file,
        figsize=figsize,
        dpi=dpi,
        max_items=max_items,
        title=title,
        color_palette=color_palette,
        x_label=x_label,
        y_label=y_label,
        rotation=rotation,
        title_fontsize=title_fontsize,
        xlabel_fontsize=xlabel_fontsize,
        ylabel_fontsize=ylabel_fontsize,
        xtick_fontsize=xtick_fontsize,
        value_label_fontsize=value_label_fontsize,
        grid_axis=grid_axis,
        grid_linestyle=grid_linestyle,
        grid_alpha=grid_alpha,
        is_semantic_clustering_enabled=is_semantic_clustering_enabled,
        similarity_threshold=similarity_threshold,
    )
    return fig

plot_characterization_techniques_pie_chart

plot_characterization_techniques_pie_chart(data_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, figsize: Tuple[int, int] = (10, 8), dpi: int = 300, min_percentage: float = 1.0, title: str = 'Distribution of Characterization Techniques', color_palette: str = 'Blues', is_semantic_clustering_enabled: bool = True, similarity_threshold: float = 0.8, title_fontsize: int = 14, label_fontsize: int = 10, legend_fontsize: int = 10)

Create a pie chart visualization of characterization techniques distribution.

Parameters:

Name Type Description Default
data_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing materials data

None
folder_path str

Path to folder containing JSON data files

None
output_file str

Path to save the output plot image. If None, the plot is not saved.

None
figsize tuple

Figure size as (width, height) in inches (Default: (10, 8))

(10, 8)
dpi int

DPI for output image (Default: 300)

300
min_percentage float

Minimum percentage for a category to be shown separately (Default: 1.0)

1.0
title str

Title for the plot (Default: "Distribution of Characterization Techniques")

'Distribution of Characterization Techniques'
color_palette str

Matplotlib colormap name for the pie sections (Default: "Blues")

'Blues'
is_semantic_clustering_enabled bool

Whether to use semantic similarity for clustering similar techniques (Default: True)

True
similarity_threshold float

Threshold for similarity-based clustering when is_semantic_clustering_enabled is True (Default: 0.8)

0.8
title_fontsize int

Font size for the title (Default: 14)

14
label_fontsize int

Font size for the percentage labels (Default: 10)

10
legend_fontsize int

Font size for the legend (Default: 10)

10

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueError

If neither data_sources nor folder_path is provided, or if no characterization techniques data found

Source code in src/comproscanner/data_visualizer.py
def plot_characterization_techniques_pie_chart(
    data_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    figsize: Tuple[int, int] = (10, 8),
    dpi: int = 300,
    min_percentage: float = 1.0,
    title: str = "Distribution of Characterization Techniques",
    color_palette: str = "Blues",
    is_semantic_clustering_enabled: bool = True,
    similarity_threshold: float = 0.8,
    title_fontsize: int = 14,
    label_fontsize: int = 10,
    legend_fontsize: int = 10,
):
    """
    Create a pie chart visualization of characterization techniques distribution.

    Args:
        data_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing materials data
        folder_path (str, optional): Path to folder containing JSON data files
        output_file (str, optional): Path to save the output plot image. If None, the plot is not saved.
        figsize (tuple, optional): Figure size as (width, height) in inches (Default: (10, 8))
        dpi (int, optional): DPI for output image (Default: 300)
        min_percentage (float, optional): Minimum percentage for a category to be shown separately (Default: 1.0)
        title (str, optional): Title for the plot (Default: "Distribution of Characterization Techniques")
        color_palette (str, optional): Matplotlib colormap name for the pie sections (Default: "Blues")
        is_semantic_clustering_enabled (bool, optional): Whether to use semantic similarity for clustering similar techniques (Default: True)
        similarity_threshold (float, optional): Threshold for similarity-based clustering when is_semantic_clustering_enabled is True (Default: 0.8)
        title_fontsize (int, optional): Font size for the title (Default: 14)
        label_fontsize (int, optional): Font size for the percentage labels (Default: 10)
        legend_fontsize (int, optional): Font size for the legend (Default: 10)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueError: If neither data_sources nor folder_path is provided, or if no characterization techniques data found
    """
    visualizer = DataDistributionVisualizer()
    fig = visualizer.plot_characterization_techniques_pie_chart(
        data_sources=data_sources,
        folder_path=folder_path,
        output_file=output_file,
        figsize=figsize,
        dpi=dpi,
        min_percentage=min_percentage,
        title=title,
        color_palette=color_palette,
        is_semantic_clustering_enabled=is_semantic_clustering_enabled,
        similarity_threshold=similarity_threshold,
        title_fontsize=title_fontsize,
        label_fontsize=label_fontsize,
        legend_fontsize=legend_fontsize,
    )
    return fig

plot_characterization_techniques_histogram

plot_characterization_techniques_histogram(data_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, figsize: Tuple[int, int] = (14, 8), dpi: int = 300, max_items: int = 15, title: str = 'Frequency Distribution of Characterization Techniques', color_palette: str = 'Blues', x_label: str = 'Characterization Technique', y_label: str = 'Frequency', rotation: int = 45, is_semantic_clustering_enabled: bool = True, similarity_threshold: float = 0.8, title_fontsize: int = 14, xlabel_fontsize: int = 12, ylabel_fontsize: int = 12, xtick_fontsize: int = 10, value_label_fontsize: int = 9, grid_axis: str = 'y', grid_linestyle: str = '--', grid_alpha: float = 0.3)

Create a histogram visualization of characterization techniques distribution.

Parameters:

Name Type Description Default
data_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing materials data

None
folder_path str

Path to folder containing JSON data files

None
output_file str

Path to save the output plot image. If None, the plot is not saved.

None
figsize tuple

Figure size as (width, height) in inches (Default: (14, 8))

(14, 8)
dpi int

DPI for output image (Default: 300)

300
max_items int

Maximum number of items to display (Default: 15)

15
title str

Title for the plot (Default: "Frequency Distribution of Characterization Techniques")

'Frequency Distribution of Characterization Techniques'
color_palette str

Matplotlib colormap name for the bars (Default: "Blues")

'Blues'
x_label str

Label for the x-axis (Default: "Characterization Technique")

'Characterization Technique'
y_label str

Label for the y-axis (Default: "Frequency")

'Frequency'
rotation int

Rotation angle for x-axis labels (Default: 45)

45
is_semantic_clustering_enabled bool

Whether to use semantic similarity for clustering similar techniques (Default: True)

True
similarity_threshold float

Threshold for similarity-based clustering when is_semantic_clustering_enabled is True (Default: 0.8)

0.8
title_fontsize int

Font size for the title (Default: 14)

14
xlabel_fontsize int

Font size for the x-axis label (Default: 12)

12
ylabel_fontsize int

Font size for the y-axis label (Default: 12)

12
xtick_fontsize int

Font size for the x-axis tick labels (Default: 10)

10
value_label_fontsize int

Font size for the value labels on bars (Default: 9)

9
grid_axis str

Axis for grid lines ('x', 'y', 'both', or None for no grid) (Default: "y")

'y'
grid_linestyle str

Line style for grid lines (Default: "--")

'--'
grid_alpha float

Alpha (transparency) for grid lines (Default: 0.3)

0.3

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueError

If neither data_sources nor folder_path is provided, or if no characterization techniques data found

Source code in src/comproscanner/data_visualizer.py
def plot_characterization_techniques_histogram(
    data_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    figsize: Tuple[int, int] = (14, 8),
    dpi: int = 300,
    max_items: int = 15,
    title: str = "Frequency Distribution of Characterization Techniques",
    color_palette: str = "Blues",
    x_label: str = "Characterization Technique",
    y_label: str = "Frequency",
    rotation: int = 45,
    is_semantic_clustering_enabled: bool = True,
    similarity_threshold: float = 0.8,
    title_fontsize: int = 14,
    xlabel_fontsize: int = 12,
    ylabel_fontsize: int = 12,
    xtick_fontsize: int = 10,
    value_label_fontsize: int = 9,
    grid_axis: str = "y",
    grid_linestyle: str = "--",
    grid_alpha: float = 0.3,
):
    """
    Create a histogram visualization of characterization techniques distribution.

    Args:
        data_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing materials data
        folder_path (str, optional): Path to folder containing JSON data files
        output_file (str, optional): Path to save the output plot image. If None, the plot is not saved.
        figsize (tuple, optional): Figure size as (width, height) in inches (Default: (14, 8))
        dpi (int, optional): DPI for output image (Default: 300)
        max_items (int, optional): Maximum number of items to display (Default: 15)
        title (str, optional): Title for the plot (Default: "Frequency Distribution of Characterization Techniques")
        color_palette (str, optional): Matplotlib colormap name for the bars (Default: "Blues")
        x_label (str, optional): Label for the x-axis (Default: "Characterization Technique")
        y_label (str, optional): Label for the y-axis (Default: "Frequency")
        rotation (int, optional): Rotation angle for x-axis labels (Default: 45)
        is_semantic_clustering_enabled (bool, optional): Whether to use semantic similarity for clustering similar techniques (Default: True)
        similarity_threshold (float, optional): Threshold for similarity-based clustering when is_semantic_clustering_enabled is True (Default: 0.8)
        title_fontsize (int, optional): Font size for the title (Default: 14)
        xlabel_fontsize (int, optional): Font size for the x-axis label (Default: 12)
        ylabel_fontsize (int, optional): Font size for the y-axis label (Default: 12)
        xtick_fontsize (int, optional): Font size for the x-axis tick labels (Default: 10)
        value_label_fontsize (int, optional): Font size for the value labels on bars (Default: 9)
        grid_axis (str, optional): Axis for grid lines ('x', 'y', 'both', or None for no grid) (Default: "y")
        grid_linestyle (str, optional): Line style for grid lines (Default: "--")
        grid_alpha (float, optional): Alpha (transparency) for grid lines (Default: 0.3)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueError: If neither data_sources nor folder_path is provided, or if no characterization techniques data found
    """
    visualizer = DataDistributionVisualizer()
    fig = visualizer.plot_characterization_techniques_histogram(
        data_sources=data_sources,
        folder_path=folder_path,
        output_file=output_file,
        figsize=figsize,
        dpi=dpi,
        max_items=max_items,
        title=title,
        color_palette=color_palette,
        x_label=x_label,
        y_label=y_label,
        rotation=rotation,
        is_semantic_clustering_enabled=is_semantic_clustering_enabled,
        similarity_threshold=similarity_threshold,
        title_fontsize=title_fontsize,
        xlabel_fontsize=xlabel_fontsize,
        ylabel_fontsize=ylabel_fontsize,
        xtick_fontsize=xtick_fontsize,
        value_label_fontsize=value_label_fontsize,
        grid_axis=grid_axis,
        grid_linestyle=grid_linestyle,
        grid_alpha=grid_alpha,
    )
    return fig

create_knowledge_graph

create_knowledge_graph(result_file: str = None, is_semantic_clustering_enabled: bool = True, family_clustering_similarity_threshold: float = 0.9, method_clustering_similarity_threshold: float = 0.8, precursor_clustering_similarity_threshold: float = 0.9, technique_clustering_similarity_threshold: float = 0.8, keyword_clustering_similarity_threshold: float = 0.85)

Create a knowledge graph from extracted composition-property data directly in Neo4j database.

Parameters:

Name Type Description Default
result_file (str, required)

Path to the JSON file containing extracted results.

None
is_semantic_clustering_enabled bool

Whether to enable clustering of similar compositions (Default: True)

True
family_clustering_similarity_threshold float

Similarity threshold for family clustering (Default: 0.9)

0.9
method_clustering_similarity_threshold float

Similarity threshold for method clustering (Default: 0.8)

0.8
precursor_clustering_similarity_threshold float

Similarity threshold for precursor clustering (Default: 0.9)

0.9
technique_clustering_similarity_threshold float

Similarity threshold for technique clustering (Default: 0.8)

0.8
keyword_clustering_similarity_threshold float

Similarity threshold for keyword clustering (Default: 0.85)

0.85

Returns:

Type Description

None (knowledge graph is created directly in Neo4j database).

Raises:

Type Description
ValueErrorHandler

If result_file is not provided.

Source code in src/comproscanner/data_visualizer.py
def create_knowledge_graph(
    result_file: str = None,
    is_semantic_clustering_enabled: bool = True,
    family_clustering_similarity_threshold: float = 0.9,
    method_clustering_similarity_threshold: float = 0.8,
    precursor_clustering_similarity_threshold: float = 0.9,
    technique_clustering_similarity_threshold: float = 0.8,
    keyword_clustering_similarity_threshold: float = 0.85,
):
    """
    Create a knowledge graph from extracted composition-property data directly in Neo4j database.

    Args:
        result_file (str, required): Path to the JSON file containing extracted results.
        is_semantic_clustering_enabled (bool, optional): Whether to enable clustering of similar compositions (Default: True)
        family_clustering_similarity_threshold (float, optional): Similarity threshold for family clustering (Default: 0.9)
        method_clustering_similarity_threshold (float, optional): Similarity threshold for method clustering (Default: 0.8)
        precursor_clustering_similarity_threshold (float, optional): Similarity threshold for precursor clustering (Default: 0.9)
        technique_clustering_similarity_threshold (float, optional): Similarity threshold for technique clustering (Default: 0.8)
        keyword_clustering_similarity_threshold (float, optional): Similarity threshold for keyword clustering (Default: 0.85)

    Returns:
        None (knowledge graph is created directly in Neo4j database).

    Raises:
        ValueErrorHandler: If result_file is not provided.
    """
    if result_file is None:
        logger.error(
            "result_file cannot be None. Please provide a valid file path. Exiting..."
        )
        raise ValueErrorHandler(
            message="Please provide result_file path to proceed for creating knowledge graph."
        )

    try:
        with CreateKG() as create_kg:
            return create_kg.create_knowledge_graph(
                result_file=result_file,
                is_semantic_clustering_enabled=is_semantic_clustering_enabled,
                method_clustering_similarity_threshold=method_clustering_similarity_threshold,
                technique_clustering_similarity_threshold=technique_clustering_similarity_threshold,
                keyword_clustering_similarity_threshold=keyword_clustering_similarity_threshold,
                family_clustering_similarity_threshold=family_clustering_similarity_threshold,
                precursor_clustering_similarity_threshold=precursor_clustering_similarity_threshold,
            )
    except Exception as e:
        logger.error(f"Error creating knowledge graph: {e}")
        raise

options: show_root_heading: true heading_level: 2

eval_visualizer

Visualization module for ComProScanner evaluation results.

This module provides functions for creating various visualizations of evaluation results, including bar charts, radar charts, heatmaps, histograms, and violin plots.

plot_single_bar_chart

plot_single_bar_chart(result_file: str | None = None, result_dict: dict | None = None, output_file: str | None = None, model_name: str | None = None, figsize: Tuple[int, int] = (12, 8), colormap: str | None = 'Blues', display_values: bool = True, title: str | None = None, typical_threshold: float | None = None, threashold_line_style: str | None = '--', threashold_tolerance_range: float | None = 0.03, threshold_color: str | None = 'red', show_grid: bool = True, bar_width: float = 0.6, y_axis_label: str = 'Score', x_axis_label: str | None = None, y_axis_range: Tuple[float, float] = (0, 1), dpi: int = 300, metrics_to_include: List[str] | None = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'absolute_precision', 'absolute_recall', 'absolute_f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

Plot evaluation metrics from results file or dictionary.

Parameters:

Name Type Description Default
result_file str

Path to the JSON file containing evaluation results

None
result_dict dict

Dictionary containing evaluation results

None
output_file str

Path to save the output plot image

None
model_name str

Name of the model used for evaluation

None
figsize tuple

Figure size (width, height) in inches (default: (12, 8))

(12, 8)
colormap str

Matplotlib colormap name (e.g., 'Blues', 'Greens', 'Oranges', etc.) (default: 'Blues')

'Blues'
display_values bool

Whether to display metric values on bars

True
title str

Custom title for the plot (default: True)

None
typical_threshold float

Typical threshold value to display as a horizontal line on the plot (default: None)

None
threashold_line_style str

Style of the threshold line (default: '--')

'--'
threashold_tolerance_range float

Tolerance range for the threshold line (default: 0.03)

0.03
threshold_color str

Color for the threshold line (default: 'red')

'red'
show_grid bool

Whether to display horizontal grid lines in the plot (default: True)

True
bar_width float

Width of the bars in the plot (default: 0.6)

0.6
y_axis_label str

Label for the y-axis (default: "Score")

'Score'
x_axis_label str

Label for the x-axis (default: None)

None
y_axis_range tuple

Range for the y-axis (default: (0, 1))

(0, 1)
dpi int

dpi for the output image (default: 300)

300
metrics_to_include list

List of metrics to include in the plot (default: ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'absolute_precision', 'absolute_recall', 'absolute_f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'absolute_precision', 'absolute_recall', 'absolute_f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueError

If neither result_file nor result_dict is provided

Source code in src/comproscanner/eval_visualizer.py
def plot_single_bar_chart(
    result_file: str | None = None,
    result_dict: dict | None = None,
    output_file: str | None = None,
    model_name: str | None = None,
    figsize: Tuple[int, int] = (12, 8),
    colormap: str | None = "Blues",
    display_values: bool = True,
    title: str | None = None,
    typical_threshold: float | None = None,
    threashold_line_style: str | None = "--",
    threashold_tolerance_range: float | None = 0.03,
    threshold_color: str | None = "red",
    show_grid: bool = True,
    bar_width: float = 0.6,
    y_axis_label: str = "Score",
    x_axis_label: str | None = None,
    y_axis_range: Tuple[float, float] = (0, 1),
    dpi: int = 300,
    metrics_to_include: List[str] | None = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "absolute_precision",
        "absolute_recall",
        "absolute_f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
):
    """
    Plot evaluation metrics from results file or dictionary.

    Args:
        result_file (str, optional): Path to the JSON file containing evaluation results
        result_dict (dict, optional): Dictionary containing evaluation results
        output_file (str, optional): Path to save the output plot image
        model_name (str, optional): Name of the model used for evaluation
        figsize (tuple, optional): Figure size (width, height) in inches (default: (12, 8))
        colormap (str, optional): Matplotlib colormap name (e.g., 'Blues', 'Greens', 'Oranges', etc.) (default: 'Blues')
        display_values (bool, optional): Whether to display metric values on bars
        title (str, optional): Custom title for the plot (default: True)
        typical_threshold (float, optional): Typical threshold value to display as a horizontal line on the plot (default: None)
        threashold_line_style (str, optional): Style of the threshold line (default: '--')
        threashold_tolerance_range (float, optional): Tolerance range for the threshold line (default: 0.03)
        threshold_color (str, optional): Color for the threshold line (default: 'red')
        show_grid (bool, optional): Whether to display horizontal grid lines in the plot (default: True)
        bar_width (float, optional): Width of the bars in the plot (default: 0.6)
        y_axis_label (str, optional): Label for the y-axis (default: "Score")
        x_axis_label (str, optional): Label for the x-axis (default: None)
        y_axis_range (tuple, optional): Range for the y-axis (default: (0, 1))
        dpi (int, optional): dpi for the output image (default: 300)
        metrics_to_include (list, optional): List of metrics to include in the plot (default: ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'absolute_precision', 'absolute_recall', 'absolute_f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueError: If neither result_file nor result_dict is provided
    """

    visualizer = EvalVisualizer()
    fig = visualizer.plot_single_bar_chart(
        result_file=result_file,
        result_dict=result_dict,
        output_file=output_file,
        model_name=model_name,
        figsize=figsize,
        colormap=colormap,
        display_values=display_values,
        title=title,
        typical_threshold=typical_threshold,
        threashold_line_style=threashold_line_style,
        threashold_tolerance_range=threashold_tolerance_range,
        threshold_color=threshold_color,
        show_grid=show_grid,
        bar_width=bar_width,
        y_axis_label=y_axis_label,
        x_axis_label=x_axis_label,
        y_axis_range=y_axis_range,
        dpi=dpi,
        metrics_to_include=metrics_to_include,
    )
    return fig

plot_multiple_bar_charts

plot_multiple_bar_charts(result_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, model_names: Optional[List[str]] = None, figsize: Tuple[int, int] = (14, 10), colormap: str = 'Blues', display_values: bool = True, title: Optional[str] = None, typical_threshold: Optional[float] = None, threshold_line_style: str = '--', threashold_tolerance_range: float = 0.03, threshold_color: str = 'red', show_grid: bool = True, y_label: str = 'Score', x_label: Optional[str] = None, group_width: float = 0.8, bar_width: Optional[float] = None, legend_loc: str = 'best', legend_fontsize: int = 10, y_axis_range: Tuple[float, float] = (0, 1), dpi: int = 300, metrics_to_include: Optional[List[str]] = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

Plot evaluation metrics from multiple result files or dictionaries as grouped bar charts.

Parameters:

Name Type Description Default
result_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing evaluation results

None
folder_path Optional[str]

Path to folder containing JSON result files

None
output_file str

Path to save the output plot image

None
model_names Optional[List[str]]

Names of models to display in the legend, defaults to filename or agent_model_name from results

None
figsize Tuple[int, int]

Figure size (width, height) in inches

(14, 10)
colormap str

Matplotlib colormap name for the bars

'Blues'
display_values bool

Whether to display metric values on bars

True
title Optional[str]

Custom title for the plot

None
typical_threshold Optional[float]

Typical threshold value to display as a horizontal line [If not provided, no line is drawn]

None
threshold_line_style str

Style of the threshold line (default: '--')

'--'
threashold_tolerance_range float

Tolerance range for the threshold line (default: 0.03)

0.03
threshold_color str

Color for the threshold line (default: 'red')

'red'
show_grid bool

Whether to display horizontal grid lines in the plot (default: True)

True
y_label str

Label for the y-axis (default: 'Score')

'Score'
x_label Optional[str]

Label for the x-axis (default: None)

None
group_width float

Width allocated for each group of bars (0-1)

0.8
bar_width Optional[float]

Width of individual bars, calculated automatically if None (default: None)

None
legend_loc str

Location of the legend (default: 'upper right')

'best'
legend_fontsize int

Font size for the legend (default: 10)

10
y_axis_range Tuple[float, float]

Range for the y-axis (default: (0, 1))

(0, 1)
dpi int

dpi for the output image (default: 300)

300
metrics_to_include Optional[List[str]]

List of metrics to include from the plot (default: ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_sources nor folder_path is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_multiple_bar_charts(
    result_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    model_names: Optional[List[str]] = None,
    figsize: Tuple[int, int] = (14, 10),
    colormap: str = "Blues",
    display_values: bool = True,
    title: Optional[str] = None,
    typical_threshold: Optional[float] = None,
    threshold_line_style: str = "--",
    threashold_tolerance_range: float = 0.03,
    threshold_color: str = "red",
    show_grid: bool = True,
    y_label: str = "Score",
    x_label: Optional[str] = None,
    group_width: float = 0.8,
    bar_width: Optional[float] = None,
    legend_loc: str = "best",
    legend_fontsize: int = 10,
    y_axis_range: Tuple[float, float] = (0, 1),
    dpi: int = 300,
    metrics_to_include: Optional[List[str]] = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "precision",
        "recall",
        "f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
):
    """
    Plot evaluation metrics from multiple result files or dictionaries as grouped bar charts.

    Args:
        result_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing evaluation results
        folder_path (Optional[str], optional): Path to folder containing JSON result files
        output_file (str, optional): Path to save the output plot image
        model_names (Optional[List[str]]): Names of models to display in the legend, defaults to filename or agent_model_name from results
        figsize (Tuple[int, int]): Figure size (width, height) in inches
        colormap (str): Matplotlib colormap name for the bars
        display_values (bool): Whether to display metric values on bars
        title (Optional[str]): Custom title for the plot
        typical_threshold (Optional[float]): Typical threshold value to display as a horizontal line [If not provided, no line is drawn]
        threshold_line_style (str): Style of the threshold line (default: '--')
        threashold_tolerance_range (float): Tolerance range for the threshold line (default: 0.03)
        threshold_color (str): Color for the threshold line (default: 'red')
        show_grid (bool): Whether to display horizontal grid lines in the plot (default: True)
        y_label (str): Label for the y-axis (default: 'Score')
        x_label (Optional[str]): Label for the x-axis (default: None)
        group_width (float): Width allocated for each group of bars (0-1)
        bar_width (Optional[float]): Width of individual bars, calculated automatically if None (default: None)
        legend_loc (str): Location of the legend (default: 'upper right')
        legend_fontsize (int): Font size for the legend (default: 10)
        y_axis_range (Tuple[float, float]): Range for the y-axis (default: (0, 1))
        dpi (int): dpi for the output image (default: 300)
        metrics_to_include (Optional[List[str]]): List of metrics to include from the plot (default: ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_sources nor folder_path is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_multiple_bar_charts(
        result_sources=result_sources,
        folder_path=folder_path,
        output_file=output_file,
        model_names=model_names,
        figsize=figsize,
        colormap=colormap,
        display_values=display_values,
        title=title,
        typical_threshold=typical_threshold,
        threshold_line_style=threshold_line_style,
        threashold_tolerance_range=threashold_tolerance_range,
        threshold_color=threshold_color,
        show_grid=show_grid,
        y_label=y_label,
        x_label=x_label,
        group_width=group_width,
        bar_width=bar_width,
        legend_loc=legend_loc,
        legend_fontsize=legend_fontsize,
        y_axis_range=y_axis_range,
        dpi=dpi,
        metrics_to_include=metrics_to_include,
    )
    return fig

plot_single_radar_chart

plot_single_radar_chart(result_file: Optional[str] = None, result_dict: Optional[dict] = None, output_file: Optional[str] = None, model_name: Optional[str] = None, figsize: Tuple[int, int] = (10, 8), colormap: str = 'Blues', display_values: bool = False, title: Optional[str] = None, title_fontsize: int = 14, title_pad: Optional[float] = 50.0, typical_threshold: Optional[float] = None, threshold_color: str = 'red', threshold_line_style: str = '--', label_fontsize: int = 12, value_fontsize: int = 10, legend_loc: str = 'best', legend_fontsize: int = 10, bbox_to_anchor: Optional[Tuple[float, float]] = None, show_grid: bool = True, show_grid_labels: bool = False, grid_line_width: float = 1.0, grid_line_style: str = '-', grid_line_color: str = 'gray', grid_line_alpha: float = 0.2, fill_alpha: float = 0.4, marker_size: int = 7, line_width: float = 2, label_padding: float = 0.25, clockwise: bool = True, start_angle: float = np.pi / 2, radar_range: Tuple[float, float] = (0, 1), dpi: int = 300, metrics_to_include: Optional[List[str]] = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

Plot radar chart for a single evaluation result.

Parameters:

Name Type Description Default
result_file str

Path to JSON file containing evaluation results

None
result_dict dict

Dictionary containing evaluation results

None
output_file str

Path to save the output plot image

None
model_name str

Name of the model for display

None
figsize tuple

Figure size (width, height) in inches

(10, 8)
colormap str

Matplotlib colormap name

'Blues'
display_values bool

Whether to display metric values on chart

False
title str

Custom title for the plot

None
title_fontsize int

Font size for the title

14
title_pad float

Padding for the title from the top of the plot

50.0
typical_threshold float

Threshold value to display as a circular line

None
threshold_color str

Color for the threshold line

'red'
threshold_line_style str

Style of the threshold line

'--'
label_fontsize int

Font size for axis labels

12
value_fontsize int

Font size for displayed values

10
legend_loc str

Location for the legend box (default: 'best')

'best'
legend_fontsize int

Font size for the legend

10
bbox_to_anchor tuple

Bounding box for the legend box (default: None)

None
show_grid bool

Whether to display the grid lines

True
show_grid_labels bool

Whether to display grid line values/labels

False
grid_line_width float

Width of the grid lines

1.0
grid_line_style str

Style of the grid lines

'-'
grid_line_color str

Color of the grid lines

'gray'
grid_line_alpha float

Alpha (transparency) of the grid lines

0.2
fill_alpha float

Alpha (transparency) of the filled area

0.4
marker_size int

Size of the data point markers

7
line_width float

Width of the plot lines

2
label_padding float

Distance padding for axis labels from plot

0.25
clockwise bool

Direction of the radar chart

True
start_angle float

Start angle in radians

pi / 2
radar_range tuple

Range for the radar axes

(0, 1)
dpi int

DPI for the output image

300
metrics_to_include list

List of metrics to include

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_file nor result_dict is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_single_radar_chart(
    result_file: Optional[str] = None,
    result_dict: Optional[dict] = None,
    output_file: Optional[str] = None,
    model_name: Optional[str] = None,
    figsize: Tuple[int, int] = (10, 8),
    colormap: str = "Blues",
    display_values: bool = False,
    title: Optional[str] = None,
    title_fontsize: int = 14,
    title_pad: Optional[float] = 50.0,
    typical_threshold: Optional[float] = None,
    threshold_color: str = "red",
    threshold_line_style: str = "--",
    label_fontsize: int = 12,
    value_fontsize: int = 10,
    legend_loc: str = "best",
    legend_fontsize: int = 10,
    bbox_to_anchor: Optional[Tuple[float, float]] = None,
    show_grid: bool = True,
    show_grid_labels: bool = False,
    grid_line_width: float = 1.0,
    grid_line_style: str = "-",
    grid_line_color: str = "gray",
    grid_line_alpha: float = 0.2,
    fill_alpha: float = 0.4,
    marker_size: int = 7,
    line_width: float = 2,
    label_padding: float = 0.25,
    clockwise: bool = True,
    start_angle: float = np.pi / 2,
    radar_range: Tuple[float, float] = (0, 1),
    dpi: int = 300,
    metrics_to_include: Optional[List[str]] = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "precision",
        "recall",
        "f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
):
    """
    Plot radar chart for a single evaluation result.

    Args:
        result_file (str, optional): Path to JSON file containing evaluation results
        result_dict (dict, optional): Dictionary containing evaluation results
        output_file (str, optional): Path to save the output plot image
        model_name (str, optional): Name of the model for display
        figsize (tuple, optional): Figure size (width, height) in inches
        colormap (str, optional): Matplotlib colormap name
        display_values (bool, optional): Whether to display metric values on chart
        title (str, optional): Custom title for the plot
        title_fontsize (int): Font size for the title
        title_pad (float): Padding for the title from the top of the plot
        typical_threshold (float, optional): Threshold value to display as a circular line
        threshold_color (str): Color for the threshold line
        threshold_line_style (str): Style of the threshold line
        label_fontsize (int): Font size for axis labels
        value_fontsize (int): Font size for displayed values
        legend_loc (str): Location for the legend box (default: 'best')
        legend_fontsize (int): Font size for the legend
        bbox_to_anchor (tuple, optional): Bounding box for the legend box (default: None)
        show_grid (bool): Whether to display the grid lines
        show_grid_labels (bool): Whether to display grid line values/labels
        grid_line_width (float): Width of the grid lines
        grid_line_style (str): Style of the grid lines
        grid_line_color (str): Color of the grid lines
        grid_line_alpha (float): Alpha (transparency) of the grid lines
        fill_alpha (float): Alpha (transparency) of the filled area
        marker_size (int): Size of the data point markers
        line_width (float): Width of the plot lines
        label_padding (float): Distance padding for axis labels from plot
        clockwise (bool): Direction of the radar chart
        start_angle (float): Start angle in radians
        radar_range (tuple): Range for the radar axes
        dpi (int): DPI for the output image
        metrics_to_include (list, optional): List of metrics to include

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_file nor result_dict is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_single_radar_chart(
        result_file=result_file,
        result_dict=result_dict,
        output_file=output_file,
        model_name=model_name,
        figsize=figsize,
        colormap=colormap,
        display_values=display_values,
        title=title,
        title_fontsize=title_fontsize,
        title_pad=title_pad,
        typical_threshold=typical_threshold,
        threshold_color=threshold_color,
        threshold_line_style=threshold_line_style,
        label_fontsize=label_fontsize,
        value_fontsize=value_fontsize,
        legend_loc=legend_loc,
        legend_fontsize=legend_fontsize,
        bbox_to_anchor=bbox_to_anchor,
        show_grid=show_grid,
        show_grid_labels=show_grid_labels,
        grid_line_width=grid_line_width,
        grid_line_style=grid_line_style,
        grid_line_color=grid_line_color,
        grid_line_alpha=grid_line_alpha,
        fill_alpha=fill_alpha,
        marker_size=marker_size,
        line_width=line_width,
        label_padding=label_padding,
        clockwise=clockwise,
        start_angle=start_angle,
        radar_range=radar_range,
        dpi=dpi,
        metrics_to_include=metrics_to_include,
    )
    return fig

plot_multiple_radar_charts

plot_multiple_radar_charts(result_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, model_names: Optional[List[str]] = None, figsize: Tuple[int, int] = (12, 10), colormap: str = 'viridis', display_values: bool = False, title: Optional[str] = None, title_fontsize: int = 14, title_pad: Optional[float] = 50.0, typical_threshold: Optional[float] = None, threshold_color: str = 'red', threshold_line_style: str = '--', label_fontsize: int = 12, value_fontsize: int = 10, legend_loc: str = 'best', bbox_to_anchor: Optional[Tuple[float, float]] = None, legend_fontsize: int = 10, show_grid: bool = True, show_grid_labels: bool = False, grid_line_width: float = 1.0, grid_line_style: str = '-', grid_line_color: str = 'gray', grid_line_alpha: float = 0.2, fill_alpha: float = 0.25, marker_size: int = 7, line_width: float = 2, label_padding: float = 0.25, clockwise: bool = True, start_angle: float = np.pi / 2, radar_range: Tuple[float, float] = (0, 1), dpi: int = 300, metrics_to_include: Optional[List[str]] = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

Plot evaluation metrics from multiple result files or dictionaries as a radar chart.

Parameters:

Name Type Description Default
result_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing evaluation results

None
folder_path Optional[str]

Path to folder containing JSON result files

None
output_file str

Path to save the output plot image

None
model_names Optional[List[str]]

Names of models to display in the legend

None
figsize Tuple[int, int]

Figure size (width, height) in inches

(12, 10)
colormap str

Matplotlib colormap name for the plot lines and markers

'viridis'
display_values bool

Whether to display metric values on the chart

False
title Optional[str]

Custom title for the plot

None
title_fontsize int

Font size for the title

14
title_pad Optional[float]

Padding for the title from the top of the plot

50.0
typical_threshold Optional[float]

Typical threshold value to display as a circular line

None
threshold_color str

Color for the threshold line

'red'
threshold_line_style str

Style of the threshold line

'--'
label_fontsize int

Font size for axis labels

12
value_fontsize int

Font size for displayed values

10
legend_loc str

Location of the legend

'best'
bbox_to_anchor Optional[Tuple[float, float]]

Bounding box for the legend

None
legend_fontsize int

Font size for the legend

10
show_grid bool

Whether to display the grid lines

True
show_grid_labels bool

Whether to display grid line values/labels

False
grid_line_width float

Width of the grid lines

1.0
grid_line_style str

Style of the grid lines

'-'
grid_line_color str

Color of the grid lines

'gray'
grid_line_alpha float

Alpha (transparency) of the grid lines

0.2
fill_alpha float

Alpha (transparency) of the filled area

0.25
marker_size int

Size of the data point markers

7
line_width float

Width of the plot lines

2
label_padding float

Distance padding for axis labels from plot

0.25
clockwise bool

Direction of the radar chart

True
start_angle float

Start angle in radians

pi / 2
radar_range Tuple[float, float]

Range for the radar axes

(0, 1)
dpi int

dpi for the output image

300
metrics_to_include Optional[List[str]]

List of metrics to include in the plot

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_sources nor folder_path is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_multiple_radar_charts(
    result_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    model_names: Optional[List[str]] = None,
    figsize: Tuple[int, int] = (12, 10),
    colormap: str = "viridis",
    display_values: bool = False,
    title: Optional[str] = None,
    title_fontsize: int = 14,
    title_pad: Optional[float] = 50.0,
    typical_threshold: Optional[float] = None,
    threshold_color: str = "red",
    threshold_line_style: str = "--",
    label_fontsize: int = 12,
    value_fontsize: int = 10,
    legend_loc: str = "best",
    bbox_to_anchor: Optional[Tuple[float, float]] = None,
    legend_fontsize: int = 10,
    show_grid: bool = True,
    show_grid_labels: bool = False,
    grid_line_width: float = 1.0,
    grid_line_style: str = "-",
    grid_line_color: str = "gray",
    grid_line_alpha: float = 0.2,
    fill_alpha: float = 0.25,
    marker_size: int = 7,
    line_width: float = 2,
    label_padding: float = 0.25,
    clockwise: bool = True,
    start_angle: float = np.pi / 2,
    radar_range: Tuple[float, float] = (0, 1),
    dpi: int = 300,
    metrics_to_include: Optional[List[str]] = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "precision",
        "recall",
        "f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
):
    """
    Plot evaluation metrics from multiple result files or dictionaries as a radar chart.

    Args:
        result_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing evaluation results
        folder_path (Optional[str], optional): Path to folder containing JSON result files
        output_file (str, optional): Path to save the output plot image
        model_names (Optional[List[str]]): Names of models to display in the legend
        figsize (Tuple[int, int]): Figure size (width, height) in inches
        colormap (str): Matplotlib colormap name for the plot lines and markers
        display_values (bool): Whether to display metric values on the chart
        title (Optional[str]): Custom title for the plot
        title_fontsize (int): Font size for the title
        title_pad (Optional[float]): Padding for the title from the top of the plot
        typical_threshold (Optional[float]): Typical threshold value to display as a circular line
        threshold_color (str): Color for the threshold line
        threshold_line_style (str): Style of the threshold line
        label_fontsize (int): Font size for axis labels
        value_fontsize (int): Font size for displayed values
        legend_loc (str): Location of the legend
        bbox_to_anchor (Optional[Tuple[float, float]]): Bounding box for the legend
        legend_fontsize (int): Font size for the legend
        show_grid (bool): Whether to display the grid lines
        show_grid_labels (bool): Whether to display grid line values/labels
        grid_line_width (float): Width of the grid lines
        grid_line_style (str): Style of the grid lines
        grid_line_color (str): Color of the grid lines
        grid_line_alpha (float): Alpha (transparency) of the grid lines
        fill_alpha (float): Alpha (transparency) of the filled area
        marker_size (int): Size of the data point markers
        line_width (float): Width of the plot lines
        label_padding (float): Distance padding for axis labels from plot
        clockwise (bool): Direction of the radar chart
        start_angle (float): Start angle in radians
        radar_range (Tuple[float, float]): Range for the radar axes
        dpi (int): dpi for the output image
        metrics_to_include (Optional[List[str]]): List of metrics to include in the plot

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_sources nor folder_path is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_multiple_radar_charts(
        result_sources=result_sources,
        folder_path=folder_path,
        output_file=output_file,
        model_names=model_names,
        figsize=figsize,
        colormap=colormap,
        display_values=display_values,
        title=title,
        title_fontsize=title_fontsize,
        title_pad=title_pad,
        typical_threshold=typical_threshold,
        threshold_color=threshold_color,
        threshold_line_style=threshold_line_style,
        label_fontsize=label_fontsize,
        value_fontsize=value_fontsize,
        legend_loc=legend_loc,
        bbox_to_anchor=bbox_to_anchor,
        legend_fontsize=legend_fontsize,
        show_grid=show_grid,
        show_grid_labels=show_grid_labels,
        grid_line_width=grid_line_width,
        grid_line_style=grid_line_style,
        grid_line_color=grid_line_color,
        grid_line_alpha=grid_line_alpha,
        fill_alpha=fill_alpha,
        marker_size=marker_size,
        line_width=line_width,
        label_padding=label_padding,
        clockwise=clockwise,
        start_angle=start_angle,
        radar_range=radar_range,
        dpi=dpi,
        metrics_to_include=metrics_to_include,
    )
    return fig

plot_single_performance_heatmap

plot_single_performance_heatmap(result_file: Optional[str] = None, result_dict: Optional[dict] = None, output_file: Optional[str] = None, model_name: Optional[str] = None, figsize: Tuple[int, int] = (12, 12), colormap: str = 'YlGnBu', bin_count: int = 10, score_range: Tuple[float, float] = (0, 1), use_percentage: bool = True, show_averages: bool = False, show_group_labels: bool = False, show_annotations: bool = False, annotation_format: Optional[str] = None, title: Optional[str] = None, title_fontsize: int = 14, title_pad: Optional[float] = None, labels: List[str] = ['Metrics', 'Scores'], label_fontsize: int = 12, dpi: int = 300, group_metrics: bool = False, metric_groups: Optional[List[Dict]] = None, group_colors: Optional[List[str]] = None, metrics_to_include: Optional[List[str]] = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'], group_label_right_margin: int = 1, average_value_left_margin: int = 1, plot_padding: float = 0.1)

Create a heatmap showing the distribution of scores across metrics for a single model.

Parameters:

Name Type Description Default
result_file str

Path to JSON file containing evaluation results for the model

None
result_dict dict

Dictionary containing evaluation results for the model. Either result_file or result_dict must be provided.

None
output_file str

Path to save the output visualization

None
model_name str

Name to display for the model in the plot

None
figsize tuple

Figure size as (width, height) in inches (default: (12, 12))

(12, 12)
colormap str

Matplotlib colormap name for the heatmap (default: 'YlGnBu')

'YlGnBu'
bin_count int

Number of bins to divide the score range into (default: 10)

10
score_range tuple

Min and max values for score bins (default: (0, 1))

(0, 1)
use_percentage bool

Whether to show percentages (True) or counts (False)

True
show_averages bool

Whether to show average scores per metric

False
show_group_labels bool

Whether to show metric group labels

False
show_annotations bool

Whether to show value annotations in cells

False
annotation_format str

Format string for annotations (e.g., '.1f' or 'd')

None
title str

Custom title for the plot

None
title_fontsize int

Font size for the title text (default: 14)

14
title_pad float

Padding for the title from the top of the plot

None
labels list

Labels for the x and y axes (default: ['Metrics', 'Scores'])

['Metrics', 'Scores']
label_fontsize int

Font size for the axis labels (default: 12)

12
dpi int

Resolution for saved image (default: 300)

300
group_metrics bool

Whether to visually group related metrics together (default: False)

False
metric_groups list

Custom metric groups definition for grouping metrics

None
group_colors list

Colors for metric groups (default: ['#f8f9fa', '#e9ecef', '#f8f9fa', '#e9ecef'])

None
metrics_to_include list

Specific metrics to include in the heatmap (default: all available)

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']
group_label_right_margin int

Right margin for group labels (default: 1)

1
average_value_left_margin int

Left margin for average values (default: 1)

1
plot_padding float

Padding between heatmap and axes (default: 0.1)

0.1

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_file nor result_dict is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_single_performance_heatmap(
    result_file: Optional[str] = None,
    result_dict: Optional[dict] = None,
    output_file: Optional[str] = None,
    model_name: Optional[str] = None,
    figsize: Tuple[int, int] = (12, 12),
    colormap: str = "YlGnBu",
    bin_count: int = 10,
    score_range: Tuple[float, float] = (0, 1),
    use_percentage: bool = True,
    show_averages: bool = False,
    show_group_labels: bool = False,
    show_annotations: bool = False,
    annotation_format: Optional[str] = None,
    title: Optional[str] = None,
    title_fontsize: int = 14,
    title_pad: Optional[float] = None,
    labels: List[str] = ["Metrics", "Scores"],
    label_fontsize: int = 12,
    dpi: int = 300,
    group_metrics: bool = False,
    metric_groups: Optional[List[Dict]] = None,
    group_colors: Optional[List[str]] = None,
    metrics_to_include: Optional[List[str]] = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "precision",
        "recall",
        "f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
    group_label_right_margin: int = 1,
    average_value_left_margin: int = 1,
    plot_padding: float = 0.1,
):
    """
    Create a heatmap showing the distribution of scores across metrics for a single model.

    Args:
        result_file (str, optional): Path to JSON file containing evaluation results for the model
        result_dict (dict, optional): Dictionary containing evaluation results for the model. Either result_file or result_dict must be provided.
        output_file (str, optional): Path to save the output visualization
        model_name (str, optional): Name to display for the model in the plot
        figsize (tuple, optional): Figure size as (width, height) in inches (default: (12, 12))
        colormap (str, optional): Matplotlib colormap name for the heatmap (default: 'YlGnBu')
        bin_count (int, optional): Number of bins to divide the score range into (default: 10)
        score_range (tuple, optional): Min and max values for score bins (default: (0, 1))
        use_percentage (bool, optional): Whether to show percentages (True) or counts (False)
        show_averages (bool, optional): Whether to show average scores per metric
        show_group_labels (bool, optional): Whether to show metric group labels
        show_annotations (bool, optional): Whether to show value annotations in cells
        annotation_format (str, optional): Format string for annotations (e.g., '.1f' or 'd')
        title (str, optional): Custom title for the plot
        title_fontsize (int, optional): Font size for the title text (default: 14)
        title_pad (float, optional): Padding for the title from the top of the plot
        labels (list, optional): Labels for the x and y axes (default: ['Metrics', 'Scores'])
        label_fontsize (int, optional): Font size for the axis labels (default: 12)
        dpi (int, optional): Resolution for saved image (default: 300)
        group_metrics (bool, optional): Whether to visually group related metrics together (default: False)
        metric_groups (list, optional): Custom metric groups definition for grouping metrics
        group_colors (list, optional): Colors for metric groups (default: ['#f8f9fa', '#e9ecef', '#f8f9fa', '#e9ecef'])
        metrics_to_include (list, optional): Specific metrics to include in the heatmap (default: all available)
        group_label_right_margin (int, optional): Right margin for group labels (default: 1)
        average_value_left_margin (int, optional): Left margin for average values (default: 1)
        plot_padding (float, optional): Padding between heatmap and axes (default: 0.1)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_file nor result_dict is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_single_performance_heatmap(
        result_file=result_file,
        result_dict=result_dict,
        output_file=output_file,
        model_name=model_name,
        figsize=figsize,
        colormap=colormap,
        bin_count=bin_count,
        score_range=score_range,
        use_percentage=use_percentage,
        show_averages=show_averages,
        show_group_labels=show_group_labels,
        show_annotations=show_annotations,
        annotation_format=annotation_format,
        title=title,
        title_fontsize=title_fontsize,
        title_pad=title_pad,
        labels=labels,
        label_fontsize=label_fontsize,
        dpi=dpi,
        group_metrics=group_metrics,
        metric_groups=metric_groups,
        group_colors=group_colors,
        metrics_to_include=metrics_to_include,
        group_label_right_margin=group_label_right_margin,
        average_value_left_margin=average_value_left_margin,
        plot_padding=plot_padding,
    )
    return fig

plot_multiple_performance_heatmaps

plot_multiple_performance_heatmaps(result_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, model_names: Optional[List[str]] = None, figsize: Tuple[int, int] = (14, 12), colormap: str = 'YlGnBu', bin_count: int = 10, score_range: Tuple[float, float] = (0, 1), use_percentage: bool = True, show_averages: bool = False, show_group_labels: bool = False, show_annotations: bool = False, annotation_format: Optional[str] = None, title: Optional[str] = None, title_fontsize: int = 14, labels: List[str] = ['Metrics', 'Scores'], label_fontsize: int = 12, dpi: int = 300, group_metrics: bool = True, metric_groups: Optional[List[Dict]] = None, group_colors: Optional[List[str]] = None, metrics_to_include: Optional[List[str]] = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'], sort_models_by: str = 'overall_accuracy', combine_models: bool = False, group_label_right_margin: int = 1, average_value_left_margin: int = 1, plot_padding: float = 0.1)

Create a heatmap showing the distribution of scores across metrics for multiple models.

Parameters:

Name Type Description Default
result_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing evaluation results

None
folder_path Optional[str]

Path to folder containing JSON result files. Either result_sources or folder_path must be provided.

None
output_file str

Path to save the output visualization

None
model_names Optional[List[str]]

Names to display for models in the plots

None
figsize Tuple[int, int]

Figure size as (width, height) in inches

(14, 12)
colormap str

Matplotlib colormap name for the heatmap

'YlGnBu'
bin_count int

Number of bins to divide the score range into

10
score_range Tuple[float, float]

Min and max values for score bins (default: (0, 1))

(0, 1)
use_percentage bool

Whether to show percentages (True) or counts (False)

True
show_averages bool

Whether to show average scores per metric group and model

False
show_group_labels bool

Whether to show metric group labels

False
show_annotations bool

Whether to show value annotations in cells

False
annotation_format Optional[str]

Format string for annotations (e.g., '.1f' or 'd')

None
title Optional[str]

Custom title for the plot

None
title_fontsize int

Font size for the title

14
labels List[str]

Labels for the x and y axes (default: ['Metrics', 'Scores'])

['Metrics', 'Scores']
label_fontsize int

Font size for the axis labels

12
dpi int

Resolution for saved image

300
group_metrics bool

Whether to visually group related metrics

True
metric_groups Optional[List[Dict]]

Custom metric groups definition

None
group_colors Optional[List[str]]

Colors for metric groups

None
metrics_to_include Optional[List[str]]

Specific metrics to include (if None, includes all available)

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']
sort_models_by str

Metric to sort models by when displaying multiple models (default: 'overall_accuracy')

'overall_accuracy'
combine_models bool

Whether to combine all models into a single distribution plot (default: False)

False
group_label_right_margin int

Right margin for group labels

1
average_value_left_margin int

Left margin for average values

1
plot_padding float

Padding between heatmap and axes labels and title

0.1

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_sources nor folder_path is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_multiple_performance_heatmaps(
    result_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    model_names: Optional[List[str]] = None,
    figsize: Tuple[int, int] = (14, 12),
    colormap: str = "YlGnBu",
    bin_count: int = 10,
    score_range: Tuple[float, float] = (0, 1),
    use_percentage: bool = True,
    show_averages: bool = False,
    show_group_labels: bool = False,
    show_annotations: bool = False,
    annotation_format: Optional[str] = None,
    title: Optional[str] = None,
    title_fontsize: int = 14,
    labels: List[str] = ["Metrics", "Scores"],
    label_fontsize: int = 12,
    dpi: int = 300,
    group_metrics: bool = True,
    metric_groups: Optional[List[Dict]] = None,
    group_colors: Optional[List[str]] = None,
    metrics_to_include: Optional[List[str]] = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "precision",
        "recall",
        "f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
    sort_models_by: str = "overall_accuracy",
    combine_models: bool = False,
    group_label_right_margin: int = 1,
    average_value_left_margin: int = 1,
    plot_padding: float = 0.1,
):
    """
    Create a heatmap showing the distribution of scores across metrics for multiple models.

    Args:
        result_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing evaluation results
        folder_path (Optional[str], optional): Path to folder containing JSON result files. Either result_sources or folder_path must be provided.
        output_file (str, optional): Path to save the output visualization
        model_names (Optional[List[str]]): Names to display for models in the plots
        figsize (Tuple[int, int]): Figure size as (width, height) in inches
        colormap (str): Matplotlib colormap name for the heatmap
        bin_count (int): Number of bins to divide the score range into
        score_range (Tuple[float, float]): Min and max values for score bins (default: (0, 1))
        use_percentage (bool): Whether to show percentages (True) or counts (False)
        show_averages (bool): Whether to show average scores per metric group and model
        show_group_labels (bool): Whether to show metric group labels
        show_annotations (bool): Whether to show value annotations in cells
        annotation_format (Optional[str]): Format string for annotations (e.g., '.1f' or 'd')
        title (Optional[str]): Custom title for the plot
        title_fontsize (int): Font size for the title
        labels (List[str]): Labels for the x and y axes (default: ['Metrics', 'Scores'])
        label_fontsize (int): Font size for the axis labels
        dpi (int): Resolution for saved image
        group_metrics (bool): Whether to visually group related metrics
        metric_groups (Optional[List[Dict]]): Custom metric groups definition
        group_colors (Optional[List[str]]): Colors for metric groups
        metrics_to_include (Optional[List[str]]): Specific metrics to include (if None, includes all available)
        sort_models_by (str): Metric to sort models by when displaying multiple models (default: 'overall_accuracy')
        combine_models (bool): Whether to combine all models into a single distribution plot (default: False)
        group_label_right_margin (int): Right margin for group labels
        average_value_left_margin (int): Left margin for average values
        plot_padding (float): Padding between heatmap and axes labels and title

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_sources nor folder_path is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_multiple_performance_heatmaps(
        result_sources=result_sources,
        folder_path=folder_path,
        output_file=output_file,
        model_names=model_names,
        figsize=figsize,
        colormap=colormap,
        bin_count=bin_count,
        score_range=score_range,
        use_percentage=use_percentage,
        show_averages=show_averages,
        show_group_labels=show_group_labels,
        show_annotations=show_annotations,
        annotation_format=annotation_format,
        title=title,
        title_fontsize=title_fontsize,
        labels=labels,
        label_fontsize=label_fontsize,
        dpi=dpi,
        group_metrics=group_metrics,
        metric_groups=metric_groups,
        group_colors=group_colors,
        metrics_to_include=metrics_to_include,
        sort_models_by=sort_models_by,
        combine_models=combine_models,
        group_label_right_margin=group_label_right_margin,
        average_value_left_margin=average_value_left_margin,
        plot_padding=plot_padding,
    )
    return fig

plot_multiple_confusion_matrices_combined

plot_multiple_confusion_matrices_combined(result_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, model_names: Optional[List[str]] = None, figsize: Tuple[int, int] = (14, 10), colormap: str = 'YlOrRd', show_annotations: bool = True, annotation_format: Optional[str] = None, annotation_fontsize: int = 10, title: Optional[str] = None, title_fontsize: int = 14, title_pad: Optional[float] = 20.0, labels: List[str] = ['Models', 'Metrics'], label_fontsize: int = 12, tick_label_fontsize: int = 10, dpi: int = 300, metrics_to_include: Optional[List[str]] = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'], sort_models_by: str = 'average', value_range: Tuple[float, float] = (0, 1), show_colorbar: bool = True, colorbar_label: str = 'Score', colorbar_fontsize: int = 10, plot_padding: float = 0.1)

Create a confusion matrix-style heatmap showing all models vs all performance metrics in a single visualization.

Parameters:

Name Type Description Default
result_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing evaluation results

None
folder_path Optional[str]

Path to folder containing JSON result files. Either result_sources or folder_path must be provided.

None
output_file str

Path to save the output visualization

None
model_names Optional[List[str]]

Names to display for models in the plot

None
figsize Tuple[int, int]

Figure size as (width, height) in inches

(14, 10)
colormap str

Matplotlib colormap name for the heatmap

'YlOrRd'
show_annotations bool

Whether to show value annotations in cells

True
annotation_format Optional[str]

Format string for annotations (e.g., '.2f' or '.1f')

None
annotation_fontsize int

Font size for the annotation values inside cells

10
title Optional[str]

Custom title for the plot

None
title_fontsize int

Font size for the title

14
title_pad Optional[float]

Padding for the title from the top of the plot

20.0
labels List[str]

Labels for the x and y axes (default: ['Models', 'Metrics'])

['Models', 'Metrics']
label_fontsize int

Font size for the axis labels

12
tick_label_fontsize int

Font size for x and y tick labels

10
dpi int

Resolution for saved image

300
metrics_to_include Optional[List[str]]

Specific metrics to include (default: all 9 standard metrics)

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']
sort_models_by str

Metric to sort models by, or "average" for average of all metrics (default: 'average')

'average'
value_range Tuple[float, float]

Min and max values for color mapping (default: (0, 1))

(0, 1)
show_colorbar bool

Whether to show the colorbar legend

True
colorbar_label str

Label for the colorbar

'Score'
colorbar_fontsize int

Font size for colorbar labels

10
plot_padding float

Padding between heatmap and axes labels and title

0.1

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Source code in src/comproscanner/eval_visualizer.py
def plot_multiple_confusion_matrices_combined(
    result_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    model_names: Optional[List[str]] = None,
    figsize: Tuple[int, int] = (14, 10),
    colormap: str = "YlOrRd",
    show_annotations: bool = True,
    annotation_format: Optional[str] = None,
    annotation_fontsize: int = 10,
    title: Optional[str] = None,
    title_fontsize: int = 14,
    title_pad: Optional[float] = 20.0,
    labels: List[str] = ["Models", "Metrics"],
    label_fontsize: int = 12,
    tick_label_fontsize: int = 10,
    dpi: int = 300,
    metrics_to_include: Optional[List[str]] = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "precision",
        "recall",
        "f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
    sort_models_by: str = "average",
    value_range: Tuple[float, float] = (0, 1),
    show_colorbar: bool = True,
    colorbar_label: str = "Score",
    colorbar_fontsize: int = 10,
    plot_padding: float = 0.1,
):
    """
    Create a confusion matrix-style heatmap showing all models vs all performance metrics in a single visualization.

    Args:
        result_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing evaluation results
        folder_path (Optional[str], optional): Path to folder containing JSON result files. Either result_sources or folder_path must be provided.
        output_file (str, optional): Path to save the output visualization
        model_names (Optional[List[str]]): Names to display for models in the plot
        figsize (Tuple[int, int]): Figure size as (width, height) in inches
        colormap (str): Matplotlib colormap name for the heatmap
        show_annotations (bool): Whether to show value annotations in cells
        annotation_format (Optional[str]): Format string for annotations (e.g., '.2f' or '.1f')
        annotation_fontsize (int): Font size for the annotation values inside cells
        title (Optional[str]): Custom title for the plot
        title_fontsize (int): Font size for the title
        title_pad (Optional[float]): Padding for the title from the top of the plot
        labels (List[str]): Labels for the x and y axes (default: ['Models', 'Metrics'])
        label_fontsize (int): Font size for the axis labels
        tick_label_fontsize (int): Font size for x and y tick labels
        dpi (int): Resolution for saved image
        metrics_to_include (Optional[List[str]]): Specific metrics to include (default: all 9 standard metrics)
        sort_models_by (str): Metric to sort models by, or "average" for average of all metrics (default: 'average')
        value_range (Tuple[float, float]): Min and max values for color mapping (default: (0, 1))
        show_colorbar (bool): Whether to show the colorbar legend
        colorbar_label (str): Label for the colorbar
        colorbar_fontsize (int): Font size for colorbar labels
        plot_padding (float): Padding between heatmap and axes labels and title

    Returns:
        matplotlib.figure.Figure: The generated figure object
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_multiple_confusion_matrices_combined(
        result_sources=result_sources,
        folder_path=folder_path,
        output_file=output_file,
        model_names=model_names,
        figsize=figsize,
        colormap=colormap,
        show_annotations=show_annotations,
        annotation_format=annotation_format,
        annotation_fontsize=annotation_fontsize,
        title=title,
        title_fontsize=title_fontsize,
        title_pad=title_pad,
        labels=labels,
        label_fontsize=label_fontsize,
        tick_label_fontsize=tick_label_fontsize,
        dpi=dpi,
        metrics_to_include=metrics_to_include,
        sort_models_by=sort_models_by,
        value_range=value_range,
        show_colorbar=show_colorbar,
        colorbar_label=colorbar_label,
        colorbar_fontsize=colorbar_fontsize,
        plot_padding=plot_padding,
    )
    return fig

plot_single_histogram_chart

plot_single_histogram_chart(result_file: Optional[str] = None, result_dict: Optional[dict] = None, metric_name: str = 'overall_accuracy', output_file: Optional[dict] = None, model_name: Optional[dict] = None, figsize: Tuple[int, int] = (8, 6), bins: int = 10, color: str = 'skyblue', color_gradient: bool = False, gradient_colors: Optional[List[str]] = None, show_kde: bool = False, show_mean: bool = False, mean_color: str = 'green', mean_line_style: str = '-', show_median: bool = False, median_color: str = 'black', median_line_style: str = '-', show_threshold: bool = False, threshold_value: float = 0.8, threshold_color: str = 'red', threshold_line_style: str = '--', title: Optional[str] = None, title_fontsize=14, xlabel: Optional[str] = None, ylabel: str = 'Count', xlabel_fontsize: int = 12, ylabel_fontsize: int = 12, legend_loc: Optional[str] = 'best', bbox_to_anchor: Optional[str] = None, dpi: int = 300)

Create a histogram for a single metric from evaluation results.

Parameters:

Name Type Description Default
result_file str

Path to JSON file containing evaluation results

None
result_dict dict

Dictionary containing evaluation results. Either result_file or result_dict must be provided.

None
metric_name str

Name of the metric to plot (default: "overall_accuracy")

'overall_accuracy'
output_file str

Path to save the output plot image

None
model_name str

Name of the model for display in the plot title

None
figsize tuple

Figure size as (width, height) in inches (default: (8, 6))

(8, 6)
bins int or sequence

Number of bins or bin edges for histogram (default: 10)

10
color str

Color for the histogram bars (default: 'skyblue')

'skyblue'
color_gradient bool

Whether to use color gradient for histogram bars (default: False)

False
gradient_colors list

List of colors for gradient (default: ['#D4E6F1', 'color'])

None
show_kde bool

Whether to show a KDE curve over the histogram (default: False)

False
show_mean bool

Whether to show a vertical line at the mean value (default: False)

False
show_median bool

Whether to show a vertical line at the median value (default: False)

False
show_threshold bool

Whether to show a threshold line (default: False)

False
threshold_value float

Value for the threshold line (default: 0.8)

0.8
threshold_color str

Color for the threshold line (default: 'red')

'red'
threshold_line_style str

Line style for the threshold line (default: '--')

'--'
title str

Custom title for the plot (default: None)

None
title_fontsize int

Font size for the title (default: 14)

14
xlabel str

Custom label for x-axis

None
ylabel str

Label for y-axis

'Count'
xlabel_fontsize int

Font size for x-axis label

12
ylabel_fontsize int

Font size for y-axis label

12
legend_loc str

Location for the legend

'best'
bbox_to_anchor tuple

Bounding box for the legend

None
dpi int

DPI for the output image

300

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_file nor result_dict is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_single_histogram_chart(
    result_file: Optional[str] = None,
    result_dict: Optional[dict] = None,
    metric_name: str = "overall_accuracy",
    output_file: Optional[dict] = None,
    model_name: Optional[dict] = None,
    figsize: Tuple[int, int] = (8, 6),
    bins: int = 10,
    color: str = "skyblue",
    color_gradient: bool = False,
    gradient_colors: Optional[List[str]] = None,
    show_kde: bool = False,
    show_mean: bool = False,
    mean_color: str = "green",
    mean_line_style: str = "-",
    show_median: bool = False,
    median_color: str = "black",
    median_line_style: str = "-",
    show_threshold: bool = False,
    threshold_value: float = 0.8,
    threshold_color: str = "red",
    threshold_line_style: str = "--",
    title: Optional[str] = None,
    title_fontsize=14,
    xlabel: Optional[str] = None,
    ylabel: str = "Count",
    xlabel_fontsize: int = 12,
    ylabel_fontsize: int = 12,
    legend_loc: Optional[str] = "best",
    bbox_to_anchor: Optional[str] = None,
    dpi: int = 300,
):
    """
    Create a histogram for a single metric from evaluation results.

    Args:
        result_file (str, optional): Path to JSON file containing evaluation results
        result_dict (dict, optional): Dictionary containing evaluation results. Either result_file or result_dict must be provided.
        metric_name (str): Name of the metric to plot (default: "overall_accuracy")
        output_file (str, optional): Path to save the output plot image
        model_name (str, optional): Name of the model for display in the plot title
        figsize (tuple): Figure size as (width, height) in inches (default: (8, 6))
        bins (int or sequence): Number of bins or bin edges for histogram (default: 10)
        color (str): Color for the histogram bars (default: 'skyblue')
        color_gradient (bool): Whether to use color gradient for histogram bars (default: False)
        gradient_colors (list, optional): List of colors for gradient (default: ['#D4E6F1', 'color'])
        show_kde (bool): Whether to show a KDE curve over the histogram (default: False)
        show_mean (bool): Whether to show a vertical line at the mean value (default: False)
        show_median (bool): Whether to show a vertical line at the median value (default: False)
        show_threshold (bool): Whether to show a threshold line (default: False)
        threshold_value (float): Value for the threshold line (default: 0.8)
        threshold_color (str): Color for the threshold line (default: 'red')
        threshold_line_style (str): Line style for the threshold line (default: '--')
        title (str, optional): Custom title for the plot (default: None)
        title_fontsize (int): Font size for the title (default: 14)
        xlabel (str, optional): Custom label for x-axis
        ylabel (str, optional): Label for y-axis
        xlabel_fontsize (int, optional): Font size for x-axis label
        ylabel_fontsize (int, optional): Font size for y-axis label
        legend_loc (str, optional): Location for the legend
        bbox_to_anchor (tuple, optional): Bounding box for the legend
        dpi (int, optional): DPI for the output image

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_file nor result_dict is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_single_histogram_chart(
        result_file=result_file,
        result_dict=result_dict,
        metric_name=metric_name,
        output_file=output_file,
        model_name=model_name,
        figsize=figsize,
        bins=bins,
        color=color,
        color_gradient=color_gradient,
        gradient_colors=gradient_colors,
        show_kde=show_kde,
        show_mean=show_mean,
        mean_color=mean_color,
        mean_line_style=mean_line_style,
        show_median=show_median,
        median_color=median_color,
        median_line_style=median_line_style,
        show_threshold=show_threshold,
        threshold_value=threshold_value,
        threshold_color=threshold_color,
        threshold_line_style=threshold_line_style,
        title=title,
        title_fontsize=title_fontsize,
        xlabel=xlabel,
        ylabel=ylabel,
        xlabel_fontsize=xlabel_fontsize,
        ylabel_fontsize=ylabel_fontsize,
        legend_loc=legend_loc,
        bbox_to_anchor=bbox_to_anchor,
        dpi=dpi,
    )
    return fig

plot_multiple_histogram_charts

plot_multiple_histogram_charts(result_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, model_names: Optional[List[str]] = None, metric_name: str = 'overall_accuracy', figsize: Tuple[int, int] = (14, 12), bins: int = 10, colormap: str = 'tab10', show_kde: bool = False, kde_alpha: float = 0.7, show_mean: bool = False, mean_color: str = 'green', mean_line_style: str = '-', show_median: bool = False, median_color: str = 'black', median_line_style: str = '-', show_threshold: bool = False, threshold_value: float = 0.8, threshold_color: str = 'red', threshold_line_style: str = '--', show_grid: bool = True, title: Optional[str] = None, title_fontsize: int = 14, xlabel: Optional[str] = None, ylabel: str = 'Count', xlabel_fontsize: int = 12, ylabel_fontsize: int = 12, legend_loc: Optional[str] = 'best', legend_fontsize: int = 10, bbox_to_anchor: Optional[str] = None, is_normalized: bool = True, shared_bins: bool = True, dpi: int = 300)

Create histograms for a single metric from evaluation results for multiple models.

Parameters:

Name Type Description Default
=result_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing evaluation results

required
folder_path Optional[str]

Path to folder containing JSON result files. Either result_sources or folder_path must be provided.

None
output_file str

Path to save the output plot image

None
model_names Optional[List[str]]

Names of the models for display in the plot titles

None
metric_name str

Name of the metric to plot (default: "overall_accuracy")

'overall_accuracy'
figsize tuple

Figure size as (width, height) in inches (default: (14, 12))

(14, 12)
bins int

Number of bins or bin edges for histogram (default: 10)

10
colormap str

Matplotlib colormap name for the histogram colors (default: 'tab10')

'tab10'
show_kde bool

Whether to show a KDE curve over the histogram (default: False)

False
kde_alpha float

Alpha value for the KDE curve (default: 0.7)

0.7
show_mean bool

Whether to show a vertical line at the mean value (default: False)

False
mean_color str

Color for the mean line (default: 'green')

'green'
mean_line_style str

Line style for the mean line (default: '-')

'-'
show_median bool

Whether to show a vertical line at the median value (default: False)

False
median_color str

Color for the median line (default: 'black')

'black'
median_line_style str

Line style for the median line (default: '-')

'-'
show_threshold bool

Whether to show a threshold line (default: False)

False
threshold_value float

Value for the threshold line (default: 0.8)

0.8
threshold_color str

Color for the threshold line (default: 'red')

'red'
threshold_line_style str

Line style for the threshold line (default: '--')

'--'
show_grid bool

Whether to show grid lines on the plot (default: True)

True
title str

Custom title for the plot (default: None)

None
title_fontsize int

Font size for the title (default: 14)

14
xlabel str

Custom label for x-axis

None
ylabel str

Label for y-axis (default: 'Count')

'Count'
xlabel_fontsize int

Font size for x-axis label (default: 12)

12
ylabel_fontsize int

Font size for y-axis label (default: 12)

12
legend_loc str

Location for the legend (default: 'best')

'best'
legend_fontsize int

Font size for the legend (default: 10)

10
bbox_to_anchor tuple

Bounding box for the legend

None
is_normalized bool

Whether to normalize histograms to show percentages (default: True)

True
shared_bins bool

Whether to use shared bins across all histograms (default: True)

True
dpi int

DPI for the output image (default: 300)

300

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_sources nor folder_path is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_multiple_histogram_charts(
    result_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    model_names: Optional[List[str]] = None,
    metric_name: str = "overall_accuracy",
    figsize: Tuple[int, int] = (14, 12),
    bins: int = 10,
    colormap: str = "tab10",
    show_kde: bool = False,
    kde_alpha: float = 0.7,
    show_mean: bool = False,
    mean_color: str = "green",
    mean_line_style: str = "-",
    show_median: bool = False,
    median_color: str = "black",
    median_line_style: str = "-",
    show_threshold: bool = False,
    threshold_value: float = 0.8,
    threshold_color: str = "red",
    threshold_line_style: str = "--",
    show_grid: bool = True,
    title: Optional[str] = None,
    title_fontsize: int = 14,
    xlabel: Optional[str] = None,
    ylabel: str = "Count",
    xlabel_fontsize: int = 12,
    ylabel_fontsize: int = 12,
    legend_loc: Optional[str] = "best",
    legend_fontsize: int = 10,
    bbox_to_anchor: Optional[str] = None,
    is_normalized: bool = True,
    shared_bins: bool = True,
    dpi: int = 300,
):
    """
    Create histograms for a single metric from evaluation results for multiple models.

    Args:
        =result_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing evaluation results
        folder_path (Optional[str], optional): Path to folder containing JSON result files. Either result_sources or folder_path must be provided.
        output_file (str, optional): Path to save the output plot image
        model_names (Optional[List[str]]): Names of the models for display in the plot titles
        metric_name (str, optional): Name of the metric to plot (default: "overall_accuracy")
        figsize (tuple, optional): Figure size as (width, height) in inches (default: (14, 12))
        bins (int, optional): Number of bins or bin edges for histogram (default: 10)
        colormap (str, optional): Matplotlib colormap name for the histogram colors (default: 'tab10')
        show_kde (bool, optional): Whether to show a KDE curve over the histogram (default: False)
        kde_alpha (float, optional): Alpha value for the KDE curve (default: 0.7)
        show_mean (bool, optional): Whether to show a vertical line at the mean value (default: False)
        mean_color (str, optional): Color for the mean line (default: 'green')
        mean_line_style (str, optional): Line style for the mean line (default: '-')
        show_median (bool, optional): Whether to show a vertical line at the median value (default: False)
        median_color (str, optional): Color for the median line (default: 'black')
        median_line_style (str, optional): Line style for the median line (default: '-')
        show_threshold (bool, optional): Whether to show a threshold line (default: False)
        threshold_value (float, optional): Value for the threshold line (default: 0.8)
        threshold_color (str, optional): Color for the threshold line (default: 'red')
        threshold_line_style (str, optional): Line style for the threshold line (default: '--')
        show_grid (bool, optional): Whether to show grid lines on the plot (default: True)
        title (str, optional): Custom title for the plot (default: None)
        title_fontsize (int, optional): Font size for the title (default: 14)
        xlabel (str, optional): Custom label for x-axis
        ylabel (str, optional): Label for y-axis (default: 'Count')
        xlabel_fontsize (int, optional): Font size for x-axis label (default: 12)
        ylabel_fontsize (int, optional): Font size for y-axis label (default: 12)
        legend_loc (str, optional): Location for the legend (default: 'best')
        legend_fontsize (int, optional): Font size for the legend (default: 10)
        bbox_to_anchor (tuple, optional): Bounding box for the legend
        is_normalized (bool, optional): Whether to normalize histograms to show percentages (default: True)
        shared_bins (bool, optional): Whether to use shared bins across all histograms (default: True)
        dpi (int, optional): DPI for the output image (default: 300)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_sources nor folder_path is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_multiple_histogram_charts(
        result_sources=result_sources,
        folder_path=folder_path,
        output_file=output_file,
        model_names=model_names,
        metric_name=metric_name,
        figsize=figsize,
        bins=bins,
        colormap=colormap,
        show_kde=show_kde,
        kde_alpha=kde_alpha,
        show_mean=show_mean,
        mean_color=mean_color,
        mean_line_style=mean_line_style,
        show_median=show_median,
        median_color=median_color,
        median_line_style=median_line_style,
        show_threshold=show_threshold,
        threshold_value=threshold_value,
        threshold_color=threshold_color,
        threshold_line_style=threshold_line_style,
        show_grid=show_grid,
        title=title,
        title_fontsize=title_fontsize,
        xlabel=xlabel,
        ylabel=ylabel,
        xlabel_fontsize=xlabel_fontsize,
        ylabel_fontsize=ylabel_fontsize,
        legend_loc=legend_loc,
        legend_fontsize=legend_fontsize,
        bbox_to_anchor=bbox_to_anchor,
        is_normalized=is_normalized,
        shared_bins=shared_bins,
        dpi=dpi,
    )
    return fig

plot_single_violin_chart

plot_single_violin_chart(result_file: Optional[str] = None, result_dict: Optional[dict] = None, output_file: Optional[str] = None, model_name: Optional[str] = None, figsize: Tuple[int, int] = (14, 10), colormap: str = 'Blues', title: Optional[str] = None, title_fontsize: int = 14, title_pad: Optional[float] = 10.0, show_box: bool = False, show_mean: bool = True, mean_marker: str = 'o', mean_color: str = 'red', show_median: bool = False, median_color: str = 'green', median_line_style: str = '-', show_grid: bool = True, show_threshold: bool = False, threshold_value: float = 0.8, threshold_color: str = 'red', threshold_line_style: str = '--', violin_alpha: float = 0.7, violin_width: float = 0.8, x_label: str = 'Metrics', y_label: str = 'Score', x_label_fontsize: int = 12, y_label_fontsize: int = 12, y_axis_range: Tuple[float, float] = (0, 1), label_rotation: int = 45, inner: str = 'box', dpi: int = 300, metrics_to_include: Optional[List[str]] = ['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score'])

Create a violin plot for all metrics from a single model's evaluation results.

Parameters:

Name Type Description Default
result_file str

Path to JSON file containing evaluation results

None
result_dict dict

Dictionary containing evaluation results. Either result_file or result_dict must be provided.

None
output_file str

Path to save the output visualization

None
model_name str

Name to display for the model in the plot

None
figsize tuple

Figure size as (width, height) in inches (default: (14, 10))

(14, 10)
colormap str

Matplotlib colormap name for the violins (default: 'Blues')

'Blues'
title str

Custom title for the plot (default: None)

None
title_fontsize int

Font size for the title text (default: 14)

14
title_pad float

Padding for the title from the top of the plot (default: 10.0)

10.0
show_box bool

Whether to show a box plot inside the violin (default: False)

False
show_mean bool

Whether to show the mean marker (default: True)

True
mean_marker str

Marker style for the mean (default: 'o')

'o'
mean_color str

Color for the mean marker (default: 'red')

'red'
show_median bool

Whether to show the median line (default: False)

False
median_color str

Color for the median line (default: 'green')

'green'
median_line_style str

Line style for the median (default: '-')

'-'
show_grid bool

Whether to display the grid lines (default: True)

True
show_threshold bool

Whether to show a threshold line (default: False)

False
threshold_value float

Value for the threshold line (default: 0.8)

0.8
threshold_color str

Color for the threshold line (default: 'red')

'red'
threshold_line_style str

Line style for the threshold line (default: '--')

'--'
violin_alpha float

Alpha (transparency) of the violin plots (default: 0.7)

0.7
violin_width float

Width of the violin plots (default: 0.8)

0.8
x_label str

Label for the x-axis (default: 'Metrics')

'Metrics'
y_label str

Label for the y-axis (default: 'Score')

'Score'
x_label_fontsize int

Font size for x-axis label (default: 12)

12
y_label_fontsize int

Font size for y-axis label (default: 12)

12
y_axis_range tuple

Range for the y-axis (default: (0, 1))

(0, 1)
label_rotation int

Rotation angle for x-axis labels (default: 45)

45
inner str

The representation of the data points inside the violin ('box', 'stick', 'point', or None) (default: 'box')

'box'
dpi int

Resolution for saved image (default: 300)

300
metrics_to_include list

Specific metrics to include in the plot (default: None - all available)

['overall_accuracy', 'overall_composition_accuracy', 'overall_synthesis_accuracy', 'precision', 'recall', 'f1_score', 'normalized_precision', 'normalized_recall', 'normalized_f1_score']

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_file nor result_dict is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_single_violin_chart(
    result_file: Optional[str] = None,
    result_dict: Optional[dict] = None,
    output_file: Optional[str] = None,
    model_name: Optional[str] = None,
    figsize: Tuple[int, int] = (14, 10),
    colormap: str = "Blues",
    title: Optional[str] = None,
    title_fontsize: int = 14,
    title_pad: Optional[float] = 10.0,
    show_box: bool = False,
    show_mean: bool = True,
    mean_marker: str = "o",
    mean_color: str = "red",
    show_median: bool = False,
    median_color: str = "green",
    median_line_style: str = "-",
    show_grid: bool = True,
    show_threshold: bool = False,
    threshold_value: float = 0.8,
    threshold_color: str = "red",
    threshold_line_style: str = "--",
    violin_alpha: float = 0.7,
    violin_width: float = 0.8,
    x_label: str = "Metrics",
    y_label: str = "Score",
    x_label_fontsize: int = 12,
    y_label_fontsize: int = 12,
    y_axis_range: Tuple[float, float] = (0, 1),
    label_rotation: int = 45,
    inner: str = "box",
    dpi: int = 300,
    metrics_to_include: Optional[List[str]] = [
        "overall_accuracy",
        "overall_composition_accuracy",
        "overall_synthesis_accuracy",
        "precision",
        "recall",
        "f1_score",
        "normalized_precision",
        "normalized_recall",
        "normalized_f1_score",
    ],
):
    """
    Create a violin plot for all metrics from a single model's evaluation results.

    Args:
        result_file (str, optional): Path to JSON file containing evaluation results
        result_dict (dict, optional): Dictionary containing evaluation results. Either result_file or result_dict must be provided.
        output_file (str, optional): Path to save the output visualization
        model_name (str, optional): Name to display for the model in the plot
        figsize (tuple, optional): Figure size as (width, height) in inches (default: (14, 10))
        colormap (str, optional): Matplotlib colormap name for the violins (default: 'Blues')
        title (str, optional): Custom title for the plot (default: None)
        title_fontsize (int, optional): Font size for the title text (default: 14)
        title_pad (float, optional): Padding for the title from the top of the plot (default: 10.0)
        show_box (bool, optional): Whether to show a box plot inside the violin (default: False)
        show_mean (bool, optional): Whether to show the mean marker (default: True)
        mean_marker (str, optional): Marker style for the mean (default: 'o')
        mean_color (str, optional): Color for the mean marker (default: 'red')
        show_median (bool, optional): Whether to show the median line (default: False)
        median_color (str, optional): Color for the median line (default: 'green')
        median_line_style (str, optional): Line style for the median (default: '-')
        show_grid (bool, optional): Whether to display the grid lines (default: True)
        show_threshold (bool, optional): Whether to show a threshold line (default: False)
        threshold_value (float, optional): Value for the threshold line (default: 0.8)
        threshold_color (str, optional): Color for the threshold line (default: 'red')
        threshold_line_style (str, optional): Line style for the threshold line (default: '--')
        violin_alpha (float, optional): Alpha (transparency) of the violin plots (default: 0.7)
        violin_width (float, optional): Width of the violin plots (default: 0.8)
        x_label (str, optional): Label for the x-axis (default: 'Metrics')
        y_label (str, optional): Label for the y-axis (default: 'Score')
        x_label_fontsize (int, optional): Font size for x-axis label (default: 12)
        y_label_fontsize (int, optional): Font size for y-axis label (default: 12)
        y_axis_range (tuple, optional): Range for the y-axis (default: (0, 1))
        label_rotation (int, optional): Rotation angle for x-axis labels (default: 45)
        inner (str, optional): The representation of the data points inside the violin ('box', 'stick', 'point', or None) (default: 'box')
        dpi (int, optional): Resolution for saved image (default: 300)
        metrics_to_include (list, optional): Specific metrics to include in the plot (default: None - all available)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_file nor result_dict is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_single_violin_chart(
        result_file=result_file,
        result_dict=result_dict,
        output_file=output_file,
        model_name=model_name,
        figsize=figsize,
        colormap=colormap,
        title=title,
        title_fontsize=title_fontsize,
        title_pad=title_pad,
        show_box=show_box,
        show_mean=show_mean,
        mean_marker=mean_marker,
        mean_color=mean_color,
        show_median=show_median,
        median_color=median_color,
        median_line_style=median_line_style,
        show_grid=show_grid,
        show_threshold=show_threshold,
        threshold_value=threshold_value,
        threshold_color=threshold_color,
        threshold_line_style=threshold_line_style,
        violin_alpha=violin_alpha,
        violin_width=violin_width,
        x_label=x_label,
        y_label=y_label,
        x_label_fontsize=x_label_fontsize,
        y_label_fontsize=y_label_fontsize,
        y_axis_range=y_axis_range,
        label_rotation=label_rotation,
        inner=inner,
        dpi=dpi,
        metrics_to_include=metrics_to_include,
    )
    return fig

plot_multiple_violin_charts

plot_multiple_violin_charts(result_sources: Union[List[str], List[Dict], str] = None, folder_path: Optional[str] = None, output_file: Optional[str] = None, model_names: Optional[List[str]] = None, metric_name: str = 'overall_accuracy', figsize: Tuple[int, int] = (12, 8), colormap: str = 'viridis', title: Optional[str] = None, title_fontsize: int = 14, title_pad: Optional[float] = 50.0, show_box: bool = False, show_mean: bool = True, mean_marker: str = 'o', mean_color: str = 'red', show_median: bool = False, median_color: str = 'green', median_line_style: str = '-', show_grid: bool = True, show_threshold: bool = False, threshold_value: float = 0.8, threshold_color: str = 'red', threshold_line_style: str = '--', violin_alpha: float = 0.7, violin_width: float = 0.8, x_label: str = 'Models', y_label: str = 'Score', x_label_fontsize: int = 12, y_label_fontsize: int = 12, y_axis_range: Tuple[float, float] = (0, 1), label_rotation: int = 45, inner: str = 'box', dpi: int = 300)

Create violin plots comparing multiple models on a single metric.

Parameters:

Name Type Description Default
result_sources Union[List[str], List[Dict], str]

List of paths to JSON files or dictionaries containing evaluation results

None
folder_path Optional[str]

Path to folder containing JSON result files. Either result_sources or folder_path must be provided.

None
output_file str

Path to save the output visualization

None
model_names Optional[List[str]]

Names to display for models in the plot

None
metric_name str

Name of the metric to compare across models (default: "overall_accuracy")

'overall_accuracy'
figsize tuple

Figure size as (width, height) in inches (default: (12, 8))

(12, 8)
colormap str

Matplotlib colormap name for the violins (default: 'viridis')

'viridis'
title str

Custom title for the plot (default: None)

None
title_fontsize int

Font size for the title text (default: 14)

14
title_pad float

Padding for the title from the top of the plot

50.0
show_box bool

Whether to show a box plot inside the violin (default: False)

False
show_mean bool

Whether to show the mean marker (default: True)

True
mean_marker str

Marker style for the mean (default: 'o')

'o'
mean_color str

Color for the mean marker (default: 'red')

'red'
show_median bool

Whether to show the median line (default: False)

False
median_color str

Color for the median line (default: 'green')

'green'
median_line_style str

Line style for the median (default: '-')

'-'
show_grid bool

Whether to display the grid lines (default: True)

True
show_threshold bool

Whether to show a threshold line (default: False)

False
threshold_value float

Value for the threshold line (default: 0.8)

0.8
threshold_color str

Color for the threshold line (default: 'red')

'red'
threshold_line_style str

Line style for the threshold line (default: '--')

'--'
violin_alpha float

Alpha (transparency) of the violin plots (default: 0.7)

0.7
violin_width float

Width of the violin plots (default: 0.8)

0.8
x_label str

Label for the x-axis (default: 'Models')

'Models'
y_label str

Label for the y-axis (default: 'Score')

'Score'
x_label_fontsize int

Font size for x-axis label (default: 12)

12
y_label_fontsize int

Font size for y-axis label (default: 12)

12
y_axis_range tuple

Range for the y-axis (default: (0, 1))

(0, 1)
label_rotation int

Rotation angle for x-axis labels (default: 45)

45
inner str

The representation of the data points inside the violin ('box', 'stick', 'point', or None) (default: 'box')

'box'
dpi int

Resolution for saved image (default: 300)

300

Returns:

Type Description

matplotlib.figure.Figure: The generated figure object

Raises:

Type Description
ValueErrorHandler

If neither result_sources nor folder_path is provided, or if the specified path does not exist

Source code in src/comproscanner/eval_visualizer.py
def plot_multiple_violin_charts(
    result_sources: Union[List[str], List[Dict], str] = None,
    folder_path: Optional[str] = None,
    output_file: Optional[str] = None,
    model_names: Optional[List[str]] = None,
    metric_name: str = "overall_accuracy",
    figsize: Tuple[int, int] = (12, 8),
    colormap: str = "viridis",
    title: Optional[str] = None,
    title_fontsize: int = 14,
    title_pad: Optional[float] = 50.0,
    show_box: bool = False,
    show_mean: bool = True,
    mean_marker: str = "o",
    mean_color: str = "red",
    show_median: bool = False,
    median_color: str = "green",
    median_line_style: str = "-",
    show_grid: bool = True,
    show_threshold: bool = False,
    threshold_value: float = 0.8,
    threshold_color: str = "red",
    threshold_line_style: str = "--",
    violin_alpha: float = 0.7,
    violin_width: float = 0.8,
    x_label: str = "Models",
    y_label: str = "Score",
    x_label_fontsize: int = 12,
    y_label_fontsize: int = 12,
    y_axis_range: Tuple[float, float] = (0, 1),
    label_rotation: int = 45,
    inner: str = "box",
    dpi: int = 300,
):
    """
    Create violin plots comparing multiple models on a single metric.

    Args:
        result_sources (Union[List[str], List[Dict], str], optional): List of paths to JSON files or dictionaries containing evaluation results
        folder_path (Optional[str], optional): Path to folder containing JSON result files. Either result_sources or folder_path must be provided.
        output_file (str, optional): Path to save the output visualization
        model_names (Optional[List[str]]): Names to display for models in the plot
        metric_name (str, optional): Name of the metric to compare across models (default: "overall_accuracy")
        figsize (tuple, optional): Figure size as (width, height) in inches (default: (12, 8))
        colormap (str, optional): Matplotlib colormap name for the violins (default: 'viridis')
        title (str, optional): Custom title for the plot (default: None)
        title_fontsize (int, optional): Font size for the title text (default: 14)
        title_pad (float, optional): Padding for the title from the top of the plot
        show_box (bool, optional): Whether to show a box plot inside the violin (default: False)
        show_mean (bool, optional): Whether to show the mean marker (default: True)
        mean_marker (str, optional): Marker style for the mean (default: 'o')
        mean_color (str, optional): Color for the mean marker (default: 'red')
        show_median (bool, optional): Whether to show the median line (default: False)
        median_color (str, optional): Color for the median line (default: 'green')
        median_line_style (str, optional): Line style for the median (default: '-')
        show_grid (bool, optional): Whether to display the grid lines (default: True)
        show_threshold (bool, optional): Whether to show a threshold line (default: False)
        threshold_value (float, optional): Value for the threshold line (default: 0.8)
        threshold_color (str, optional): Color for the threshold line (default: 'red')
        threshold_line_style (str, optional): Line style for the threshold line (default: '--')
        violin_alpha (float, optional): Alpha (transparency) of the violin plots (default: 0.7)
        violin_width (float, optional): Width of the violin plots (default: 0.8)
        x_label (str, optional): Label for the x-axis (default: 'Models')
        y_label (str, optional): Label for the y-axis (default: 'Score')
        x_label_fontsize (int, optional): Font size for x-axis label (default: 12)
        y_label_fontsize (int, optional): Font size for y-axis label (default: 12)
        y_axis_range (tuple, optional): Range for the y-axis (default: (0, 1))
        label_rotation (int, optional): Rotation angle for x-axis labels (default: 45)
        inner (str, optional): The representation of the data points inside the violin ('box', 'stick', 'point', or None) (default: 'box')
        dpi (int, optional): Resolution for saved image (default: 300)

    Returns:
        matplotlib.figure.Figure: The generated figure object

    Raises:
        ValueErrorHandler: If neither result_sources nor folder_path is provided, or if the specified path does not exist
    """
    visualizer = EvalVisualizer()
    fig = visualizer.plot_multiple_violin_charts(
        result_sources=result_sources,
        folder_path=folder_path,
        output_file=output_file,
        model_names=model_names,
        metric_name=metric_name,
        figsize=figsize,
        colormap=colormap,
        title=title,
        title_fontsize=title_fontsize,
        title_pad=title_pad,
        show_box=show_box,
        show_mean=show_mean,
        mean_marker=mean_marker,
        mean_color=mean_color,
        show_median=show_median,
        median_color=median_color,
        median_line_style=median_line_style,
        show_grid=show_grid,
        show_threshold=show_threshold,
        threshold_value=threshold_value,
        threshold_color=threshold_color,
        threshold_line_style=threshold_line_style,
        violin_alpha=violin_alpha,
        violin_width=violin_width,
        x_label=x_label,
        y_label=y_label,
        x_label_fontsize=x_label_fontsize,
        y_label_fontsize=y_label_fontsize,
        y_axis_range=y_axis_range,
        label_rotation=label_rotation,
        inner=inner,
        dpi=dpi,
    )
    return fig

options: show_root_heading: true heading_level: 2