edsl 0.1.38.dev3__py3-none-any.whl → 0.1.39__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edsl/Base.py +413 -303
- edsl/BaseDiff.py +260 -260
- edsl/TemplateLoader.py +24 -24
- edsl/__init__.py +57 -49
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +1071 -858
- edsl/agents/AgentList.py +551 -362
- edsl/agents/Invigilator.py +284 -222
- edsl/agents/InvigilatorBase.py +257 -284
- edsl/agents/PromptConstructor.py +272 -353
- edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
- edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
- edsl/agents/__init__.py +2 -3
- edsl/agents/descriptors.py +99 -99
- edsl/agents/prompt_helpers.py +129 -129
- edsl/agents/question_option_processor.py +172 -0
- edsl/auto/AutoStudy.py +130 -117
- edsl/auto/StageBase.py +243 -230
- edsl/auto/StageGenerateSurvey.py +178 -178
- edsl/auto/StageLabelQuestions.py +125 -125
- edsl/auto/StagePersona.py +61 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +88 -88
- edsl/auto/StagePersonaDimensionValues.py +74 -74
- edsl/auto/StagePersonaDimensions.py +69 -69
- edsl/auto/StageQuestions.py +74 -73
- edsl/auto/SurveyCreatorPipeline.py +21 -21
- edsl/auto/utilities.py +218 -224
- edsl/base/Base.py +279 -279
- edsl/config.py +177 -149
- edsl/conversation/Conversation.py +290 -290
- edsl/conversation/car_buying.py +59 -58
- edsl/conversation/chips.py +95 -95
- edsl/conversation/mug_negotiation.py +81 -81
- edsl/conversation/next_speaker_utilities.py +93 -93
- edsl/coop/CoopFunctionsMixin.py +15 -0
- edsl/coop/ExpectedParrotKeyHandler.py +125 -0
- edsl/coop/PriceFetcher.py +54 -54
- edsl/coop/__init__.py +2 -2
- edsl/coop/coop.py +1106 -961
- edsl/coop/utils.py +131 -131
- edsl/data/Cache.py +573 -530
- edsl/data/CacheEntry.py +230 -228
- edsl/data/CacheHandler.py +168 -149
- edsl/data/RemoteCacheSync.py +186 -97
- edsl/data/SQLiteDict.py +292 -292
- edsl/data/__init__.py +5 -4
- edsl/data/orm.py +10 -10
- edsl/data_transfer_models.py +74 -73
- edsl/enums.py +202 -173
- edsl/exceptions/BaseException.py +21 -21
- edsl/exceptions/__init__.py +54 -54
- edsl/exceptions/agents.py +54 -42
- edsl/exceptions/cache.py +5 -5
- edsl/exceptions/configuration.py +16 -16
- edsl/exceptions/coop.py +10 -10
- edsl/exceptions/data.py +14 -14
- edsl/exceptions/general.py +34 -34
- edsl/exceptions/inference_services.py +5 -0
- edsl/exceptions/jobs.py +33 -33
- edsl/exceptions/language_models.py +63 -63
- edsl/exceptions/prompts.py +15 -15
- edsl/exceptions/questions.py +109 -91
- edsl/exceptions/results.py +29 -29
- edsl/exceptions/scenarios.py +29 -22
- edsl/exceptions/surveys.py +37 -37
- edsl/inference_services/AnthropicService.py +106 -87
- edsl/inference_services/AvailableModelCacheHandler.py +184 -0
- edsl/inference_services/AvailableModelFetcher.py +215 -0
- edsl/inference_services/AwsBedrock.py +118 -120
- edsl/inference_services/AzureAI.py +215 -217
- edsl/inference_services/DeepInfraService.py +18 -18
- edsl/inference_services/GoogleService.py +143 -156
- edsl/inference_services/GroqService.py +20 -20
- edsl/inference_services/InferenceServiceABC.py +80 -147
- edsl/inference_services/InferenceServicesCollection.py +138 -97
- edsl/inference_services/MistralAIService.py +120 -123
- edsl/inference_services/OllamaService.py +18 -18
- edsl/inference_services/OpenAIService.py +236 -224
- edsl/inference_services/PerplexityService.py +160 -0
- edsl/inference_services/ServiceAvailability.py +135 -0
- edsl/inference_services/TestService.py +90 -89
- edsl/inference_services/TogetherAIService.py +172 -170
- edsl/inference_services/data_structures.py +134 -0
- edsl/inference_services/models_available_cache.py +118 -118
- edsl/inference_services/rate_limits_cache.py +25 -25
- edsl/inference_services/registry.py +41 -39
- edsl/inference_services/write_available.py +10 -10
- edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
- edsl/jobs/Answers.py +43 -56
- edsl/jobs/FetchInvigilator.py +47 -0
- edsl/jobs/InterviewTaskManager.py +98 -0
- edsl/jobs/InterviewsConstructor.py +50 -0
- edsl/jobs/Jobs.py +823 -1358
- edsl/jobs/JobsChecks.py +172 -0
- edsl/jobs/JobsComponentConstructor.py +189 -0
- edsl/jobs/JobsPrompts.py +270 -0
- edsl/jobs/JobsRemoteInferenceHandler.py +311 -0
- edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
- edsl/jobs/RequestTokenEstimator.py +30 -0
- edsl/jobs/__init__.py +1 -1
- edsl/jobs/async_interview_runner.py +138 -0
- edsl/jobs/buckets/BucketCollection.py +104 -63
- edsl/jobs/buckets/ModelBuckets.py +65 -65
- edsl/jobs/buckets/TokenBucket.py +283 -251
- edsl/jobs/buckets/TokenBucketAPI.py +211 -0
- edsl/jobs/buckets/TokenBucketClient.py +191 -0
- edsl/jobs/check_survey_scenario_compatibility.py +85 -0
- edsl/jobs/data_structures.py +120 -0
- edsl/jobs/decorators.py +35 -0
- edsl/jobs/interviews/Interview.py +396 -661
- edsl/jobs/interviews/InterviewExceptionCollection.py +99 -99
- edsl/jobs/interviews/InterviewExceptionEntry.py +186 -186
- edsl/jobs/interviews/InterviewStatistic.py +63 -63
- edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -25
- edsl/jobs/interviews/InterviewStatusDictionary.py +78 -78
- edsl/jobs/interviews/InterviewStatusLog.py +92 -92
- edsl/jobs/interviews/ReportErrors.py +66 -66
- edsl/jobs/interviews/interview_status_enum.py +9 -9
- edsl/jobs/jobs_status_enums.py +9 -0
- edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
- edsl/jobs/results_exceptions_handler.py +98 -0
- edsl/jobs/runners/JobsRunnerAsyncio.py +151 -361
- edsl/jobs/runners/JobsRunnerStatus.py +298 -332
- edsl/jobs/tasks/QuestionTaskCreator.py +244 -242
- edsl/jobs/tasks/TaskCreators.py +64 -64
- edsl/jobs/tasks/TaskHistory.py +470 -451
- edsl/jobs/tasks/TaskStatusLog.py +23 -23
- edsl/jobs/tasks/task_status_enum.py +161 -163
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -27
- edsl/jobs/tokens/TokenUsage.py +34 -34
- edsl/language_models/ComputeCost.py +63 -0
- edsl/language_models/LanguageModel.py +626 -708
- edsl/language_models/ModelList.py +164 -109
- edsl/language_models/PriceManager.py +127 -0
- edsl/language_models/RawResponseHandler.py +106 -0
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -184
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/__init__.py +2 -3
- edsl/language_models/fake_openai_call.py +15 -15
- edsl/language_models/fake_openai_service.py +61 -61
- edsl/language_models/key_management/KeyLookup.py +63 -0
- edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
- edsl/language_models/key_management/KeyLookupCollection.py +38 -0
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +131 -0
- edsl/language_models/model.py +256 -0
- edsl/language_models/repair.py +156 -156
- edsl/language_models/utilities.py +65 -64
- edsl/notebooks/Notebook.py +263 -258
- edsl/notebooks/NotebookToLaTeX.py +142 -0
- edsl/notebooks/__init__.py +1 -1
- edsl/prompts/Prompt.py +352 -357
- edsl/prompts/__init__.py +2 -2
- edsl/questions/ExceptionExplainer.py +77 -0
- edsl/questions/HTMLQuestion.py +103 -0
- edsl/questions/QuestionBase.py +518 -660
- edsl/questions/QuestionBasePromptsMixin.py +221 -217
- edsl/questions/QuestionBudget.py +227 -227
- edsl/questions/QuestionCheckBox.py +359 -359
- edsl/questions/QuestionExtract.py +180 -183
- edsl/questions/QuestionFreeText.py +113 -114
- edsl/questions/QuestionFunctional.py +166 -166
- edsl/questions/QuestionList.py +223 -231
- edsl/questions/QuestionMatrix.py +265 -0
- edsl/questions/QuestionMultipleChoice.py +330 -286
- edsl/questions/QuestionNumerical.py +151 -153
- edsl/questions/QuestionRank.py +314 -324
- edsl/questions/Quick.py +41 -41
- edsl/questions/SimpleAskMixin.py +74 -73
- edsl/questions/__init__.py +27 -26
- edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +334 -289
- edsl/questions/compose_questions.py +98 -98
- edsl/questions/data_structures.py +20 -0
- edsl/questions/decorators.py +21 -21
- edsl/questions/derived/QuestionLikertFive.py +76 -76
- edsl/questions/derived/QuestionLinearScale.py +90 -87
- edsl/questions/derived/QuestionTopK.py +93 -93
- edsl/questions/derived/QuestionYesNo.py +82 -82
- edsl/questions/descriptors.py +427 -413
- edsl/questions/loop_processor.py +149 -0
- edsl/questions/prompt_templates/question_budget.jinja +13 -13
- edsl/questions/prompt_templates/question_checkbox.jinja +32 -32
- edsl/questions/prompt_templates/question_extract.jinja +11 -11
- edsl/questions/prompt_templates/question_free_text.jinja +3 -3
- edsl/questions/prompt_templates/question_linear_scale.jinja +11 -11
- edsl/questions/prompt_templates/question_list.jinja +17 -17
- edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -33
- edsl/questions/prompt_templates/question_numerical.jinja +36 -36
- edsl/questions/{QuestionBaseGenMixin.py → question_base_gen_mixin.py} +168 -161
- edsl/questions/question_registry.py +177 -147
- edsl/questions/{RegisterQuestionsMeta.py → register_questions_meta.py} +71 -71
- edsl/questions/{ResponseValidatorABC.py → response_validator_abc.py} +188 -174
- edsl/questions/response_validator_factory.py +34 -0
- edsl/questions/settings.py +12 -12
- edsl/questions/templates/budget/answering_instructions.jinja +7 -7
- edsl/questions/templates/budget/question_presentation.jinja +7 -7
- edsl/questions/templates/checkbox/answering_instructions.jinja +10 -10
- edsl/questions/templates/checkbox/question_presentation.jinja +22 -22
- edsl/questions/templates/extract/answering_instructions.jinja +7 -7
- edsl/questions/templates/likert_five/answering_instructions.jinja +10 -10
- edsl/questions/templates/likert_five/question_presentation.jinja +11 -11
- edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -5
- edsl/questions/templates/linear_scale/question_presentation.jinja +5 -5
- edsl/questions/templates/list/answering_instructions.jinja +3 -3
- edsl/questions/templates/list/question_presentation.jinja +5 -5
- edsl/questions/templates/matrix/__init__.py +1 -0
- edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
- edsl/questions/templates/matrix/question_presentation.jinja +20 -0
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -9
- edsl/questions/templates/multiple_choice/question_presentation.jinja +11 -11
- edsl/questions/templates/numerical/answering_instructions.jinja +6 -6
- edsl/questions/templates/numerical/question_presentation.jinja +6 -6
- edsl/questions/templates/rank/answering_instructions.jinja +11 -11
- edsl/questions/templates/rank/question_presentation.jinja +15 -15
- edsl/questions/templates/top_k/answering_instructions.jinja +8 -8
- edsl/questions/templates/top_k/question_presentation.jinja +22 -22
- edsl/questions/templates/yes_no/answering_instructions.jinja +6 -6
- edsl/questions/templates/yes_no/question_presentation.jinja +11 -11
- edsl/results/CSSParameterizer.py +108 -0
- edsl/results/Dataset.py +587 -293
- edsl/results/DatasetExportMixin.py +594 -717
- edsl/results/DatasetTree.py +295 -145
- edsl/results/MarkdownToDocx.py +122 -0
- edsl/results/MarkdownToPDF.py +111 -0
- edsl/results/Result.py +557 -456
- edsl/results/Results.py +1183 -1071
- edsl/results/ResultsExportMixin.py +45 -43
- edsl/results/ResultsGGMixin.py +121 -121
- edsl/results/TableDisplay.py +125 -0
- edsl/results/TextEditor.py +50 -0
- edsl/results/__init__.py +2 -2
- edsl/results/file_exports.py +252 -0
- edsl/results/{ResultsFetchMixin.py → results_fetch_mixin.py} +33 -33
- edsl/results/{Selector.py → results_selector.py} +145 -135
- edsl/results/{ResultsToolsMixin.py → results_tools_mixin.py} +98 -98
- edsl/results/smart_objects.py +96 -0
- edsl/results/table_data_class.py +12 -0
- edsl/results/table_display.css +78 -0
- edsl/results/table_renderers.py +118 -0
- edsl/results/tree_explore.py +115 -115
- edsl/scenarios/ConstructDownloadLink.py +109 -0
- edsl/scenarios/DocumentChunker.py +102 -0
- edsl/scenarios/DocxScenario.py +16 -0
- edsl/scenarios/FileStore.py +543 -458
- edsl/scenarios/PdfExtractor.py +40 -0
- edsl/scenarios/Scenario.py +498 -544
- edsl/scenarios/ScenarioHtmlMixin.py +65 -64
- edsl/scenarios/ScenarioList.py +1458 -1112
- edsl/scenarios/ScenarioListExportMixin.py +45 -52
- edsl/scenarios/ScenarioListPdfMixin.py +239 -261
- edsl/scenarios/__init__.py +3 -4
- edsl/scenarios/directory_scanner.py +96 -0
- edsl/scenarios/file_methods.py +85 -0
- edsl/scenarios/handlers/__init__.py +13 -0
- edsl/scenarios/handlers/csv.py +49 -0
- edsl/scenarios/handlers/docx.py +76 -0
- edsl/scenarios/handlers/html.py +37 -0
- edsl/scenarios/handlers/json.py +111 -0
- edsl/scenarios/handlers/latex.py +5 -0
- edsl/scenarios/handlers/md.py +51 -0
- edsl/scenarios/handlers/pdf.py +68 -0
- edsl/scenarios/handlers/png.py +39 -0
- edsl/scenarios/handlers/pptx.py +105 -0
- edsl/scenarios/handlers/py.py +294 -0
- edsl/scenarios/handlers/sql.py +313 -0
- edsl/scenarios/handlers/sqlite.py +149 -0
- edsl/scenarios/handlers/txt.py +33 -0
- edsl/scenarios/scenario_join.py +131 -0
- edsl/scenarios/scenario_selector.py +156 -0
- edsl/shared.py +1 -1
- edsl/study/ObjectEntry.py +173 -173
- edsl/study/ProofOfWork.py +113 -113
- edsl/study/SnapShot.py +80 -80
- edsl/study/Study.py +521 -528
- edsl/study/__init__.py +4 -4
- edsl/surveys/ConstructDAG.py +92 -0
- edsl/surveys/DAG.py +148 -148
- edsl/surveys/EditSurvey.py +221 -0
- edsl/surveys/InstructionHandler.py +100 -0
- edsl/surveys/Memory.py +31 -31
- edsl/surveys/MemoryManagement.py +72 -0
- edsl/surveys/MemoryPlan.py +244 -244
- edsl/surveys/Rule.py +327 -326
- edsl/surveys/RuleCollection.py +385 -387
- edsl/surveys/RuleManager.py +172 -0
- edsl/surveys/Simulator.py +75 -0
- edsl/surveys/Survey.py +1280 -1787
- edsl/surveys/SurveyCSS.py +273 -261
- edsl/surveys/SurveyExportMixin.py +259 -259
- edsl/surveys/{SurveyFlowVisualizationMixin.py → SurveyFlowVisualization.py} +181 -121
- edsl/surveys/SurveyQualtricsImport.py +284 -284
- edsl/surveys/SurveyToApp.py +141 -0
- edsl/surveys/__init__.py +5 -3
- edsl/surveys/base.py +53 -53
- edsl/surveys/descriptors.py +60 -56
- edsl/surveys/instructions/ChangeInstruction.py +48 -49
- edsl/surveys/instructions/Instruction.py +56 -53
- edsl/surveys/instructions/InstructionCollection.py +82 -77
- edsl/templates/error_reporting/base.html +23 -23
- edsl/templates/error_reporting/exceptions_by_model.html +34 -34
- edsl/templates/error_reporting/exceptions_by_question_name.html +16 -16
- edsl/templates/error_reporting/exceptions_by_type.html +16 -16
- edsl/templates/error_reporting/interview_details.html +115 -115
- edsl/templates/error_reporting/interviews.html +19 -10
- edsl/templates/error_reporting/overview.html +4 -4
- edsl/templates/error_reporting/performance_plot.html +1 -1
- edsl/templates/error_reporting/report.css +73 -73
- edsl/templates/error_reporting/report.html +117 -117
- edsl/templates/error_reporting/report.js +25 -25
- edsl/tools/__init__.py +1 -1
- edsl/tools/clusters.py +192 -192
- edsl/tools/embeddings.py +27 -27
- edsl/tools/embeddings_plotting.py +118 -118
- edsl/tools/plotting.py +112 -112
- edsl/tools/summarize.py +18 -18
- edsl/utilities/PrettyList.py +56 -0
- edsl/utilities/SystemInfo.py +28 -28
- edsl/utilities/__init__.py +22 -22
- edsl/utilities/ast_utilities.py +25 -25
- edsl/utilities/data/Registry.py +6 -6
- edsl/utilities/data/__init__.py +1 -1
- edsl/utilities/data/scooter_results.json +1 -1
- edsl/utilities/decorators.py +77 -77
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -96
- edsl/utilities/interface.py +627 -627
- edsl/utilities/is_notebook.py +18 -0
- edsl/utilities/is_valid_variable_name.py +11 -0
- edsl/utilities/naming_utilities.py +263 -263
- edsl/utilities/remove_edsl_version.py +24 -0
- edsl/utilities/repair_functions.py +28 -28
- edsl/utilities/restricted_python.py +70 -70
- edsl/utilities/utilities.py +436 -409
- {edsl-0.1.38.dev3.dist-info → edsl-0.1.39.dist-info}/LICENSE +21 -21
- {edsl-0.1.38.dev3.dist-info → edsl-0.1.39.dist-info}/METADATA +13 -10
- edsl-0.1.39.dist-info/RECORD +358 -0
- {edsl-0.1.38.dev3.dist-info → edsl-0.1.39.dist-info}/WHEEL +1 -1
- edsl/language_models/KeyLookup.py +0 -30
- edsl/language_models/registry.py +0 -137
- edsl/language_models/unused/ReplicateBase.py +0 -83
- edsl/results/ResultsDBMixin.py +0 -238
- edsl-0.1.38.dev3.dist-info/RECORD +0 -269
@@ -1,43 +1,45 @@
|
|
1
|
-
"""Mixin class for exporting results."""
|
2
|
-
|
3
|
-
from functools import wraps
|
4
|
-
from typing import Literal, Optional, Union
|
5
|
-
|
6
|
-
from edsl.results.DatasetExportMixin import DatasetExportMixin
|
7
|
-
|
8
|
-
|
9
|
-
def to_dataset(func):
|
10
|
-
"""Convert the Results object to a Dataset object before calling the function."""
|
11
|
-
|
12
|
-
@wraps(func)
|
13
|
-
def wrapper(self, *args, **kwargs):
|
14
|
-
"""Return the function with the Results object converted to a Dataset object."""
|
15
|
-
if self.__class__.__name__ == "Results":
|
16
|
-
return func(self.select(), *args, **kwargs)
|
17
|
-
|
18
|
-
return func(self, *args, **kwargs)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
doctest
|
1
|
+
"""Mixin class for exporting results."""
|
2
|
+
|
3
|
+
from functools import wraps
|
4
|
+
from typing import Literal, Optional, Union
|
5
|
+
|
6
|
+
from edsl.results.DatasetExportMixin import DatasetExportMixin
|
7
|
+
|
8
|
+
|
9
|
+
def to_dataset(func):
|
10
|
+
"""Convert the Results object to a Dataset object before calling the function."""
|
11
|
+
|
12
|
+
@wraps(func)
|
13
|
+
def wrapper(self, *args, **kwargs):
|
14
|
+
"""Return the function with the Results object converted to a Dataset object."""
|
15
|
+
if self.__class__.__name__ == "Results":
|
16
|
+
return func(self.select(), *args, **kwargs)
|
17
|
+
elif self.__class__.__name__ == "AgentList":
|
18
|
+
return func(self.to_dataset(), *args, **kwargs)
|
19
|
+
else:
|
20
|
+
return func(self, *args, **kwargs)
|
21
|
+
|
22
|
+
wrapper._is_wrapped = True
|
23
|
+
return wrapper
|
24
|
+
|
25
|
+
|
26
|
+
def decorate_methods_from_mixin(cls, mixin_cls):
|
27
|
+
for attr_name, attr_value in mixin_cls.__dict__.items():
|
28
|
+
if callable(attr_value) and not attr_name.startswith("__"):
|
29
|
+
setattr(cls, attr_name, to_dataset(attr_value))
|
30
|
+
return cls
|
31
|
+
|
32
|
+
|
33
|
+
class ResultsExportMixin(DatasetExportMixin):
|
34
|
+
"""Mixin class for exporting Results objects."""
|
35
|
+
|
36
|
+
def __init_subclass__(cls, **kwargs):
|
37
|
+
super().__init_subclass__(**kwargs)
|
38
|
+
decorate_methods_from_mixin(cls, DatasetExportMixin)
|
39
|
+
|
40
|
+
|
41
|
+
if __name__ == "__main__":
|
42
|
+
# pass
|
43
|
+
import doctest
|
44
|
+
|
45
|
+
doctest.testmod(optionflags=doctest.ELLIPSIS)
|
edsl/results/ResultsGGMixin.py
CHANGED
@@ -1,121 +1,121 @@
|
|
1
|
-
"""Mixin class for ggplot2 plotting."""
|
2
|
-
|
3
|
-
import subprocess
|
4
|
-
import tempfile
|
5
|
-
from typing import Optional
|
6
|
-
|
7
|
-
|
8
|
-
class ResultsGGMixin:
|
9
|
-
"""Mixin class for ggplot2 plotting."""
|
10
|
-
|
11
|
-
def ggplot2(
|
12
|
-
self,
|
13
|
-
ggplot_code: str,
|
14
|
-
filename: str = None,
|
15
|
-
shape="wide",
|
16
|
-
sql: str = None,
|
17
|
-
remove_prefix: bool = True,
|
18
|
-
debug: bool = False,
|
19
|
-
height=4,
|
20
|
-
width=6,
|
21
|
-
format="svg",
|
22
|
-
factor_orders: Optional[dict] = None,
|
23
|
-
):
|
24
|
-
"""Create a ggplot2 plot from a DataFrame.
|
25
|
-
|
26
|
-
:param ggplot_code: The ggplot2 code to execute.
|
27
|
-
:param filename: The filename to save the plot to.
|
28
|
-
:param shape: The shape of the data in the DataFrame (wide or long).
|
29
|
-
:param sql: The SQL query to execute beforehand to manipulate the data.
|
30
|
-
:param remove_prefix: Whether to remove the prefix from the column names.
|
31
|
-
:param debug: Whether to print the R code instead of executing it.
|
32
|
-
:param height: The height of the plot in inches.
|
33
|
-
:param width: The width of the plot in inches.
|
34
|
-
:param format: The format to save the plot in (png or svg).
|
35
|
-
:param factor_orders: A dictionary of factor columns and their order.
|
36
|
-
"""
|
37
|
-
|
38
|
-
if sql == None:
|
39
|
-
sql = "select * from self"
|
40
|
-
|
41
|
-
if shape == "long":
|
42
|
-
df = self.sql(sql, shape="long")
|
43
|
-
elif shape == "wide":
|
44
|
-
df = self.sql(sql, shape="wide", remove_prefix=remove_prefix)
|
45
|
-
|
46
|
-
# Convert DataFrame to CSV format
|
47
|
-
csv_data = df.to_csv(index=False)
|
48
|
-
|
49
|
-
# Embed the CSV data within the R script
|
50
|
-
csv_data_escaped = csv_data.replace("\n", "\\n").replace("'", "\\'")
|
51
|
-
read_csv_code = f"self <- read.csv(text = '{csv_data_escaped}', sep = ',')\n"
|
52
|
-
|
53
|
-
if factor_orders is not None:
|
54
|
-
for factor, order in factor_orders.items():
|
55
|
-
# read_csv_code += f"""self${{{factor}}} <- factor(self${{{factor}}}, levels=c({','.join(['"{}"'.format(x) for x in order])}))"""
|
56
|
-
|
57
|
-
level_string = ", ".join([f'"{x}"' for x in order])
|
58
|
-
read_csv_code += (
|
59
|
-
f"self${factor} <- factor(self${factor}, levels=c({level_string}))"
|
60
|
-
)
|
61
|
-
read_csv_code += "\n"
|
62
|
-
|
63
|
-
# Load ggplot2 library
|
64
|
-
load_ggplot2 = "library(ggplot2)\n"
|
65
|
-
|
66
|
-
# Check if a filename is provided for the plot, if not create a temporary one
|
67
|
-
if not filename:
|
68
|
-
filename = tempfile.mktemp(suffix=f".{format}")
|
69
|
-
|
70
|
-
# Combine all R script parts
|
71
|
-
full_r_code = load_ggplot2 + read_csv_code + ggplot_code
|
72
|
-
|
73
|
-
# Add command to save the plot to a file
|
74
|
-
full_r_code += f'\nggsave("{filename}", plot = last_plot(), width = {width}, height = {height}, device = "{format}")'
|
75
|
-
|
76
|
-
if debug:
|
77
|
-
print(full_r_code)
|
78
|
-
return
|
79
|
-
|
80
|
-
result = subprocess.run(
|
81
|
-
["Rscript", "-"],
|
82
|
-
input=full_r_code,
|
83
|
-
text=True,
|
84
|
-
stdout=subprocess.PIPE,
|
85
|
-
stderr=subprocess.PIPE,
|
86
|
-
)
|
87
|
-
|
88
|
-
if result.returncode != 0:
|
89
|
-
if result.returncode == 127: # 'command not found'
|
90
|
-
raise RuntimeError(
|
91
|
-
"Rscript is probably not installed. Please install R from https://cran.r-project.org/"
|
92
|
-
)
|
93
|
-
else:
|
94
|
-
raise RuntimeError(
|
95
|
-
f"An error occurred while running Rscript: {result.stderr}"
|
96
|
-
)
|
97
|
-
|
98
|
-
if result.stderr:
|
99
|
-
print("Error in R script:", result.stderr)
|
100
|
-
else:
|
101
|
-
self._display_plot(filename, width, height)
|
102
|
-
|
103
|
-
def _display_plot(self, filename: str, width: float, height: float):
|
104
|
-
"""Display the plot in the notebook."""
|
105
|
-
import matplotlib.pyplot as plt
|
106
|
-
import matplotlib.image as mpimg
|
107
|
-
|
108
|
-
if filename.endswith(".png"):
|
109
|
-
img = mpimg.imread(filename)
|
110
|
-
plt.figure(
|
111
|
-
figsize=(width, height)
|
112
|
-
) # Set the figure size (width, height) in inches
|
113
|
-
plt.imshow(img)
|
114
|
-
plt.axis("off")
|
115
|
-
plt.show()
|
116
|
-
elif filename.endswith(".svg"):
|
117
|
-
from IPython.display import SVG, display
|
118
|
-
|
119
|
-
display(SVG(filename=filename))
|
120
|
-
else:
|
121
|
-
print("Unsupported file format. Please provide a PNG or SVG file.")
|
1
|
+
"""Mixin class for ggplot2 plotting."""
|
2
|
+
|
3
|
+
import subprocess
|
4
|
+
import tempfile
|
5
|
+
from typing import Optional
|
6
|
+
|
7
|
+
|
8
|
+
class ResultsGGMixin:
|
9
|
+
"""Mixin class for ggplot2 plotting."""
|
10
|
+
|
11
|
+
def ggplot2(
|
12
|
+
self,
|
13
|
+
ggplot_code: str,
|
14
|
+
filename: str = None,
|
15
|
+
shape="wide",
|
16
|
+
sql: str = None,
|
17
|
+
remove_prefix: bool = True,
|
18
|
+
debug: bool = False,
|
19
|
+
height=4,
|
20
|
+
width=6,
|
21
|
+
format="svg",
|
22
|
+
factor_orders: Optional[dict] = None,
|
23
|
+
):
|
24
|
+
"""Create a ggplot2 plot from a DataFrame.
|
25
|
+
|
26
|
+
:param ggplot_code: The ggplot2 code to execute.
|
27
|
+
:param filename: The filename to save the plot to.
|
28
|
+
:param shape: The shape of the data in the DataFrame (wide or long).
|
29
|
+
:param sql: The SQL query to execute beforehand to manipulate the data.
|
30
|
+
:param remove_prefix: Whether to remove the prefix from the column names.
|
31
|
+
:param debug: Whether to print the R code instead of executing it.
|
32
|
+
:param height: The height of the plot in inches.
|
33
|
+
:param width: The width of the plot in inches.
|
34
|
+
:param format: The format to save the plot in (png or svg).
|
35
|
+
:param factor_orders: A dictionary of factor columns and their order.
|
36
|
+
"""
|
37
|
+
|
38
|
+
if sql == None:
|
39
|
+
sql = "select * from self"
|
40
|
+
|
41
|
+
if shape == "long":
|
42
|
+
df = self.sql(sql, shape="long")
|
43
|
+
elif shape == "wide":
|
44
|
+
df = self.sql(sql, shape="wide", remove_prefix=remove_prefix)
|
45
|
+
|
46
|
+
# Convert DataFrame to CSV format
|
47
|
+
csv_data = df.to_csv(index=False)
|
48
|
+
|
49
|
+
# Embed the CSV data within the R script
|
50
|
+
csv_data_escaped = csv_data.replace("\n", "\\n").replace("'", "\\'")
|
51
|
+
read_csv_code = f"self <- read.csv(text = '{csv_data_escaped}', sep = ',')\n"
|
52
|
+
|
53
|
+
if factor_orders is not None:
|
54
|
+
for factor, order in factor_orders.items():
|
55
|
+
# read_csv_code += f"""self${{{factor}}} <- factor(self${{{factor}}}, levels=c({','.join(['"{}"'.format(x) for x in order])}))"""
|
56
|
+
|
57
|
+
level_string = ", ".join([f'"{x}"' for x in order])
|
58
|
+
read_csv_code += (
|
59
|
+
f"self${factor} <- factor(self${factor}, levels=c({level_string}))"
|
60
|
+
)
|
61
|
+
read_csv_code += "\n"
|
62
|
+
|
63
|
+
# Load ggplot2 library
|
64
|
+
load_ggplot2 = "library(ggplot2)\n"
|
65
|
+
|
66
|
+
# Check if a filename is provided for the plot, if not create a temporary one
|
67
|
+
if not filename:
|
68
|
+
filename = tempfile.mktemp(suffix=f".{format}")
|
69
|
+
|
70
|
+
# Combine all R script parts
|
71
|
+
full_r_code = load_ggplot2 + read_csv_code + ggplot_code
|
72
|
+
|
73
|
+
# Add command to save the plot to a file
|
74
|
+
full_r_code += f'\nggsave("{filename}", plot = last_plot(), width = {width}, height = {height}, device = "{format}")'
|
75
|
+
|
76
|
+
if debug:
|
77
|
+
print(full_r_code)
|
78
|
+
return
|
79
|
+
|
80
|
+
result = subprocess.run(
|
81
|
+
["Rscript", "-"],
|
82
|
+
input=full_r_code,
|
83
|
+
text=True,
|
84
|
+
stdout=subprocess.PIPE,
|
85
|
+
stderr=subprocess.PIPE,
|
86
|
+
)
|
87
|
+
|
88
|
+
if result.returncode != 0:
|
89
|
+
if result.returncode == 127: # 'command not found'
|
90
|
+
raise RuntimeError(
|
91
|
+
"Rscript is probably not installed. Please install R from https://cran.r-project.org/"
|
92
|
+
)
|
93
|
+
else:
|
94
|
+
raise RuntimeError(
|
95
|
+
f"An error occurred while running Rscript: {result.stderr}"
|
96
|
+
)
|
97
|
+
|
98
|
+
if result.stderr:
|
99
|
+
print("Error in R script:", result.stderr)
|
100
|
+
else:
|
101
|
+
self._display_plot(filename, width, height)
|
102
|
+
|
103
|
+
def _display_plot(self, filename: str, width: float, height: float):
|
104
|
+
"""Display the plot in the notebook."""
|
105
|
+
import matplotlib.pyplot as plt
|
106
|
+
import matplotlib.image as mpimg
|
107
|
+
|
108
|
+
if filename.endswith(".png"):
|
109
|
+
img = mpimg.imread(filename)
|
110
|
+
plt.figure(
|
111
|
+
figsize=(width, height)
|
112
|
+
) # Set the figure size (width, height) in inches
|
113
|
+
plt.imshow(img)
|
114
|
+
plt.axis("off")
|
115
|
+
plt.show()
|
116
|
+
elif filename.endswith(".svg"):
|
117
|
+
from IPython.display import SVG, display
|
118
|
+
|
119
|
+
display(SVG(filename=filename))
|
120
|
+
else:
|
121
|
+
print("Unsupported file format. Please provide a PNG or SVG file.")
|
@@ -0,0 +1,125 @@
|
|
1
|
+
from typing import (
|
2
|
+
Protocol,
|
3
|
+
List,
|
4
|
+
Any,
|
5
|
+
Optional,
|
6
|
+
TYPE_CHECKING,
|
7
|
+
Sequence,
|
8
|
+
Union,
|
9
|
+
Literal,
|
10
|
+
)
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from edsl.results.Dataset import Dataset
|
14
|
+
|
15
|
+
from edsl.results.table_data_class import TableData
|
16
|
+
|
17
|
+
from edsl.results.table_renderers import DataTablesRenderer, PandasStyleRenderer
|
18
|
+
|
19
|
+
Row = Sequence[Union[str, int, float, bool, None]]
|
20
|
+
TableFormat = Literal[
|
21
|
+
"grid", "simple", "pipe", "orgtbl", "rst", "mediawiki", "html", "latex"
|
22
|
+
]
|
23
|
+
|
24
|
+
|
25
|
+
class TableRenderer(Protocol):
|
26
|
+
"""Table renderer protocol"""
|
27
|
+
|
28
|
+
def render_html(self, table_data: TableData) -> str:
|
29
|
+
pass
|
30
|
+
|
31
|
+
|
32
|
+
# Modified TableDisplay class
|
33
|
+
class TableDisplay:
|
34
|
+
def __init__(
|
35
|
+
self,
|
36
|
+
headers: Sequence[str],
|
37
|
+
data: Sequence[Row],
|
38
|
+
tablefmt: Optional[TableFormat] = None,
|
39
|
+
raw_data_set: "Dataset" = None,
|
40
|
+
renderer_class: Optional[TableRenderer] = None,
|
41
|
+
):
|
42
|
+
assert len(headers) == len(data[0]) # Check if headers and data are consistent
|
43
|
+
|
44
|
+
self.headers = headers
|
45
|
+
self.data = data
|
46
|
+
self.tablefmt = tablefmt
|
47
|
+
self.raw_data_set = raw_data_set
|
48
|
+
|
49
|
+
self.renderer_class = renderer_class or PandasStyleRenderer
|
50
|
+
|
51
|
+
# Handle printing parameters from raw_data_set
|
52
|
+
if hasattr(raw_data_set, "print_parameters"):
|
53
|
+
self.printing_parameters = (
|
54
|
+
raw_data_set.print_parameters if raw_data_set.print_parameters else {}
|
55
|
+
)
|
56
|
+
else:
|
57
|
+
self.printing_parameters = {}
|
58
|
+
|
59
|
+
def _repr_html_(self) -> str:
|
60
|
+
table_data = TableData(
|
61
|
+
headers=self.headers,
|
62
|
+
data=self.data,
|
63
|
+
parameters=self.printing_parameters,
|
64
|
+
raw_data_set=self.raw_data_set,
|
65
|
+
)
|
66
|
+
return self.renderer_class(table_data).render_html()
|
67
|
+
|
68
|
+
def __repr__(self):
|
69
|
+
from tabulate import tabulate
|
70
|
+
|
71
|
+
return tabulate(self.data, headers=self.headers, tablefmt=self.tablefmt)
|
72
|
+
|
73
|
+
@classmethod
|
74
|
+
def from_dictionary(
|
75
|
+
cls,
|
76
|
+
dictionary: dict,
|
77
|
+
tablefmt: Optional[TableFormat] = None,
|
78
|
+
renderer: Optional[TableRenderer] = None,
|
79
|
+
) -> "TableDisplay":
|
80
|
+
headers = list(dictionary.keys())
|
81
|
+
data = [list(dictionary.values())]
|
82
|
+
return cls(headers, data, tablefmt, renderer_class=renderer)
|
83
|
+
|
84
|
+
@classmethod
|
85
|
+
def from_dictionary_wide(
|
86
|
+
cls,
|
87
|
+
dictionary: dict,
|
88
|
+
tablefmt: Optional[TableFormat] = None,
|
89
|
+
renderer: Optional[TableRenderer] = None,
|
90
|
+
) -> "TableDisplay":
|
91
|
+
headers = ["key", "value"]
|
92
|
+
data = [[k, v] for k, v in dictionary.items()]
|
93
|
+
return cls(headers, data, tablefmt, renderer_class=renderer)
|
94
|
+
|
95
|
+
@classmethod
|
96
|
+
def from_dataset(
|
97
|
+
cls,
|
98
|
+
dataset: "Dataset",
|
99
|
+
tablefmt: Optional[TableFormat] = None,
|
100
|
+
renderer: Optional[TableRenderer] = None,
|
101
|
+
) -> "TableDisplay":
|
102
|
+
headers, data = dataset._tabular()
|
103
|
+
return cls(headers, data, tablefmt, dataset, renderer_class=renderer)
|
104
|
+
|
105
|
+
def long(self) -> "TableDisplay":
|
106
|
+
"""Convert to long format"""
|
107
|
+
new_header = ["row", "key", "value"]
|
108
|
+
new_data = []
|
109
|
+
for index, row in enumerate(self.data):
|
110
|
+
new_data.extend([[index, k, v] for k, v in zip(self.headers, row)])
|
111
|
+
return TableDisplay(
|
112
|
+
new_header, new_data, self.tablefmt, renderer_class=self.renderer_class
|
113
|
+
)
|
114
|
+
|
115
|
+
|
116
|
+
# Example usage:
|
117
|
+
if __name__ == "__main__":
|
118
|
+
headers = ["Name", "Age", "City"]
|
119
|
+
data = [["John", 30, "New York"], ["Jane", 25, "London"]]
|
120
|
+
|
121
|
+
# Using default (Pandas) renderer
|
122
|
+
table1 = TableDisplay(headers, data)
|
123
|
+
|
124
|
+
# Using DataTables renderer
|
125
|
+
table2 = TableDisplay(headers, data, renderer=DataTablesRenderer())
|
@@ -0,0 +1,50 @@
|
|
1
|
+
try:
|
2
|
+
import gradio as gr
|
3
|
+
except ImportError:
|
4
|
+
print("Gradio is not installed. Please install it using `pip install gradio`")
|
5
|
+
|
6
|
+
import time
|
7
|
+
|
8
|
+
|
9
|
+
class TextEditor:
|
10
|
+
def __init__(self, initial_text=""):
|
11
|
+
self.text = initial_text
|
12
|
+
self._text_saved = False
|
13
|
+
|
14
|
+
def save_text(self, new_text):
|
15
|
+
self.text = new_text
|
16
|
+
self._text_saved = True
|
17
|
+
return "Text saved successfully!"
|
18
|
+
|
19
|
+
def edit_gui(self):
|
20
|
+
js_code = """
|
21
|
+
async (text) => {
|
22
|
+
await navigator.clipboard.writeText(text);
|
23
|
+
return "Copied to clipboard!";
|
24
|
+
}
|
25
|
+
"""
|
26
|
+
|
27
|
+
with gr.Blocks() as interface:
|
28
|
+
text_area = gr.Textbox(
|
29
|
+
value=self.text, lines=10, label="Edit Text", placeholder="Type here..."
|
30
|
+
)
|
31
|
+
|
32
|
+
with gr.Row():
|
33
|
+
save_btn = gr.Button("Save")
|
34
|
+
copy_btn = gr.Button("Copy to Clipboard")
|
35
|
+
|
36
|
+
output = gr.Textbox(label="Status")
|
37
|
+
|
38
|
+
save_btn.click(fn=self.save_text, inputs=[text_area], outputs=[output])
|
39
|
+
|
40
|
+
# Add copy functionality
|
41
|
+
copy_btn.click(
|
42
|
+
fn=None, inputs=text_area, outputs=output, api_name=False, js=js_code
|
43
|
+
)
|
44
|
+
|
45
|
+
interface.launch(share=False, prevent_thread_lock=True)
|
46
|
+
|
47
|
+
while not self._text_saved:
|
48
|
+
time.sleep(0.1)
|
49
|
+
|
50
|
+
return self.text
|
edsl/results/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
from edsl.results.Result import Result
|
2
|
-
from edsl.results.Results import Results
|
1
|
+
# from edsl.results.Result import Result
|
2
|
+
from edsl.results.Results import Results
|