eta =~ y1 + y2 + y3it reads as "latent variable eta is measured by y1, y2, y3". However, the phrase "measured by" appears to be a bit of a misnomer, as in SEM software is usually the converse: "y1, y2, y3 are measured by eta". In fact, what the measurement operator does, is says that the latent factor regresses onto some observable variables. In semopy, under the hood (as been explained in a greater detail in Syntax part of the tutorial - see DEFINE(latent) command), "=~" is just a syntax sugar that switches the left part and the right parts of the equation and turns "=~" into "~", while pushing variables from the left part into a class of latent variables. Hence arrows are drawn correctly, and inspect provides a valid representation of parameter estimates. Also, report attempts to restore "=~" operation and outputs it together with an inspect DataFrame.
ModelMeans can be useful if you want to have a greater degree of certainty that p-values for regressions of non-normal exogenous variables are sensible. You can also constrain intercepts with it, if you need to. Note that estimating intercepts can be done with Model too via estimate_means function, however it is done separately and we can't impose any constraints.
ModelEffects comes in handy when you know that is a population structure that violates the assumption of independent observations and you you have a ready-to-go covariance-between-individuals matrix. That's very common in bioinormatics and in GWAS specifically, where that covariance matrix is computed from genotypes.
ModelGeneralizedEffects, as the name suggests, is similar to ModelEffects. Two big differences are: a) it can model multiple causes of population structure; b) one does not need to know a precise covariance-across-individuals matrix - the knowledge of its structure is enough. It can be used for modeling spatial data, temporal data or even both. People who are familar with gaussian processes might realize that a more suiting name for this model is ModelGaussianProcess.
eta =~ a*y1 + b*y2 + c*y3In most realistic scenarios, however, you don't need this.
model.fit(data, cov=data.cov())There is a chance that this will change in future versions and semopy will use an unbiased estimate by default.
logging.disable()You can also redirect it to file or some other output stream, see its documentation.