Skip to content

Commit

Permalink
feat: string expression to latex expression conversion (#4181)
Browse files Browse the repository at this point in the history
  • Loading branch information
shawnyama authored Jul 23, 2024
1 parent 7998046 commit cd820e7
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/client/hmi-client/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dist-ssr
# Test artifacts
coverage
/tests/e2e/test-report/
/tests/unit/reports/
/tests/e2e/test-results/
/tests/component/test-report/
/playwright/.cache/
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@
@item-select="$emit('update-item', { key: 'concept', value: $event.value.curie })"
/>
</span>
<katex-element class="expression" v-if="item.expression" :expression="item.expression" :throw-on-error="false" />
<katex-element
class="expression"
v-if="item.expression"
:expression="stringToLatexExpression(item.expression)"
:throw-on-error="false"
/>
<tera-input
title="Description"
placeholder="Add a description"
Expand All @@ -59,6 +64,7 @@ import { ref, watch } from 'vue';
import TeraInput from '@/components/widgets/tera-input.vue';
import AutoComplete from 'primevue/autocomplete';
import type { ModelPartItem } from '@/types/Model';
import { stringToLatexExpression } from '@/services/model';
import type { DKG } from '@/types/Types';
import { getCurieFromGroundingIdentifier, getNameOfCurieCached, searchCuriesEntities } from '@/services/concept';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@
<Column field="downstream_stock" header="Downstream stock" />
<Column field="rate_expression" header="Rate expression">
<template #body="{ data }">
<katex-element v-if="data.rate_expression" :expression="data.rate_expression" :throw-on-error="false" />
<katex-element
v-if="data.rate_expression"
:expression="stringToLatexExpression(data.rate_expression)"
:throw-on-error="false"
/>
<template v-else>--</template>
</template>
</Column>
Expand Down Expand Up @@ -122,6 +126,7 @@ import AccordionTab from 'primevue/accordiontab';
import { computed } from 'vue';
import { Dictionary } from 'vue-gtag';
import { getCurieUrl } from '@/services/concept';
import { stringToLatexExpression } from '@/services/model';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import type { MiraModel, MiraTemplateParams, ObservableSummary } from '@/model-representation/mira/mira-common';
Expand Down
20 changes: 20 additions & 0 deletions packages/client/hmi-client/src/services/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,23 @@ export function isInitial(obj: Initial | ModelParameter | null): obj is Initial
export function isModelParameter(obj: Initial | ModelParameter | null): obj is ModelParameter {
return obj !== null && 'id' in obj;
}

export function stringToLatexExpression(expression: string): string {
// Wrap everything after the first underscore in {} for each variable
// and add a \ before subsequent underscores
let latexExpression = expression.replace(/(_)([a-zA-Z0-9_]+)/g, (_match, p1, p2) => {
// Replace subsequent underscores in p2 with \_
const modifiedP2 = p2.replace(/_/g, '\\_');
return `${p1}{${modifiedP2}}`;
});

// (Unsure about this) Convert * to space (implicit multiplication) for LaTeX
// latexExpression = latexExpression.replace(/\*/g, ' ');

// Convert ^ to LaTeX superscript notation
latexExpression = latexExpression.replace(/\^([a-zA-Z0-9]+)/g, '^{$1}');

// Detect and convert fractions a/b to \frac{a}{b}
latexExpression = latexExpression.replace(/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)/g, '\\frac{$1}{$2}');
return latexExpression;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, expect, it } from 'vitest';
import { stringToLatexExpression } from '@/services/model';

describe('stringToLatexExpression', () => {
it('should wrap variables after underscores in {} and escape subsequent underscores', () => {
const expression = 'x_variable';
const expected = 'x_{variable}';
const result = stringToLatexExpression(expression);
expect(result).toEqual(expected);
});

it('should convert ^ to LaTeX superscript notation', () => {
const expression = 'x^2';
const expected = 'x^{2}';
const result = stringToLatexExpression(expression);
expect(result).toEqual(expected);
});

it('should detect and convert fractions a/b to \\frac{a}{b}', () => {
const expression = '1/2';
const expected = '\\frac{1}{2}';
const result = stringToLatexExpression(expression);
expect(result).toEqual(expected);
});

it('should handle the expression I_unvaccinated^2*NPI_mult*S_unvaccinated*beta/N', () => {
const expression = 'I_unvaccinated^2*NPI_mult*S_unvaccinated*beta/N';
const expected = 'I_{unvaccinated}^{2}*NPI_{mult}*S_{unvaccinated}*\\frac{beta}{N}';
const result = stringToLatexExpression(expression);
expect(result).toEqual(expected);
});
});

0 comments on commit cd820e7

Please sign in to comment.