Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
FROM python:3
FROM python:3.9.6-bullseye

#Update the image we start from and install all latex stuf and dependencies for mupdf
RUN apt-get update -y\
&& apt-get install texlive-full -y\
&& apt-get install graphviz -y\
&& apt-get install libx11-dev mesa-common-dev libgl1-mesa-dev -y\
&& rm -rf /var/lib/apt/lists/*


#Copy varylatex files to the image
COPY . /varylatex
WORKDIR /varylatex

#Install mupdf 1.18.16 version
RUN sh mupdf_install.sh

#Install varylatex python dependencies
RUN pip install -r requirements.txt

VOLUME /varylatex/build
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ You can also run the app within a `Docker` container : to do this, install docke
sudo docker build -t varylatex .
# Create the container
sudo docker run -it --rm -p 5000:5000 varylatex
# In case you want to rely on a prebuild image there is one at https://hub.docker.com/r/diversolab/varylatex
```
And inside the container you can run
```bash
Expand Down
40 changes: 29 additions & 11 deletions main_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from vary.model.generation.generate import generate_random, generate_pdf
from vary.model.generation.compile import generate_bbl
from vary.model.decision_trees.analysis import decision_tree
from vary.model.feature_models.fm_operations import getFeatureHeaders, getProducts, getRandomProduct


if __name__ == "__main__":
parser = argparse.ArgumentParser()
Expand All @@ -31,6 +33,7 @@
It needs to have a 'values.json' file and the document must include 'macros' and 'values'")
parser.add_argument("-c", "--config", help="Generate a specific PDF from a config JSON string")
parser.add_argument("-p", "--maxpages", type=int, help="The maximum amount of pages accepted for the document")
parser.add_argument("-fm","--feature-model", action="store_true", help="This is relying on Famapy to generate the set of configurations. Now this allows contratins. However, a translation to the varylatex format has to be manually done" )
args = parser.parse_args()

document_path = args.source
Expand All @@ -42,18 +45,25 @@

temp_path = create_temporary_copy(document_path)

conf_source_path = os.path.join(document_path, "variables.json")
with open(conf_source_path) as f:
conf_source = json.load(f)
if args.feature_model :
conf_source_path = os.path.join(document_path, "feature_model.uvl")
#DataFrame init
cols = getFeatureHeaders(conf_source_path)
df = pd.DataFrame(columns=cols)

# DataFrame initialisation
cols = conf_source["booleans"] + \
list(conf_source["numbers"].keys()) + \
list(conf_source["enums"].keys()) + \
list(flatten(conf_source["choices"])) + \
["nbPages", "space"]
df = pd.DataFrame(columns=cols)
else:
conf_source_path = os.path.join(document_path, "variables.json")
with open(conf_source_path) as f:
conf_source = json.load(f)

# DataFrame initialisation
cols = conf_source["booleans"] + \
list(conf_source["numbers"].keys()) + \
list(conf_source["enums"].keys()) + \
list(flatten(conf_source["choices"])) + \
["nbPages", "space"]
df = pd.DataFrame(columns=cols)
print(df)
file_path = os.path.join(temp_path, filename)
inject_space_indicator(file_path)
# LaTeX bbl pregeneration
Expand All @@ -67,9 +77,17 @@
pdf_name = filename+".pdf"
shutil.copyfile(os.path.join(temp_path, pdf_name), os.path.join(args.output, pdf_name))
else:
if args.feature_model:
products = getProducts(conf_source_path)
for i in range(args.generations):
row = generate_random(conf_source, filename, temp_path)
if args.feature_model:
row = getRandomProduct(products)
row = generate_pdf(row, filename, temp_path)
else:
row = generate_random(conf_source, filename, temp_path)

df = df.append(row, ignore_index=True)

if args.verbose:
print(f"Doc {i} generated")

Expand Down
7 changes: 7 additions & 0 deletions mupdf_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#\bin\sh
wget -O mupdf.tar.gz https://mupdf.com/downloads/archive/mupdf-1.18.0-source.tar.gz ;
tar -xzf mupdf.tar.gz
ls
cd mupdf-1.18.0-source
make
make HAVE_X11=no HAVE_GLUT=no prefix=/usr/local install
7 changes: 5 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Flask==1.1.2
intervaltree==3.0.2
PyMuPDF==1.17.1
PyMuPDF==1.18.16
pandas==1.0.5
requests==2.22.0
scikit-learn==0.23.1
scikit-learn==0.23.1
famapy==0.5.1
famapy-fm==0.5.0
famapy-sat==0.5.1
38 changes: 38 additions & 0 deletions vary/example/fse/feature_model.uvl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
imports

features
Paper { abstract }
optional
PL_FOOTNOTE
ACK
LONG_AFFILIATION
EMAIL
LONG_ACK
mandatory
JS_STYLE { abstract }
alternative
tiny
scriptsize
footnotesize
CHOICES { abstract }
or
PARAGRAPH_ACK
BOLD_ACK
vspace_bib { abstract }
alternative
vspace_ONE
vspace_FIVE
vspace_TWO
bref_size { abstract }
alternative
bref_size_POINT_SEVEN
bref_size_ONE
bref_size_TWO
cserver_size { abstract }
alternative
cserver_size_POINT_SIX
cserver_size_POINT_NINE
cserver_size_TWO

constraints

93 changes: 93 additions & 0 deletions vary/model/feature_models/fm_operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from famapy.core.discover import DiscoverMetamodels # This loads the tool in the python execution eviroment
import random

def transcodeProducts(rawProducts):
transcoddedRes=[]
for result in rawProducts:
r={}
if "PL_FOOTNOTE" in result:
r["PL_FOOTNOTE"]=True
else:
r["PL_FOOTNOTE"]=False

if "ACK" in result:
r["ACK"]=True
else:
r["ACK"]=False

if "LONG_AFFILIATION" in result:
r["LONG_AFFILIATION"]=True
else:
r["LONG_AFFILIATION"]=False

if "EMAIL" in result:
r["EMAIL"]=True
else:
r["EMAIL"]=False

if "LONG_ACK" in result:
r["LONG_ACK"]=True
else:
r["LONG_ACK"]=False

if "vspace_ONE" in result:
r["vspace"]=1
elif "vspace_FIVE" in result:
r["vspace"]=5
elif "vspace_TWO" in result:
r["vspace"]=2
else:
raise Exception

if "bref_size_POINT_SEVEN" in result:
r["bref_size"]=0.7
elif "bref_size_ONE" in result:
r["bref_size"]=1
elif "bref_size_TWO" in result:
r["bref_size"]=2
else:
raise Exception

if "cserver_size_POINT_SIX" in result:
r["cserver_size"]=0.6
elif "cserver_size_POINT_NINE" in result:
r["cserver_size"]=0.9
elif "cserver_size_TWO" in result:
r["cserver_size"]=2
else:
raise Exception

if "tiny" in result:
r["js_style"]="\\tiny"
elif "scriptsize" in result:
r["js_style"]="\\scriptsize"
elif "footnotesize" in result:
r["js_style"]="\\footnotesize"

if "PARAGRAPH_ACK" in result:
r["PARAGRAPH_ACK"]=True
else:
r["PARAGRAPH_ACK"]=False

if "BOLD_ACK" in result:
r["BOLD_ACK"]=True
else:
r["BOLD_ACK"]=False

transcoddedRes.append(r)
return transcoddedRes

def getProducts(path):
dm = DiscoverMetamodels()
results = dm.use_operation_from_file("Products", path) # This launch the operation and stores the result on the result variable
results = transcodeProducts(results)
return results


def getRandomProduct(products):
n = random.randint(0,len(products)-1)
return products[n]

def getFeatureHeaders(path):
#This is still hardcoded for the example. TODO See how to generalize
return ["PL_FOOTNOTE", "ACK", "LONG_AFFILIATION", "EMAIL", "LONG_ACK", "vspace_bib", "bref_size", "cserver_size", "js_style", "PARAGRAPH_ACK", "BOLD_ACK", "nbPages", "space"]
4 changes: 1 addition & 3 deletions vary/model/generation/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from vary.model.generation.compile import compile_latex
from vary.model.generation.analyze_pdf import page_count


def random_config(conf_source, fixed_values={}):
"""
Generates a config dictionnary based on the range of values provided from a dictionnary containing the following keys :
Expand Down Expand Up @@ -81,8 +80,7 @@ def generate_random(conf_source, filename, temp_path, fixes_values={}):
"""
config = random_config(conf_source, fixes_values)
return generate_pdf(config, filename, temp_path)



def generate_pdfs(filename, source, output, nb_gens, reset=True, fixed_values = {}):
"""
Creates as many PDFs as specified with nb_gens, from a random config based on conf_source, and calculate
Expand Down