# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---
# ## Initialization
# +
import spacy
from chemdataextractor import Document
from chemdataextractor.model import Compound
from chemdataextractor.doc import Paragraph, Heading
# -
# ## Playing with two different synthetic paragraphs
#
# `text` is from the Angewandte paper out of Stanford.  The synthetic paragraph is not very straightforward.
#
# `text2` is taken from the Methods section of the Nature Nanotech paper out of the University of Toronto.  The synthetic portion is much more straightforward in this case.
#
# `text3` is taken from the Methods section of the Nature Materials paper from Korea.  The synthesis portion is somewhat readable, but lies in between the previous two texts.
nlp = spacy.load('en_core_web_sm') # Load English dictionary from spaCy
# +
# Angewandte
#text = 'Layered perovskites can be structurally derived from the 3D analogue by slicing along specific crystallographic planes.4 The interlayer separation and thickness of the inorganic layers can be controlled through the choice of organic cations.5 The inorganic layers of most layered perovskites comprise a single sheet (n=1) of corner‐sharing metal–halide octahedra sandwiching layers of organic cations.4 These 2D materials do not have electronic properties typically associated with good solar‐cell absorbers. Along with larger bandgaps compared to the 3D analogue (n=∞), the spatial confinement of the 2D structure and dielectric mismatch between organic and inorganic layers lead to strongly bound excitons with low mobility.6 Such tightly bound excitons are difficult to dissociate into free carriers at room temperature and the localized charge carriers are unlikely to reach the electron/hole selective contacts in a typical solar‐cell geometry. To access the more favorable electronic properties of the 3D structure, we sought an intermediate structure between the n=1 and n=∞ materials. We synthesized the n=3 member of the series (PEA)2(MA)n−1[PbnI3n+1] (n=number of Pb–I sheets in each inorganic layer), by combining (PEA)I, (MA)I, and PbI2 in a 2:2:3 stoichiometric ratio in a solvent mixture of nitromethane/acetone. Slow solvent evaporation afforded dark red crystals of (PEA)2(MA)2[Pb3I10] (1), the first crystallographically characterized n=3 lead perovskite (Figure 1).'
# -
# Nature Nanotechnology
text2 = "Perovskite film fabrication Different dimensionality perovskite [(PEA)2(CH3NH3)n−1PbnI3n+1] solutions was prepared by dissolving stoichiometric quantities of lead iodide (PbI2), methylammonium idodide (MAI) and PEAI in a dimethyl sulfoxide (DMSO)/ɣ-butyrolactone (1:1 volume ratio) mixture at 70 °C for 1 h with continuous stirring. The resulting solution was then filtered through a polytetrafluoroethylene (PTFE) filter (0.2 µm). The resulting solution was spin-coated onto the substrate via a two-step process at 1,000 r.p.m. and 5,000 r.p.m. for 10 s and 60 s, respectively. During the second spin step, 100 µl of chlorobenzene were poured onto the substrate. The resulting films were then annealed at 70 °C for 10 min to improve crystallization."
# Nature Materials
text3 = u"A dense blocking layer of TiO2 (bl-TiO2, ∼70 nm in thickness) was deposited onto a F-doped SnO2 (FTO, Pilkington, TEC8) substrate by spray pyrolysis, using a 20 mM titanium diisopropoxide bis(acetylacetonate) solution (Aldrich) at 450 °C to prevent direct contact between the FTO and the hole-conducting layer. A 200–300-nm-thick mesoporous TiO2 (particle size: about 50 nm, crystalline phase: anatase) film was spin-coated onto the bl-TiO2/FTO substrate using home-made pastes14 and calcining at 500 °C for 1 h in air to remove organic components. CH3NH3I (MAI) and CH3NH3Br (MABr) were first synthesized by reacting 27.86 ml CH3NH2 (40% in methanol, Junsei Chemical) and 30 ml HI (57 wt% in water, Aldrich) or 44 ml HBr (48 wt% in water, Aldrich) in a 250 ml round-bottom flask at 0 °C for 4 h with stirring, respectively. The precipitate was recovered by evaporation at 55 °C for 1 h. MAI and MABr were dissolved in ethanol, recrystallized from diethyl ether, and dried at 60 °C in a vacuum oven for 24 h. The prepared MAI and MABr powders, PbI2 (Aldrich) and PbBr2 (Aldrich) for 0.8 M MAPb(I1 − xBrx)3 (x  =  0.1–0.15) solution were stirred in a mixture of GBL and DMSO (7:3 v/v) at 60 °C for 12 h. The resulting solution was coated onto the mp-TiO2/bl-TiO2/FTO substrate by a consecutive two-step spin-coating process at 1,000 and 5,000 r.p.m for 10 and 20 s, respectively. During the second spin-coating step, the substrate (around 1 cm × 1 cm) was treated with toluene drop-casting. A detailed time-rotation profile for the spin-coating is represented in Supplementary Fig. 1c. The substrate was dried on a hot plate at 100 °C for 10 min. A solution of poly(triarylamine) (15 mg, PTAA, EM Index, Mw  =  17,500 g mol−1) in toluene (1.5 ml) was mixed with 15 μl of a solution of lithium bistrifluoromethanesulphonimidate (170 mg) in acetonitrile (1 ml) and 7.5 μl 4-tert-butylpyridine and spin-coated on the MAPb(I1 − xBrx)3 (x  =  0.1–0.15)/mp-TiO2/bl-TiO2/FTO substrate at 3,000 r.p.m for 30 s. Finally, a Au counterelectrode was deposited by thermal evaporation. The active area of this electrode was fixed at 0.16 cm2."
# ### Nature Materials paragraph: Playing with ChemDataExtractor
# Formatting the Nature Nanotech paragraph according to ChemDataExtractor
nat = Document(Heading(u'Solar cell fabrication'), Paragraph(text3))
nat.records.serialize()
nat.paragraphs[0].pos_tagged_tokens
# +
sp_nm = nlp(text3)
for token in sp_nm:
    print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
          token.shape_, token.is_alpha, token.is_stop)
# +
#sp_ang = nlp(text)
#for token in sp_ang:
#    print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
#          token.shape_, token.is_alpha, token.is_stop)
# +
#angew = Document(text)
# +
#angew
# -
# ## Defining Custom Properties in CDE
#
# I'm using mostly code from the CDE notebook to define a new property for spin-coating step(s).
nat
# +
from chemdataextractor.model import BaseModel, StringType, ListType, ModelType
class SpinCoat(BaseModel):
    value = StringType()
    units = StringType()
    
Compound.spin_coat_spd = ListType(ModelType(SpinCoat))
# +
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import logging
#from chemdataextractor.model.cem import chemical_name
# +
# logging.getLogger?
# -
# hao 2 edit 2 make more useful
def extract_units(tokens, start, result):
    """Extract units from bracketed after nu"""
    for e in result:
        for child in e.iter():
            if 'rpm' or 'r.p.m.' or 'r.p.m' or 'rcf' or 'r.c.f.' in child.text:
                return [E('units', 'whatever the unit is')]
    return []

# +
import re
from chemdataextractor.parse import R, I, W, Optional, merge, ZeroOrMore, OneOrMore
from chemdataextractor.parse.cem import chemical_name
solvent = (I('GBL') | R('γ-[Bb]utyrolactone') | chemical_name('solvent'))
units = Optional(R(u'^\b?r(\.)?p(\.)?m(\.)?\b?$') | R(u'^r(\.)?c(\.)?f(\.)?$') | R(u'^([x×]?)(\s?)?g$'))(u'units')
#Optional(W('/')).hide() + W(u'^r\.?p\.?m\.?')
#R('^(re)?crystalli[sz](ation|ed)$', re.I)
value = R(u'^\d+(,\d+)?$')(u'value')
spinspd = (value + units)(u'spinspd')
from chemdataextractor.parse.base import BaseParser
from chemdataextractor.utils import first
def extract_units(tokens, start, result):
    """Extract units from bracketed after nu"""
    for e in result:
        for child in e.iter():
            if R(u'^\b?r(\.)?p(\.)?m(\.)?\b?$') in child.text:
                return [E('units', 'rpm')]
            elif R(u'^r(\.)?c(\.)?f(\.)?$') in child.text:
                return [E('units', 'rcf')]
            elif R(u'^([x×]?)(\s?)?g$') in child.text:
                return [E('units', 'g')]
    return []
class SpinCoatParser(BaseParser):
    root = spinspd
    def interpret(self, result, start, end):
        compound = Compound(
            spin_coat_spd=[
                SpinCoat(
                    solvent=first(result.xpath('./solvent/text()')),
                    value=first(result.xpath('./value/text()')),
                    units=first(result.xpath('./units/text()'))
                )
            ]
        )
        yield compound

# -
Paragraph.parsers = [SpinCoatParser()]
# +
d = Document(u'The resulting solution was coated onto the mp-TiO2/bl-TiO2/FTO substrate by a consecutive two-step spin-coating process at 1,000 and 5,000 r.p.m for 10 and 20 s, respectively.')
d.records.serialize()
# -